mirror of https://github.com/django/django.git
Fixed #31716 -- Fixed detection of console scripts in autoreloader on Windows.
This commit is contained in:
parent
7f4db2d82b
commit
8a902b7ee6
|
@ -207,12 +207,26 @@ def get_child_arguments():
|
||||||
on reloading.
|
on reloading.
|
||||||
"""
|
"""
|
||||||
import django.__main__
|
import django.__main__
|
||||||
|
django_main_path = Path(django.__main__.__file__)
|
||||||
|
py_script = Path(sys.argv[0])
|
||||||
|
|
||||||
args = [sys.executable] + ['-W%s' % o for o in sys.warnoptions]
|
args = [sys.executable] + ['-W%s' % o for o in sys.warnoptions]
|
||||||
if sys.argv[0] == django.__main__.__file__:
|
if py_script == django_main_path:
|
||||||
# The server was started with `python -m django runserver`.
|
# The server was started with `python -m django runserver`.
|
||||||
args += ['-m', 'django']
|
args += ['-m', 'django']
|
||||||
args += sys.argv[1:]
|
args += sys.argv[1:]
|
||||||
|
elif not py_script.exists():
|
||||||
|
# sys.argv[0] may not exist for several reasons on Windows.
|
||||||
|
# It may exist with a .exe extension or have a -script.py suffix.
|
||||||
|
exe_entrypoint = py_script.with_suffix('.exe')
|
||||||
|
if exe_entrypoint.exists():
|
||||||
|
# Should be executed directly, ignoring sys.executable.
|
||||||
|
return [exe_entrypoint, *sys.argv[1:]]
|
||||||
|
script_entrypoint = py_script.with_name('%s-script.py' % py_script.name)
|
||||||
|
if script_entrypoint.exists():
|
||||||
|
# Should be executed as usual.
|
||||||
|
return [*args, script_entrypoint, *sys.argv[1:]]
|
||||||
|
raise RuntimeError('Script %s does not exist.' % py_script)
|
||||||
else:
|
else:
|
||||||
args += sys.argv
|
args += sys.argv
|
||||||
return args
|
return args
|
||||||
|
|
|
@ -14,6 +14,7 @@ from pathlib import Path
|
||||||
from subprocess import CompletedProcess
|
from subprocess import CompletedProcess
|
||||||
from unittest import mock, skip, skipIf
|
from unittest import mock, skip, skipIf
|
||||||
|
|
||||||
|
import django.__main__
|
||||||
from django.apps.registry import Apps
|
from django.apps.registry import Apps
|
||||||
from django.test import SimpleTestCase
|
from django.test import SimpleTestCase
|
||||||
from django.test.utils import extend_sys_path
|
from django.test.utils import extend_sys_path
|
||||||
|
@ -153,6 +154,55 @@ class TestIterModulesAndFiles(SimpleTestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestChildArguments(SimpleTestCase):
|
||||||
|
@mock.patch('sys.argv', [django.__main__.__file__, 'runserver'])
|
||||||
|
@mock.patch('sys.warnoptions', [])
|
||||||
|
def test_run_as_module(self):
|
||||||
|
self.assertEqual(
|
||||||
|
autoreload.get_child_arguments(),
|
||||||
|
[sys.executable, '-m', 'django', 'runserver']
|
||||||
|
)
|
||||||
|
|
||||||
|
@mock.patch('sys.argv', [__file__, 'runserver'])
|
||||||
|
@mock.patch('sys.warnoptions', ['error'])
|
||||||
|
def test_warnoptions(self):
|
||||||
|
self.assertEqual(
|
||||||
|
autoreload.get_child_arguments(),
|
||||||
|
[sys.executable, '-Werror', __file__, 'runserver']
|
||||||
|
)
|
||||||
|
|
||||||
|
@mock.patch('sys.warnoptions', [])
|
||||||
|
def test_exe_fallback(self):
|
||||||
|
tmpdir = tempfile.TemporaryDirectory()
|
||||||
|
self.addCleanup(tmpdir.cleanup)
|
||||||
|
exe_path = Path(tmpdir.name) / 'django-admin.exe'
|
||||||
|
exe_path.touch()
|
||||||
|
with mock.patch('sys.argv', [exe_path.with_suffix(''), 'runserver']):
|
||||||
|
self.assertEqual(
|
||||||
|
autoreload.get_child_arguments(),
|
||||||
|
[exe_path, 'runserver']
|
||||||
|
)
|
||||||
|
|
||||||
|
@mock.patch('sys.warnoptions', [])
|
||||||
|
def test_entrypoint_fallback(self):
|
||||||
|
tmpdir = tempfile.TemporaryDirectory()
|
||||||
|
self.addCleanup(tmpdir.cleanup)
|
||||||
|
script_path = Path(tmpdir.name) / 'django-admin-script.py'
|
||||||
|
script_path.touch()
|
||||||
|
with mock.patch('sys.argv', [script_path.with_name('django-admin'), 'runserver']):
|
||||||
|
self.assertEqual(
|
||||||
|
autoreload.get_child_arguments(),
|
||||||
|
[sys.executable, script_path, 'runserver']
|
||||||
|
)
|
||||||
|
|
||||||
|
@mock.patch('sys.argv', ['does-not-exist', 'runserver'])
|
||||||
|
@mock.patch('sys.warnoptions', [])
|
||||||
|
def test_raises_runtimeerror(self):
|
||||||
|
msg = 'Script does-not-exist does not exist.'
|
||||||
|
with self.assertRaisesMessage(RuntimeError, msg):
|
||||||
|
autoreload.get_child_arguments()
|
||||||
|
|
||||||
|
|
||||||
class TestCommonRoots(SimpleTestCase):
|
class TestCommonRoots(SimpleTestCase):
|
||||||
def test_common_roots(self):
|
def test_common_roots(self):
|
||||||
paths = (
|
paths = (
|
||||||
|
@ -360,6 +410,9 @@ class RestartWithReloaderTests(SimpleTestCase):
|
||||||
return mock_call
|
return mock_call
|
||||||
|
|
||||||
def test_manage_py(self):
|
def test_manage_py(self):
|
||||||
|
script = Path('manage.py')
|
||||||
|
script.touch()
|
||||||
|
self.addCleanup(script.unlink)
|
||||||
argv = ['./manage.py', 'runserver']
|
argv = ['./manage.py', 'runserver']
|
||||||
mock_call = self.patch_autoreload(argv)
|
mock_call = self.patch_autoreload(argv)
|
||||||
autoreload.restart_with_reloader()
|
autoreload.restart_with_reloader()
|
||||||
|
|
Loading…
Reference in New Issue