summaryrefslogtreecommitdiff
path: root/tests/utils_tests/test_autoreload.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/utils_tests/test_autoreload.py')
-rw-r--r--tests/utils_tests/test_autoreload.py474
1 files changed, 269 insertions, 205 deletions
diff --git a/tests/utils_tests/test_autoreload.py b/tests/utils_tests/test_autoreload.py
index 9b318722c0..c50d141cf3 100644
--- a/tests/utils_tests/test_autoreload.py
+++ b/tests/utils_tests/test_autoreload.py
@@ -26,7 +26,8 @@ from django.test.utils import extend_sys_path
from django.utils import autoreload
from django.utils.autoreload import WatchmanUnavailable
-from .test_module import __main__ as test_main, main_module as test_main_module
+from .test_module import __main__ as test_main
+from .test_module import main_module as test_main_module
from .utils import on_macos_with_hfs
@@ -45,18 +46,26 @@ class TestIterModulesAndFiles(SimpleTestCase):
resolved_filename = filename.resolve(strict=True)
self.clear_autoreload_caches()
# Test uncached access
- self.assertIn(resolved_filename, list(autoreload.iter_all_python_module_files()))
+ self.assertIn(
+ resolved_filename, list(autoreload.iter_all_python_module_files())
+ )
# Test cached access
- self.assertIn(resolved_filename, list(autoreload.iter_all_python_module_files()))
+ self.assertIn(
+ resolved_filename, list(autoreload.iter_all_python_module_files())
+ )
self.assertEqual(autoreload.iter_modules_and_files.cache_info().hits, 1)
def assertFileNotFound(self, filename):
resolved_filename = filename.resolve(strict=True)
self.clear_autoreload_caches()
# Test uncached access
- self.assertNotIn(resolved_filename, list(autoreload.iter_all_python_module_files()))
+ self.assertNotIn(
+ resolved_filename, list(autoreload.iter_all_python_module_files())
+ )
# Test cached access
- self.assertNotIn(resolved_filename, list(autoreload.iter_all_python_module_files()))
+ self.assertNotIn(
+ resolved_filename, list(autoreload.iter_all_python_module_files())
+ )
self.assertEqual(autoreload.iter_modules_and_files.cache_info().hits, 1)
def temporary_file(self, filename):
@@ -72,11 +81,11 @@ class TestIterModulesAndFiles(SimpleTestCase):
"""
When a file is added, it's returned by iter_all_python_module_files().
"""
- filename = self.temporary_file('test_deleted_removed_module.py')
+ filename = self.temporary_file("test_deleted_removed_module.py")
filename.touch()
with extend_sys_path(str(filename.parent)):
- self.import_and_cleanup('test_deleted_removed_module')
+ self.import_and_cleanup("test_deleted_removed_module")
self.assertFileFound(filename.absolute())
@@ -85,13 +94,13 @@ class TestIterModulesAndFiles(SimpleTestCase):
When a file containing an error is imported in a function wrapped by
check_errors(), gen_filenames() returns it.
"""
- filename = self.temporary_file('test_syntax_error.py')
+ filename = self.temporary_file("test_syntax_error.py")
filename.write_text("Ceci n'est pas du Python.")
with extend_sys_path(str(filename.parent)):
try:
with self.assertRaises(SyntaxError):
- autoreload.check_errors(import_module)('test_syntax_error')
+ autoreload.check_errors(import_module)("test_syntax_error")
finally:
autoreload._exception = None
self.assertFileFound(filename)
@@ -101,12 +110,12 @@ class TestIterModulesAndFiles(SimpleTestCase):
Since Python may raise arbitrary exceptions when importing code,
check_errors() must catch Exception, not just some subclasses.
"""
- filename = self.temporary_file('test_exception.py')
- filename.write_text('raise Exception')
+ filename = self.temporary_file("test_exception.py")
+ filename.write_text("raise Exception")
with extend_sys_path(str(filename.parent)):
try:
with self.assertRaises(Exception):
- autoreload.check_errors(import_module)('test_exception')
+ autoreload.check_errors(import_module)("test_exception")
finally:
autoreload._exception = None
self.assertFileFound(filename)
@@ -116,48 +125,54 @@ class TestIterModulesAndFiles(SimpleTestCase):
Modules imported from zipped files have their archive location included
in the result.
"""
- zip_file = self.temporary_file('zip_import.zip')
- with zipfile.ZipFile(str(zip_file), 'w', zipfile.ZIP_DEFLATED) as zipf:
- zipf.writestr('test_zipped_file.py', '')
+ zip_file = self.temporary_file("zip_import.zip")
+ with zipfile.ZipFile(str(zip_file), "w", zipfile.ZIP_DEFLATED) as zipf:
+ zipf.writestr("test_zipped_file.py", "")
with extend_sys_path(str(zip_file)):
- self.import_and_cleanup('test_zipped_file')
+ self.import_and_cleanup("test_zipped_file")
self.assertFileFound(zip_file)
def test_bytecode_conversion_to_source(self):
""".pyc and .pyo files are included in the files list."""
- filename = self.temporary_file('test_compiled.py')
+ filename = self.temporary_file("test_compiled.py")
filename.touch()
- compiled_file = Path(py_compile.compile(str(filename), str(filename.with_suffix('.pyc'))))
+ compiled_file = Path(
+ py_compile.compile(str(filename), str(filename.with_suffix(".pyc")))
+ )
filename.unlink()
with extend_sys_path(str(compiled_file.parent)):
- self.import_and_cleanup('test_compiled')
+ self.import_and_cleanup("test_compiled")
self.assertFileFound(compiled_file)
def test_weakref_in_sys_module(self):
"""iter_all_python_module_file() ignores weakref modules."""
time_proxy = weakref.proxy(time)
- sys.modules['time_proxy'] = time_proxy
- self.addCleanup(lambda: sys.modules.pop('time_proxy', None))
+ sys.modules["time_proxy"] = time_proxy
+ self.addCleanup(lambda: sys.modules.pop("time_proxy", None))
list(autoreload.iter_all_python_module_files()) # No crash.
def test_module_without_spec(self):
- module = types.ModuleType('test_module')
+ module = types.ModuleType("test_module")
del module.__spec__
- self.assertEqual(autoreload.iter_modules_and_files((module,), frozenset()), frozenset())
+ self.assertEqual(
+ autoreload.iter_modules_and_files((module,), frozenset()), frozenset()
+ )
def test_main_module_is_resolved(self):
- main_module = sys.modules['__main__']
+ main_module = sys.modules["__main__"]
self.assertFileFound(Path(main_module.__file__))
def test_main_module_without_file_is_not_resolved(self):
- fake_main = types.ModuleType('__main__')
- self.assertEqual(autoreload.iter_modules_and_files((fake_main,), frozenset()), frozenset())
+ fake_main = types.ModuleType("__main__")
+ self.assertEqual(
+ autoreload.iter_modules_and_files((fake_main,), frozenset()), frozenset()
+ )
def test_path_with_embedded_null_bytes(self):
for path in (
- 'embedded_null_byte\x00.py',
- 'di\x00rectory/embedded_null_byte.py',
+ "embedded_null_byte\x00.py",
+ "di\x00rectory/embedded_null_byte.py",
):
with self.subTest(path=path):
self.assertEqual(
@@ -167,108 +182,105 @@ class TestIterModulesAndFiles(SimpleTestCase):
class TestChildArguments(SimpleTestCase):
- @mock.patch.dict(sys.modules, {'__main__': django.__main__})
- @mock.patch('sys.argv', [django.__main__.__file__, 'runserver'])
- @mock.patch('sys.warnoptions', [])
- @mock.patch('sys._xoptions', {})
+ @mock.patch.dict(sys.modules, {"__main__": django.__main__})
+ @mock.patch("sys.argv", [django.__main__.__file__, "runserver"])
+ @mock.patch("sys.warnoptions", [])
+ @mock.patch("sys._xoptions", {})
def test_run_as_module(self):
self.assertEqual(
autoreload.get_child_arguments(),
- [sys.executable, '-m', 'django', 'runserver']
+ [sys.executable, "-m", "django", "runserver"],
)
- @mock.patch.dict(sys.modules, {'__main__': test_main})
- @mock.patch('sys.argv', [test_main.__file__, 'runserver'])
- @mock.patch('sys.warnoptions', [])
- @mock.patch('sys._xoptions', {})
+ @mock.patch.dict(sys.modules, {"__main__": test_main})
+ @mock.patch("sys.argv", [test_main.__file__, "runserver"])
+ @mock.patch("sys.warnoptions", [])
+ @mock.patch("sys._xoptions", {})
def test_run_as_non_django_module(self):
self.assertEqual(
autoreload.get_child_arguments(),
- [sys.executable, '-m', 'utils_tests.test_module', 'runserver'],
+ [sys.executable, "-m", "utils_tests.test_module", "runserver"],
)
- @mock.patch.dict(sys.modules, {'__main__': test_main_module})
- @mock.patch('sys.argv', [test_main.__file__, 'runserver'])
- @mock.patch('sys.warnoptions', [])
- @mock.patch('sys._xoptions', {})
+ @mock.patch.dict(sys.modules, {"__main__": test_main_module})
+ @mock.patch("sys.argv", [test_main.__file__, "runserver"])
+ @mock.patch("sys.warnoptions", [])
+ @mock.patch("sys._xoptions", {})
def test_run_as_non_django_module_non_package(self):
self.assertEqual(
autoreload.get_child_arguments(),
- [sys.executable, '-m', 'utils_tests.test_module.main_module', 'runserver'],
+ [sys.executable, "-m", "utils_tests.test_module.main_module", "runserver"],
)
- @mock.patch('__main__.__spec__', None)
- @mock.patch('sys.argv', [__file__, 'runserver'])
- @mock.patch('sys.warnoptions', ['error'])
- @mock.patch('sys._xoptions', {})
+ @mock.patch("__main__.__spec__", None)
+ @mock.patch("sys.argv", [__file__, "runserver"])
+ @mock.patch("sys.warnoptions", ["error"])
+ @mock.patch("sys._xoptions", {})
def test_warnoptions(self):
self.assertEqual(
autoreload.get_child_arguments(),
- [sys.executable, '-Werror', __file__, 'runserver']
+ [sys.executable, "-Werror", __file__, "runserver"],
)
- @mock.patch('sys.argv', [__file__, 'runserver'])
- @mock.patch('sys.warnoptions', [])
- @mock.patch('sys._xoptions', {'utf8': True, 'a': 'b'})
+ @mock.patch("sys.argv", [__file__, "runserver"])
+ @mock.patch("sys.warnoptions", [])
+ @mock.patch("sys._xoptions", {"utf8": True, "a": "b"})
def test_xoptions(self):
self.assertEqual(
autoreload.get_child_arguments(),
- [sys.executable, '-Xutf8', '-Xa=b', __file__, 'runserver'],
+ [sys.executable, "-Xutf8", "-Xa=b", __file__, "runserver"],
)
- @mock.patch('__main__.__spec__', None)
- @mock.patch('sys.warnoptions', [])
+ @mock.patch("__main__.__spec__", None)
+ @mock.patch("sys.warnoptions", [])
def test_exe_fallback(self):
with tempfile.TemporaryDirectory() as tmpdir:
- exe_path = Path(tmpdir) / 'django-admin.exe'
+ exe_path = Path(tmpdir) / "django-admin.exe"
exe_path.touch()
- with mock.patch('sys.argv', [exe_path.with_suffix(''), 'runserver']):
+ with mock.patch("sys.argv", [exe_path.with_suffix(""), "runserver"]):
self.assertEqual(
- autoreload.get_child_arguments(),
- [exe_path, 'runserver']
+ autoreload.get_child_arguments(), [exe_path, "runserver"]
)
- @mock.patch('__main__.__spec__', None)
- @mock.patch('sys.warnoptions', [])
- @mock.patch('sys._xoptions', {})
+ @mock.patch("__main__.__spec__", None)
+ @mock.patch("sys.warnoptions", [])
+ @mock.patch("sys._xoptions", {})
def test_entrypoint_fallback(self):
with tempfile.TemporaryDirectory() as tmpdir:
- script_path = Path(tmpdir) / 'django-admin-script.py'
+ script_path = Path(tmpdir) / "django-admin-script.py"
script_path.touch()
- with mock.patch('sys.argv', [script_path.with_name('django-admin'), 'runserver']):
+ with mock.patch(
+ "sys.argv", [script_path.with_name("django-admin"), "runserver"]
+ ):
self.assertEqual(
autoreload.get_child_arguments(),
- [sys.executable, script_path, 'runserver']
+ [sys.executable, script_path, "runserver"],
)
- @mock.patch('__main__.__spec__', None)
- @mock.patch('sys.argv', ['does-not-exist', 'runserver'])
- @mock.patch('sys.warnoptions', [])
+ @mock.patch("__main__.__spec__", None)
+ @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.'
+ msg = "Script does-not-exist does not exist."
with self.assertRaisesMessage(RuntimeError, msg):
autoreload.get_child_arguments()
- @mock.patch('sys.argv', [__file__, 'runserver'])
- @mock.patch('sys.warnoptions', [])
- @mock.patch('sys._xoptions', {})
+ @mock.patch("sys.argv", [__file__, "runserver"])
+ @mock.patch("sys.warnoptions", [])
+ @mock.patch("sys._xoptions", {})
def test_module_no_spec(self):
- module = types.ModuleType('test_module')
+ module = types.ModuleType("test_module")
del module.__spec__
- with mock.patch.dict(sys.modules, {'__main__': module}):
+ with mock.patch.dict(sys.modules, {"__main__": module}):
self.assertEqual(
autoreload.get_child_arguments(),
- [sys.executable, __file__, 'runserver']
+ [sys.executable, __file__, "runserver"],
)
class TestUtilities(SimpleTestCase):
def test_is_django_module(self):
- for module, expected in (
- (zoneinfo, False),
- (sys, False),
- (autoreload, True)
- ):
+ for module, expected in ((zoneinfo, False), (sys, False), (autoreload, True)):
with self.subTest(module=module):
self.assertIs(autoreload.is_django_module(module), expected)
@@ -276,7 +288,7 @@ class TestUtilities(SimpleTestCase):
for module, expected in (
(zoneinfo.__file__, False),
(contextlib.__file__, False),
- (autoreload.__file__, True)
+ (autoreload.__file__, True),
):
with self.subTest(module=module):
self.assertIs(autoreload.is_django_path(module), expected)
@@ -285,20 +297,20 @@ class TestUtilities(SimpleTestCase):
class TestCommonRoots(SimpleTestCase):
def test_common_roots(self):
paths = (
- Path('/first/second'),
- Path('/first/second/third'),
- Path('/first/'),
- Path('/root/first/'),
+ Path("/first/second"),
+ Path("/first/second/third"),
+ Path("/first/"),
+ Path("/root/first/"),
)
results = autoreload.common_roots(paths)
- self.assertCountEqual(results, [Path('/first/'), Path('/root/first/')])
+ self.assertCountEqual(results, [Path("/first/"), Path("/root/first/")])
class TestSysPathDirectories(SimpleTestCase):
def setUp(self):
self._directory = tempfile.TemporaryDirectory()
self.directory = Path(self._directory.name).resolve(strict=True).absolute()
- self.file = self.directory / 'test'
+ self.file = self.directory / "test"
self.file.touch()
def tearDown(self):
@@ -310,7 +322,7 @@ class TestSysPathDirectories(SimpleTestCase):
self.assertIn(self.file.parent, paths)
def test_sys_paths_non_existing(self):
- nonexistent_file = Path(self.directory.name) / 'does_not_exist'
+ nonexistent_file = Path(self.directory.name) / "does_not_exist"
with extend_sys_path(str(nonexistent_file)):
paths = list(autoreload.sys_path_directories())
self.assertNotIn(nonexistent_file, paths)
@@ -327,12 +339,12 @@ class TestSysPathDirectories(SimpleTestCase):
class GetReloaderTests(SimpleTestCase):
- @mock.patch('django.utils.autoreload.WatchmanReloader')
+ @mock.patch("django.utils.autoreload.WatchmanReloader")
def test_watchman_unavailable(self, mocked_watchman):
mocked_watchman.check_availability.side_effect = WatchmanUnavailable
self.assertIsInstance(autoreload.get_reloader(), autoreload.StatReloader)
- @mock.patch.object(autoreload.WatchmanReloader, 'check_availability')
+ @mock.patch.object(autoreload.WatchmanReloader, "check_availability")
def test_watchman_available(self, mocked_available):
# If WatchmanUnavailable isn't raised, Watchman will be chosen.
mocked_available.return_value = None
@@ -341,35 +353,35 @@ class GetReloaderTests(SimpleTestCase):
class RunWithReloaderTests(SimpleTestCase):
- @mock.patch.dict(os.environ, {autoreload.DJANGO_AUTORELOAD_ENV: 'true'})
- @mock.patch('django.utils.autoreload.get_reloader')
+ @mock.patch.dict(os.environ, {autoreload.DJANGO_AUTORELOAD_ENV: "true"})
+ @mock.patch("django.utils.autoreload.get_reloader")
def test_swallows_keyboard_interrupt(self, mocked_get_reloader):
mocked_get_reloader.side_effect = KeyboardInterrupt()
autoreload.run_with_reloader(lambda: None) # No exception
- @mock.patch.dict(os.environ, {autoreload.DJANGO_AUTORELOAD_ENV: 'false'})
- @mock.patch('django.utils.autoreload.restart_with_reloader')
+ @mock.patch.dict(os.environ, {autoreload.DJANGO_AUTORELOAD_ENV: "false"})
+ @mock.patch("django.utils.autoreload.restart_with_reloader")
def test_calls_sys_exit(self, mocked_restart_reloader):
mocked_restart_reloader.return_value = 1
with self.assertRaises(SystemExit) as exc:
autoreload.run_with_reloader(lambda: None)
self.assertEqual(exc.exception.code, 1)
- @mock.patch.dict(os.environ, {autoreload.DJANGO_AUTORELOAD_ENV: 'true'})
- @mock.patch('django.utils.autoreload.start_django')
- @mock.patch('django.utils.autoreload.get_reloader')
+ @mock.patch.dict(os.environ, {autoreload.DJANGO_AUTORELOAD_ENV: "true"})
+ @mock.patch("django.utils.autoreload.start_django")
+ @mock.patch("django.utils.autoreload.get_reloader")
def test_calls_start_django(self, mocked_reloader, mocked_start_django):
mocked_reloader.return_value = mock.sentinel.RELOADER
autoreload.run_with_reloader(mock.sentinel.METHOD)
self.assertEqual(mocked_start_django.call_count, 1)
self.assertSequenceEqual(
mocked_start_django.call_args[0],
- [mock.sentinel.RELOADER, mock.sentinel.METHOD]
+ [mock.sentinel.RELOADER, mock.sentinel.METHOD],
)
class StartDjangoTests(SimpleTestCase):
- @mock.patch('django.utils.autoreload.StatReloader')
+ @mock.patch("django.utils.autoreload.StatReloader")
def test_watchman_becomes_unavailable(self, mocked_stat):
mocked_stat.should_stop.return_value = True
fake_reloader = mock.MagicMock()
@@ -379,21 +391,21 @@ class StartDjangoTests(SimpleTestCase):
autoreload.start_django(fake_reloader, lambda: None)
self.assertEqual(mocked_stat.call_count, 1)
- @mock.patch('django.utils.autoreload.ensure_echo_on')
+ @mock.patch("django.utils.autoreload.ensure_echo_on")
def test_echo_on_called(self, mocked_echo):
fake_reloader = mock.MagicMock()
autoreload.start_django(fake_reloader, lambda: None)
self.assertEqual(mocked_echo.call_count, 1)
- @mock.patch('django.utils.autoreload.check_errors')
+ @mock.patch("django.utils.autoreload.check_errors")
def test_check_errors_called(self, mocked_check_errors):
fake_method = mock.MagicMock(return_value=None)
fake_reloader = mock.MagicMock()
autoreload.start_django(fake_reloader, fake_method)
self.assertCountEqual(mocked_check_errors.call_args[0], [fake_method])
- @mock.patch('threading.Thread')
- @mock.patch('django.utils.autoreload.check_errors')
+ @mock.patch("threading.Thread")
+ @mock.patch("django.utils.autoreload.check_errors")
def test_starts_thread_with_args(self, mocked_check_errors, mocked_thread):
fake_reloader = mock.MagicMock()
fake_main_func = mock.MagicMock()
@@ -404,7 +416,12 @@ class StartDjangoTests(SimpleTestCase):
self.assertEqual(mocked_thread.call_count, 1)
self.assertEqual(
mocked_thread.call_args[1],
- {'target': fake_main_func, 'args': (123,), 'kwargs': {'abc': 123}, 'name': 'django-main-thread'}
+ {
+ "target": fake_main_func,
+ "args": (123,),
+ "kwargs": {"abc": 123},
+ "name": "django-main-thread",
+ },
)
self.assertIs(fake_thread.daemon, True)
self.assertTrue(fake_thread.start.called)
@@ -414,7 +431,7 @@ class TestCheckErrors(SimpleTestCase):
def test_mutates_error_files(self):
fake_method = mock.MagicMock(side_effect=RuntimeError())
wrapped = autoreload.check_errors(fake_method)
- with mock.patch.object(autoreload, '_error_files') as mocked_error_files:
+ with mock.patch.object(autoreload, "_error_files") as mocked_error_files:
try:
with self.assertRaises(RuntimeError):
wrapped()
@@ -424,7 +441,7 @@ class TestCheckErrors(SimpleTestCase):
class TestRaiseLastException(SimpleTestCase):
- @mock.patch('django.utils.autoreload._exception', None)
+ @mock.patch("django.utils.autoreload._exception", None)
def test_no_exception(self):
# Should raise no exception if _exception is None
autoreload.raise_last_exception()
@@ -435,12 +452,12 @@ class TestRaiseLastException(SimpleTestCase):
# Create an exception
try:
- raise MyException('Test Message')
+ raise MyException("Test Message")
except MyException:
exc_info = sys.exc_info()
- with mock.patch('django.utils.autoreload._exception', exc_info):
- with self.assertRaisesMessage(MyException, 'Test Message'):
+ with mock.patch("django.utils.autoreload._exception", exc_info):
+ with self.assertRaisesMessage(MyException, "Test Message"):
autoreload.raise_last_exception()
def test_raises_custom_exception(self):
@@ -448,14 +465,15 @@ class TestRaiseLastException(SimpleTestCase):
def __init__(self, msg, extra_context):
super().__init__(msg)
self.extra_context = extra_context
+
# Create an exception.
try:
- raise MyException('Test Message', 'extra context')
+ raise MyException("Test Message", "extra context")
except MyException:
exc_info = sys.exc_info()
- with mock.patch('django.utils.autoreload._exception', exc_info):
- with self.assertRaisesMessage(MyException, 'Test Message'):
+ with mock.patch("django.utils.autoreload._exception", exc_info):
+ with self.assertRaisesMessage(MyException, "Test Message"):
autoreload.raise_last_exception()
def test_raises_exception_with_context(self):
@@ -467,7 +485,7 @@ class TestRaiseLastException(SimpleTestCase):
except Exception:
exc_info = sys.exc_info()
- with mock.patch('django.utils.autoreload._exception', exc_info):
+ with mock.patch("django.utils.autoreload._exception", exc_info):
with self.assertRaises(Exception) as cm:
autoreload.raise_last_exception()
self.assertEqual(cm.exception.args[0], 1)
@@ -475,15 +493,18 @@ class TestRaiseLastException(SimpleTestCase):
class RestartWithReloaderTests(SimpleTestCase):
- executable = '/usr/bin/python'
+ executable = "/usr/bin/python"
def patch_autoreload(self, argv):
- patch_call = mock.patch('django.utils.autoreload.subprocess.run', return_value=CompletedProcess(argv, 0))
+ patch_call = mock.patch(
+ "django.utils.autoreload.subprocess.run",
+ return_value=CompletedProcess(argv, 0),
+ )
patches = [
- mock.patch('django.utils.autoreload.sys.argv', argv),
- mock.patch('django.utils.autoreload.sys.executable', self.executable),
- mock.patch('django.utils.autoreload.sys.warnoptions', ['all']),
- mock.patch('django.utils.autoreload.sys._xoptions', {}),
+ mock.patch("django.utils.autoreload.sys.argv", argv),
+ mock.patch("django.utils.autoreload.sys.executable", self.executable),
+ mock.patch("django.utils.autoreload.sys.warnoptions", ["all"]),
+ mock.patch("django.utils.autoreload.sys._xoptions", {}),
]
for p in patches:
p.start()
@@ -494,27 +515,30 @@ class RestartWithReloaderTests(SimpleTestCase):
def test_manage_py(self):
with tempfile.TemporaryDirectory() as temp_dir:
- script = Path(temp_dir) / 'manage.py'
+ script = Path(temp_dir) / "manage.py"
script.touch()
- argv = [str(script), 'runserver']
+ argv = [str(script), "runserver"]
mock_call = self.patch_autoreload(argv)
- with mock.patch('__main__.__spec__', None):
+ with mock.patch("__main__.__spec__", None):
autoreload.restart_with_reloader()
self.assertEqual(mock_call.call_count, 1)
self.assertEqual(
mock_call.call_args[0][0],
- [self.executable, '-Wall'] + argv,
+ [self.executable, "-Wall"] + argv,
)
def test_python_m_django(self):
- main = '/usr/lib/pythonX.Y/site-packages/django/__main__.py'
- argv = [main, 'runserver']
+ main = "/usr/lib/pythonX.Y/site-packages/django/__main__.py"
+ argv = [main, "runserver"]
mock_call = self.patch_autoreload(argv)
- with mock.patch('django.__main__.__file__', main):
- with mock.patch.dict(sys.modules, {'__main__': django.__main__}):
+ with mock.patch("django.__main__.__file__", main):
+ with mock.patch.dict(sys.modules, {"__main__": django.__main__}):
autoreload.restart_with_reloader()
self.assertEqual(mock_call.call_count, 1)
- self.assertEqual(mock_call.call_args[0][0], [self.executable, '-Wall', '-m', 'django'] + argv[1:])
+ self.assertEqual(
+ mock_call.call_args[0][0],
+ [self.executable, "-Wall", "-m", "django"] + argv[1:],
+ )
class ReloaderTests(SimpleTestCase):
@@ -523,8 +547,8 @@ class ReloaderTests(SimpleTestCase):
def setUp(self):
self._tempdir = tempfile.TemporaryDirectory()
self.tempdir = Path(self._tempdir.name).resolve(strict=True).absolute()
- self.existing_file = self.ensure_file(self.tempdir / 'test.py')
- self.nonexistent_file = (self.tempdir / 'does_not_exist.py').absolute()
+ self.existing_file = self.ensure_file(self.tempdir / "test.py")
+ self.nonexistent_file = (self.tempdir / "does_not_exist.py").absolute()
self.reloader = self.RELOADER_CLS()
def tearDown(self):
@@ -558,80 +582,96 @@ class ReloaderTests(SimpleTestCase):
class IntegrationTests:
- @mock.patch('django.utils.autoreload.BaseReloader.notify_file_changed')
- @mock.patch('django.utils.autoreload.iter_all_python_module_files', return_value=frozenset())
+ @mock.patch("django.utils.autoreload.BaseReloader.notify_file_changed")
+ @mock.patch(
+ "django.utils.autoreload.iter_all_python_module_files", return_value=frozenset()
+ )
def test_glob(self, mocked_modules, notify_mock):
- non_py_file = self.ensure_file(self.tempdir / 'non_py_file')
- self.reloader.watch_dir(self.tempdir, '*.py')
+ non_py_file = self.ensure_file(self.tempdir / "non_py_file")
+ self.reloader.watch_dir(self.tempdir, "*.py")
with self.tick_twice():
self.increment_mtime(non_py_file)
self.increment_mtime(self.existing_file)
self.assertEqual(notify_mock.call_count, 1)
self.assertCountEqual(notify_mock.call_args[0], [self.existing_file])
- @mock.patch('django.utils.autoreload.BaseReloader.notify_file_changed')
- @mock.patch('django.utils.autoreload.iter_all_python_module_files', return_value=frozenset())
+ @mock.patch("django.utils.autoreload.BaseReloader.notify_file_changed")
+ @mock.patch(
+ "django.utils.autoreload.iter_all_python_module_files", return_value=frozenset()
+ )
def test_multiple_globs(self, mocked_modules, notify_mock):
- self.ensure_file(self.tempdir / 'x.test')
- self.reloader.watch_dir(self.tempdir, '*.py')
- self.reloader.watch_dir(self.tempdir, '*.test')
+ self.ensure_file(self.tempdir / "x.test")
+ self.reloader.watch_dir(self.tempdir, "*.py")
+ self.reloader.watch_dir(self.tempdir, "*.test")
with self.tick_twice():
self.increment_mtime(self.existing_file)
self.assertEqual(notify_mock.call_count, 1)
self.assertCountEqual(notify_mock.call_args[0], [self.existing_file])
- @mock.patch('django.utils.autoreload.BaseReloader.notify_file_changed')
- @mock.patch('django.utils.autoreload.iter_all_python_module_files', return_value=frozenset())
+ @mock.patch("django.utils.autoreload.BaseReloader.notify_file_changed")
+ @mock.patch(
+ "django.utils.autoreload.iter_all_python_module_files", return_value=frozenset()
+ )
def test_overlapping_globs(self, mocked_modules, notify_mock):
- self.reloader.watch_dir(self.tempdir, '*.py')
- self.reloader.watch_dir(self.tempdir, '*.p*')
+ self.reloader.watch_dir(self.tempdir, "*.py")
+ self.reloader.watch_dir(self.tempdir, "*.p*")
with self.tick_twice():
self.increment_mtime(self.existing_file)
self.assertEqual(notify_mock.call_count, 1)
self.assertCountEqual(notify_mock.call_args[0], [self.existing_file])
- @mock.patch('django.utils.autoreload.BaseReloader.notify_file_changed')
- @mock.patch('django.utils.autoreload.iter_all_python_module_files', return_value=frozenset())
+ @mock.patch("django.utils.autoreload.BaseReloader.notify_file_changed")
+ @mock.patch(
+ "django.utils.autoreload.iter_all_python_module_files", return_value=frozenset()
+ )
def test_glob_recursive(self, mocked_modules, notify_mock):
- non_py_file = self.ensure_file(self.tempdir / 'dir' / 'non_py_file')
- py_file = self.ensure_file(self.tempdir / 'dir' / 'file.py')
- self.reloader.watch_dir(self.tempdir, '**/*.py')
+ non_py_file = self.ensure_file(self.tempdir / "dir" / "non_py_file")
+ py_file = self.ensure_file(self.tempdir / "dir" / "file.py")
+ self.reloader.watch_dir(self.tempdir, "**/*.py")
with self.tick_twice():
self.increment_mtime(non_py_file)
self.increment_mtime(py_file)
self.assertEqual(notify_mock.call_count, 1)
self.assertCountEqual(notify_mock.call_args[0], [py_file])
- @mock.patch('django.utils.autoreload.BaseReloader.notify_file_changed')
- @mock.patch('django.utils.autoreload.iter_all_python_module_files', return_value=frozenset())
+ @mock.patch("django.utils.autoreload.BaseReloader.notify_file_changed")
+ @mock.patch(
+ "django.utils.autoreload.iter_all_python_module_files", return_value=frozenset()
+ )
def test_multiple_recursive_globs(self, mocked_modules, notify_mock):
- non_py_file = self.ensure_file(self.tempdir / 'dir' / 'test.txt')
- py_file = self.ensure_file(self.tempdir / 'dir' / 'file.py')
- self.reloader.watch_dir(self.tempdir, '**/*.txt')
- self.reloader.watch_dir(self.tempdir, '**/*.py')
+ non_py_file = self.ensure_file(self.tempdir / "dir" / "test.txt")
+ py_file = self.ensure_file(self.tempdir / "dir" / "file.py")
+ self.reloader.watch_dir(self.tempdir, "**/*.txt")
+ self.reloader.watch_dir(self.tempdir, "**/*.py")
with self.tick_twice():
self.increment_mtime(non_py_file)
self.increment_mtime(py_file)
self.assertEqual(notify_mock.call_count, 2)
- self.assertCountEqual(notify_mock.call_args_list, [mock.call(py_file), mock.call(non_py_file)])
+ self.assertCountEqual(
+ notify_mock.call_args_list, [mock.call(py_file), mock.call(non_py_file)]
+ )
- @mock.patch('django.utils.autoreload.BaseReloader.notify_file_changed')
- @mock.patch('django.utils.autoreload.iter_all_python_module_files', return_value=frozenset())
+ @mock.patch("django.utils.autoreload.BaseReloader.notify_file_changed")
+ @mock.patch(
+ "django.utils.autoreload.iter_all_python_module_files", return_value=frozenset()
+ )
def test_nested_glob_recursive(self, mocked_modules, notify_mock):
- inner_py_file = self.ensure_file(self.tempdir / 'dir' / 'file.py')
- self.reloader.watch_dir(self.tempdir, '**/*.py')
- self.reloader.watch_dir(inner_py_file.parent, '**/*.py')
+ inner_py_file = self.ensure_file(self.tempdir / "dir" / "file.py")
+ self.reloader.watch_dir(self.tempdir, "**/*.py")
+ self.reloader.watch_dir(inner_py_file.parent, "**/*.py")
with self.tick_twice():
self.increment_mtime(inner_py_file)
self.assertEqual(notify_mock.call_count, 1)
self.assertCountEqual(notify_mock.call_args[0], [inner_py_file])
- @mock.patch('django.utils.autoreload.BaseReloader.notify_file_changed')
- @mock.patch('django.utils.autoreload.iter_all_python_module_files', return_value=frozenset())
+ @mock.patch("django.utils.autoreload.BaseReloader.notify_file_changed")
+ @mock.patch(
+ "django.utils.autoreload.iter_all_python_module_files", return_value=frozenset()
+ )
def test_overlapping_glob_recursive(self, mocked_modules, notify_mock):
- py_file = self.ensure_file(self.tempdir / 'dir' / 'file.py')
- self.reloader.watch_dir(self.tempdir, '**/*.p*')
- self.reloader.watch_dir(self.tempdir, '**/*.py*')
+ py_file = self.ensure_file(self.tempdir / "dir" / "file.py")
+ self.reloader.watch_dir(self.tempdir, "**/*.p*")
+ self.reloader.watch_dir(self.tempdir, "**/*.py*")
with self.tick_twice():
self.increment_mtime(py_file)
self.assertEqual(notify_mock.call_count, 1)
@@ -642,19 +682,19 @@ class BaseReloaderTests(ReloaderTests):
RELOADER_CLS = autoreload.BaseReloader
def test_watch_dir_with_unresolvable_path(self):
- path = Path('unresolvable_directory')
- with mock.patch.object(Path, 'absolute', side_effect=FileNotFoundError):
- self.reloader.watch_dir(path, '**/*.mo')
+ path = Path("unresolvable_directory")
+ with mock.patch.object(Path, "absolute", side_effect=FileNotFoundError):
+ self.reloader.watch_dir(path, "**/*.mo")
self.assertEqual(list(self.reloader.directory_globs), [])
def test_watch_with_glob(self):
- self.reloader.watch_dir(self.tempdir, '*.py')
+ self.reloader.watch_dir(self.tempdir, "*.py")
watched_files = list(self.reloader.watched_files())
self.assertIn(self.existing_file, watched_files)
def test_watch_files_with_recursive_glob(self):
- inner_file = self.ensure_file(self.tempdir / 'test' / 'test.py')
- self.reloader.watch_dir(self.tempdir, '**/*.py')
+ inner_file = self.ensure_file(self.tempdir / "test" / "test.py")
+ self.reloader.watch_dir(self.tempdir, "**/*.py")
watched_files = list(self.reloader.watched_files())
self.assertIn(self.existing_file, watched_files)
self.assertIn(inner_file, watched_files)
@@ -663,7 +703,7 @@ class BaseReloaderTests(ReloaderTests):
def mocked_tick():
yield
- with mock.patch.object(self.reloader, 'tick', side_effect=mocked_tick) as tick:
+ with mock.patch.object(self.reloader, "tick", side_effect=mocked_tick) as tick:
self.reloader.run_loop()
self.assertEqual(tick.call_count, 1)
@@ -673,7 +713,7 @@ class BaseReloaderTests(ReloaderTests):
self.reloader.stop()
return # Raises StopIteration
- with mock.patch.object(self.reloader, 'tick', side_effect=mocked_tick) as tick:
+ with mock.patch.object(self.reloader, "tick", side_effect=mocked_tick) as tick:
self.reloader.run_loop()
self.assertEqual(tick.call_count, 1)
@@ -697,7 +737,7 @@ def skip_unless_watchman_available():
try:
autoreload.WatchmanReloader.check_availability()
except WatchmanUnavailable as e:
- return skip('Watchman unavailable: %s' % e)
+ return skip("Watchman unavailable: %s" % e)
return lambda func: func
@@ -708,33 +748,35 @@ class WatchmanReloaderTests(ReloaderTests, IntegrationTests):
def setUp(self):
super().setUp()
# Shorten the timeout to speed up tests.
- self.reloader.client_timeout = int(os.environ.get('DJANGO_WATCHMAN_TIMEOUT', 2))
+ self.reloader.client_timeout = int(os.environ.get("DJANGO_WATCHMAN_TIMEOUT", 2))
def test_watch_glob_ignores_non_existing_directories_two_levels(self):
- with mock.patch.object(self.reloader, '_subscribe') as mocked_subscribe:
- self.reloader._watch_glob(self.tempdir / 'does_not_exist' / 'more', ['*'])
+ with mock.patch.object(self.reloader, "_subscribe") as mocked_subscribe:
+ self.reloader._watch_glob(self.tempdir / "does_not_exist" / "more", ["*"])
self.assertFalse(mocked_subscribe.called)
def test_watch_glob_uses_existing_parent_directories(self):
- with mock.patch.object(self.reloader, '_subscribe') as mocked_subscribe:
- self.reloader._watch_glob(self.tempdir / 'does_not_exist', ['*'])
+ with mock.patch.object(self.reloader, "_subscribe") as mocked_subscribe:
+ self.reloader._watch_glob(self.tempdir / "does_not_exist", ["*"])
self.assertSequenceEqual(
mocked_subscribe.call_args[0],
[
- self.tempdir, 'glob-parent-does_not_exist:%s' % self.tempdir,
- ['anyof', ['match', 'does_not_exist/*', 'wholename']]
- ]
+ self.tempdir,
+ "glob-parent-does_not_exist:%s" % self.tempdir,
+ ["anyof", ["match", "does_not_exist/*", "wholename"]],
+ ],
)
def test_watch_glob_multiple_patterns(self):
- with mock.patch.object(self.reloader, '_subscribe') as mocked_subscribe:
- self.reloader._watch_glob(self.tempdir, ['*', '*.py'])
+ with mock.patch.object(self.reloader, "_subscribe") as mocked_subscribe:
+ self.reloader._watch_glob(self.tempdir, ["*", "*.py"])
self.assertSequenceEqual(
mocked_subscribe.call_args[0],
[
- self.tempdir, 'glob:%s' % self.tempdir,
- ['anyof', ['match', '*', 'wholename'], ['match', '*.py', 'wholename']]
- ]
+ self.tempdir,
+ "glob:%s" % self.tempdir,
+ ["anyof", ["match", "*", "wholename"], ["match", "*.py", "wholename"]],
+ ],
)
def test_watched_roots_contains_files(self):
@@ -742,7 +784,7 @@ class WatchmanReloaderTests(ReloaderTests, IntegrationTests):
self.assertIn(self.existing_file.parent, paths)
def test_watched_roots_contains_directory_globs(self):
- self.reloader.watch_dir(self.tempdir, '*.py')
+ self.reloader.watch_dir(self.tempdir, "*.py")
paths = self.reloader.watched_roots([])
self.assertIn(self.tempdir, paths)
@@ -755,42 +797,52 @@ class WatchmanReloaderTests(ReloaderTests, IntegrationTests):
self.assertTrue(self.reloader.check_server_status())
def test_check_server_status_raises_error(self):
- with mock.patch.object(self.reloader.client, 'query') as mocked_query:
+ with mock.patch.object(self.reloader.client, "query") as mocked_query:
mocked_query.side_effect = Exception()
with self.assertRaises(autoreload.WatchmanUnavailable):
self.reloader.check_server_status()
- @mock.patch('pywatchman.client')
+ @mock.patch("pywatchman.client")
def test_check_availability(self, mocked_client):
mocked_client().capabilityCheck.side_effect = Exception()
- with self.assertRaisesMessage(WatchmanUnavailable, 'Cannot connect to the watchman service'):
+ with self.assertRaisesMessage(
+ WatchmanUnavailable, "Cannot connect to the watchman service"
+ ):
self.RELOADER_CLS.check_availability()
- @mock.patch('pywatchman.client')
+ @mock.patch("pywatchman.client")
def test_check_availability_lower_version(self, mocked_client):
- mocked_client().capabilityCheck.return_value = {'version': '4.8.10'}
- with self.assertRaisesMessage(WatchmanUnavailable, 'Watchman 4.9 or later is required.'):
+ mocked_client().capabilityCheck.return_value = {"version": "4.8.10"}
+ with self.assertRaisesMessage(
+ WatchmanUnavailable, "Watchman 4.9 or later is required."
+ ):
self.RELOADER_CLS.check_availability()
def test_pywatchman_not_available(self):
- with mock.patch.object(autoreload, 'pywatchman') as mocked:
+ with mock.patch.object(autoreload, "pywatchman") as mocked:
mocked.__bool__.return_value = False
- with self.assertRaisesMessage(WatchmanUnavailable, 'pywatchman not installed.'):
+ with self.assertRaisesMessage(
+ WatchmanUnavailable, "pywatchman not installed."
+ ):
self.RELOADER_CLS.check_availability()
def test_update_watches_raises_exceptions(self):
class TestException(Exception):
pass
- with mock.patch.object(self.reloader, '_update_watches') as mocked_watches:
- with mock.patch.object(self.reloader, 'check_server_status') as mocked_server_status:
+ with mock.patch.object(self.reloader, "_update_watches") as mocked_watches:
+ with mock.patch.object(
+ self.reloader, "check_server_status"
+ ) as mocked_server_status:
mocked_watches.side_effect = TestException()
mocked_server_status.return_value = True
with self.assertRaises(TestException):
self.reloader.update_watches()
- self.assertIsInstance(mocked_server_status.call_args[0][0], TestException)
+ self.assertIsInstance(
+ mocked_server_status.call_args[0][0], TestException
+ )
- @mock.patch.dict(os.environ, {'DJANGO_WATCHMAN_TIMEOUT': '10'})
+ @mock.patch.dict(os.environ, {"DJANGO_WATCHMAN_TIMEOUT": "10"})
def test_setting_timeout_from_environment_variable(self):
self.assertEqual(self.RELOADER_CLS().client_timeout, 10)
@@ -804,9 +856,11 @@ class StatReloaderTests(ReloaderTests, IntegrationTests):
# Shorten the sleep time to speed up tests.
self.reloader.SLEEP_TIME = 0.01
- @mock.patch('django.utils.autoreload.StatReloader.notify_file_changed')
+ @mock.patch("django.utils.autoreload.StatReloader.notify_file_changed")
def test_tick_does_not_trigger_twice(self, mock_notify_file_changed):
- with mock.patch.object(self.reloader, 'watched_files', return_value=[self.existing_file]):
+ with mock.patch.object(
+ self.reloader, "watched_files", return_value=[self.existing_file]
+ ):
ticker = self.reloader.tick()
next(ticker)
self.increment_mtime(self.existing_file)
@@ -815,19 +869,29 @@ class StatReloaderTests(ReloaderTests, IntegrationTests):
self.assertEqual(mock_notify_file_changed.call_count, 1)
def test_snapshot_files_ignores_missing_files(self):
- with mock.patch.object(self.reloader, 'watched_files', return_value=[self.nonexistent_file]):
+ with mock.patch.object(
+ self.reloader, "watched_files", return_value=[self.nonexistent_file]
+ ):
self.assertEqual(dict(self.reloader.snapshot_files()), {})
def test_snapshot_files_updates(self):
- with mock.patch.object(self.reloader, 'watched_files', return_value=[self.existing_file]):
+ with mock.patch.object(
+ self.reloader, "watched_files", return_value=[self.existing_file]
+ ):
snapshot1 = dict(self.reloader.snapshot_files())
self.assertIn(self.existing_file, snapshot1)
self.increment_mtime(self.existing_file)
snapshot2 = dict(self.reloader.snapshot_files())
- self.assertNotEqual(snapshot1[self.existing_file], snapshot2[self.existing_file])
+ self.assertNotEqual(
+ snapshot1[self.existing_file], snapshot2[self.existing_file]
+ )
def test_snapshot_files_with_duplicates(self):
- with mock.patch.object(self.reloader, 'watched_files', return_value=[self.existing_file, self.existing_file]):
+ with mock.patch.object(
+ self.reloader,
+ "watched_files",
+ return_value=[self.existing_file, self.existing_file],
+ ):
snapshot = list(self.reloader.snapshot_files())
self.assertEqual(len(snapshot), 1)
self.assertEqual(snapshot[0][0], self.existing_file)