Skip to content

Commit 3483bfc

Browse files
Fixed #36943 -- Preserved any exception from URLconf module in autoreloader.
Co-authored-by: Jacob Walls <jacobtylerwalls@gmail.com>
1 parent 14889d8 commit 3483bfc

2 files changed

Lines changed: 22 additions & 5 deletions

File tree

django/utils/autoreload.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
# file paths to allow watching them in the future.
3434
_error_files = []
3535
_exception = None
36+
# Exception raised while loading the URLConf.
37+
_url_module_exception = None
3638

3739
try:
3840
import termios
@@ -62,7 +64,7 @@ def wrapper(*args, **kwargs):
6264
global _exception
6365
try:
6466
fn(*args, **kwargs)
65-
except Exception:
67+
except Exception as e:
6668
_exception = sys.exc_info()
6769

6870
et, ev, tb = _exception
@@ -75,8 +77,10 @@ def wrapper(*args, **kwargs):
7577

7678
if filename not in _error_files:
7779
_error_files.append(filename)
80+
if _url_module_exception is not None:
81+
raise e from _url_module_exception
7882

79-
raise
83+
raise e
8084

8185
return wrapper
8286

@@ -339,6 +343,7 @@ def wait_for_apps_ready(self, app_reg, django_main_thread):
339343
return False
340344

341345
def run(self, django_main_thread):
346+
global _url_module_exception
342347
logger.debug("Waiting for apps ready_event.")
343348
self.wait_for_apps_ready(apps, django_main_thread)
344349
from django.urls import get_resolver
@@ -347,10 +352,10 @@ def run(self, django_main_thread):
347352
# reloader starts by accessing the urlconf_module property.
348353
try:
349354
get_resolver().urlconf_module
350-
except Exception:
355+
except Exception as e:
351356
# Loading the urlconf can result in errors during development.
352-
# If this occurs then swallow the error and continue.
353-
pass
357+
# If this occurs then store the error and continue.
358+
_url_module_exception = e
354359
logger.debug("Apps ready_event triggered. Sending autoreload_started signal.")
355360
autoreload_started.send(sender=self)
356361
self.run_loop()

tests/utils_tests/test_autoreload.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,18 @@ def test_mutates_error_files(self):
434434
autoreload._exception = None
435435
self.assertEqual(mocked_error_files.append.call_count, 1)
436436

437+
def test_urlconf_exception_is_used_as_cause(self):
438+
urlconf_exc = ValueError("Error")
439+
fake_method = mock.MagicMock(side_effect=RuntimeError())
440+
wrapped = autoreload.check_errors(fake_method)
441+
with mock.patch.object(autoreload, "_url_module_exception", urlconf_exc):
442+
try:
443+
with self.assertRaises(RuntimeError) as cm:
444+
wrapped()
445+
finally:
446+
autoreload._exception = None
447+
self.assertIs(cm.exception.__cause__, urlconf_exc)
448+
437449

438450
class TestRaiseLastException(SimpleTestCase):
439451
@mock.patch("django.utils.autoreload._exception", None)

0 commit comments

Comments
 (0)