summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Holtermann <info@markusholtermann.eu>2014-10-31 10:22:15 +0100
committerTim Graham <timograham@gmail.com>2014-10-31 08:01:47 -0400
commit98da408964b229ee0b35bb8c4500820e3606aeab (patch)
tree2d5208b605524f0a565318806f708449f096e922
parentc0c1bb9e64d7e1cea50dc4818ffcf229b568578b (diff)
Fixed #23670 -- Prevented partial import state during module autodiscovery
Thanks kostko for the report.
-rw-r--r--django/utils/module_loading.py34
-rw-r--r--tests/utils_tests/test_module/another_good_module.py5
-rw-r--r--tests/utils_tests/test_module_loading.py25
3 files changed, 47 insertions, 17 deletions
diff --git a/django/utils/module_loading.py b/django/utils/module_loading.py
index 826aed8c00..cd0c8bc5cc 100644
--- a/django/utils/module_loading.py
+++ b/django/utils/module_loading.py
@@ -64,26 +64,26 @@ def autodiscover_modules(*args, **kwargs):
register_to = kwargs.get('register_to')
for app_config in apps.get_app_configs():
- # Attempt to import the app's module.
- try:
- if register_to:
- before_import_registry = copy.copy(register_to._registry)
+ for module_to_search in args:
+ # Attempt to import the app's module.
+ try:
+ if register_to:
+ before_import_registry = copy.copy(register_to._registry)
- for module_to_search in args:
import_module('%s.%s' % (app_config.name, module_to_search))
- except:
- # Reset the model registry to the state before the last import as
- # this import will have to reoccur on the next request and this
- # could raise NotRegistered and AlreadyRegistered exceptions
- # (see #8245).
- if register_to:
- register_to._registry = before_import_registry
+ except:
+ # Reset the registry to the state before the last import
+ # as this import will have to reoccur on the next request and
+ # this could raise NotRegistered and AlreadyRegistered
+ # exceptions (see #8245).
+ if register_to:
+ register_to._registry = before_import_registry
- # Decide whether to bubble up this error. If the app just
- # doesn't have an admin module, we can ignore the error
- # attempting to import it, otherwise we want it to bubble up.
- if module_has_submodule(app_config.module, module_to_search):
- raise
+ # Decide whether to bubble up this error. If the app just
+ # doesn't have the module in question, we can ignore the error
+ # attempting to import it, otherwise we want it to bubble up.
+ if module_has_submodule(app_config.module, module_to_search):
+ raise
if sys.version_info[:2] >= (3, 3):
diff --git a/tests/utils_tests/test_module/another_good_module.py b/tests/utils_tests/test_module/another_good_module.py
index ed4b2d34a2..fd69a3b30c 100644
--- a/tests/utils_tests/test_module/another_good_module.py
+++ b/tests/utils_tests/test_module/another_good_module.py
@@ -1 +1,6 @@
+from . import site
content = 'Another Good Module'
+
+site._registry.update({
+ 'lorem': 'ipsum',
+})
diff --git a/tests/utils_tests/test_module_loading.py b/tests/utils_tests/test_module_loading.py
index 9cdaf8df09..31608bfcc1 100644
--- a/tests/utils_tests/test_module_loading.py
+++ b/tests/utils_tests/test_module_loading.py
@@ -155,6 +155,15 @@ class ModuleImportTestCase(IgnoreDeprecationWarningsMixin, unittest.TestCase):
@modify_settings(INSTALLED_APPS={'append': 'utils_tests.test_module'})
class AutodiscoverModulesTestCase(SimpleTestCase):
+ def tearDown(self):
+ sys.path_importer_cache.clear()
+
+ sys.modules.pop('utils_tests.test_module.another_bad_module', None)
+ sys.modules.pop('utils_tests.test_module.another_good_module', None)
+ sys.modules.pop('utils_tests.test_module.bad_module', None)
+ sys.modules.pop('utils_tests.test_module.good_module', None)
+ sys.modules.pop('utils_tests.test_module', None)
+
def test_autodiscover_modules_found(self):
autodiscover_modules('good_module')
@@ -172,12 +181,28 @@ class AutodiscoverModulesTestCase(SimpleTestCase):
def test_autodiscover_modules_several_found(self):
autodiscover_modules('good_module', 'another_good_module')
+ def test_autodiscover_modules_several_found_with_registry(self):
+ from .test_module import site
+ autodiscover_modules('good_module', 'another_good_module', register_to=site)
+ self.assertEqual(site._registry, {'lorem': 'ipsum'})
+
def test_validate_registry_keeps_intact(self):
from .test_module import site
with six.assertRaisesRegex(self, Exception, "Some random exception."):
autodiscover_modules('another_bad_module', register_to=site)
self.assertEqual(site._registry, {})
+ def test_validate_registry_resets_after_erroneous_module(self):
+ from .test_module import site
+ with six.assertRaisesRegex(self, Exception, "Some random exception."):
+ autodiscover_modules('another_good_module', 'another_bad_module', register_to=site)
+ self.assertEqual(site._registry, {'lorem': 'ipsum'})
+
+ def test_validate_registry_resets_after_missing_module(self):
+ from .test_module import site
+ autodiscover_modules('does_not_exist', 'another_good_module', 'does_not_exist2', register_to=site)
+ self.assertEqual(site._registry, {'lorem': 'ipsum'})
+
class ProxyFinder(object):
def __init__(self):