]> granicus.if.org Git - python/commitdiff
If a module injects something into sys.modules as a side-effect of
authorBrett Cannon <brett@python.org>
Tue, 3 Apr 2012 00:33:56 +0000 (20:33 -0400)
committerBrett Cannon <brett@python.org>
Tue, 3 Apr 2012 00:33:56 +0000 (20:33 -0400)
importation, then respect that injection.

Discovered thanks to Lib/xml/parsers/expat.py injecting
xml.parsers.expat.errors and etree now importing that directly as a
module.

Lib/importlib/_bootstrap.py
Lib/importlib/test/import_/test_packages.py

index e0f86fc17273d44cfdeceb1e5dc6b064bb180c56..d81e9498ddc16b8938ad8fb2c9040379674efed7 100644 (file)
@@ -927,6 +927,9 @@ def _find_and_load(name, import_):
     if parent:
         if parent not in sys.modules:
             import_(parent)
+        # Crazy side-effects!
+        if name in sys.modules:
+            return sys.modules[name]
         # Backwards-compatibility; be nicer to skip the dict lookup.
         parent_module = sys.modules[parent]
         try:
index faadc32172bfa40b0f3c817a9c8d6d4598c2830b..9590d5f7f3b6b9ace3f45a4541cf3166d7c5bf5f 100644 (file)
@@ -27,6 +27,19 @@ class ParentModuleTests(unittest.TestCase):
         with self.assertRaises(ImportError):
             import_util.import_('sys.no_submodules_here')
 
+    def test_module_not_package_but_side_effects(self):
+        # If a module injects something into sys.modules as a side-effect, then
+        # pick up on that fact.
+        name = 'mod'
+        subname = name + '.b'
+        def module_injection():
+            sys.modules[subname] = 'total bunk'
+        mock_modules = util.mock_modules('mod',
+                                         module_code={'mod': module_injection})
+        with mock_modules as mock:
+            with util.import_state(meta_path=[mock]):
+                submodule = import_util.import_(subname)
+
 
 def test_main():
     from test.support import run_unittest