Browse Source

Fixed #30215 -- Fixed autoreloader crash for modules without __spec__.

Regression in c8720e7696ca41f3262d5369365cc1bd72a216ca.
shiningfm 6 years ago
parent
commit
99cfb28e99
3 changed files with 8 additions and 1 deletions
  1. 1 0
      AUTHORS
  2. 1 1
      django/utils/autoreload.py
  3. 6 0
      tests/utils_tests/test_autoreload.py

+ 1 - 0
AUTHORS

@@ -280,6 +280,7 @@ answer newbie questions, and generally made Django that much better:
     Flávio Juvenal da Silva Junior <flavio@vinta.com.br>
     flavio.curella@gmail.com
     Florian Apolloner <florian@apolloner.eu>
+    Florian Moussous <florian.moussous@gmail.com>
     Francisco Albarran Cristobal <pahko.xd@gmail.com>
     François Freitag <mail@franek.fr>
     Frank Tegtmeyer <fte@fte.to>

+ 1 - 1
django/utils/autoreload.py

@@ -111,7 +111,7 @@ def iter_modules_and_files(modules, extra_files):
         # During debugging (with PyDev) the 'typing.io' and 'typing.re' objects
         # are added to sys.modules, however they are types not modules and so
         # cause issues here.
-        if not isinstance(module, ModuleType) or module.__spec__ is None:
+        if not isinstance(module, ModuleType) or getattr(module, '__spec__', None) is None:
             continue
         spec = module.__spec__
         # Modules could be loaded from places without a concrete location. If

+ 6 - 0
tests/utils_tests/test_autoreload.py

@@ -6,6 +6,7 @@ import sys
 import tempfile
 import threading
 import time
+import types
 import weakref
 import zipfile
 from importlib import import_module
@@ -124,6 +125,11 @@ class TestIterModulesAndFiles(SimpleTestCase):
         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')
+        del module.__spec__
+        self.assertEqual(autoreload.iter_modules_and_files((module,), frozenset()), frozenset())
+
 
 class TestCommonRoots(SimpleTestCase):
     def test_common_roots(self):