diff options
| author | varunkasyap <varunkasyap@hotmail.com> | 2026-03-03 19:10:51 +0530 |
|---|---|---|
| committer | Jacob Walls <jacobtylerwalls@gmail.com> | 2026-03-10 11:32:39 -0400 |
| commit | 3483bfc0920b0ef0b28563aabe8ff546699b6ece (patch) | |
| tree | a89fc93947f0062059ee7b8b0dcb2e9d4c6f85c9 | |
| parent | 14889d8cead6af22ef71360f26610711997915d1 (diff) | |
Fixed #36943 -- Preserved any exception from URLconf module in autoreloader.
Co-authored-by: Jacob Walls <jacobtylerwalls@gmail.com>
| -rw-r--r-- | django/utils/autoreload.py | 15 | ||||
| -rw-r--r-- | tests/utils_tests/test_autoreload.py | 12 |
2 files changed, 22 insertions, 5 deletions
diff --git a/django/utils/autoreload.py b/django/utils/autoreload.py index 99812979d7..13019f7214 100644 --- a/django/utils/autoreload.py +++ b/django/utils/autoreload.py @@ -33,6 +33,8 @@ logger = logging.getLogger("django.utils.autoreload") # file paths to allow watching them in the future. _error_files = [] _exception = None +# Exception raised while loading the URLConf. +_url_module_exception = None try: import termios @@ -62,7 +64,7 @@ def check_errors(fn): global _exception try: fn(*args, **kwargs) - except Exception: + except Exception as e: _exception = sys.exc_info() et, ev, tb = _exception @@ -75,8 +77,10 @@ def check_errors(fn): if filename not in _error_files: _error_files.append(filename) + if _url_module_exception is not None: + raise e from _url_module_exception - raise + raise e return wrapper @@ -339,6 +343,7 @@ class BaseReloader: return False def run(self, django_main_thread): + global _url_module_exception logger.debug("Waiting for apps ready_event.") self.wait_for_apps_ready(apps, django_main_thread) from django.urls import get_resolver @@ -347,10 +352,10 @@ class BaseReloader: # reloader starts by accessing the urlconf_module property. try: get_resolver().urlconf_module - except Exception: + except Exception as e: # Loading the urlconf can result in errors during development. - # If this occurs then swallow the error and continue. - pass + # If this occurs then store the error and continue. + _url_module_exception = e logger.debug("Apps ready_event triggered. Sending autoreload_started signal.") autoreload_started.send(sender=self) self.run_loop() diff --git a/tests/utils_tests/test_autoreload.py b/tests/utils_tests/test_autoreload.py index c9e6443c6f..2033728da8 100644 --- a/tests/utils_tests/test_autoreload.py +++ b/tests/utils_tests/test_autoreload.py @@ -434,6 +434,18 @@ class TestCheckErrors(SimpleTestCase): autoreload._exception = None self.assertEqual(mocked_error_files.append.call_count, 1) + def test_urlconf_exception_is_used_as_cause(self): + urlconf_exc = ValueError("Error") + fake_method = mock.MagicMock(side_effect=RuntimeError()) + wrapped = autoreload.check_errors(fake_method) + with mock.patch.object(autoreload, "_url_module_exception", urlconf_exc): + try: + with self.assertRaises(RuntimeError) as cm: + wrapped() + finally: + autoreload._exception = None + self.assertIs(cm.exception.__cause__, urlconf_exc) + class TestRaiseLastException(SimpleTestCase): @mock.patch("django.utils.autoreload._exception", None) |
