mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	Issue #13591: import_module potentially imports a module twice.
This commit is contained in:
		
						commit
						d7afeeeb8d
					
				
					 4 changed files with 29 additions and 2 deletions
				
			
		|  | @ -837,7 +837,9 @@ def _gcd_import(name, package=None, level=0): | |||
|         for finder in meta_path: | ||||
|             loader = finder.find_module(name, path) | ||||
|             if loader is not None: | ||||
|                 loader.load_module(name) | ||||
|                 # The parent import may have already imported this module. | ||||
|                 if name not in sys.modules: | ||||
|                     loader.load_module(name) | ||||
|                 break | ||||
|         else: | ||||
|             raise ImportError(_ERR_MSG.format(name)) | ||||
|  |  | |||
|  | @ -67,6 +67,23 @@ def test_relative_import_wo_package(self): | |||
|             importlib.import_module('.support') | ||||
| 
 | ||||
| 
 | ||||
|     def test_loaded_once(self): | ||||
|         # Issue #13591: Modules should only be loaded once when | ||||
|         # initializing the parent package attempts to import the | ||||
|         # module currently being imported. | ||||
|         b_load_count = 0 | ||||
|         def load_a(): | ||||
|             importlib.import_module('a.b') | ||||
|         def load_b(): | ||||
|             nonlocal b_load_count | ||||
|             b_load_count += 1 | ||||
|         code = {'a': load_a, 'a.b': load_b} | ||||
|         modules = ['a.__init__', 'a.b'] | ||||
|         with util.mock_modules(*modules, module_code=code) as mock: | ||||
|             with util.import_state(meta_path=[mock]): | ||||
|                 importlib.import_module('a.b') | ||||
|         self.assertEqual(b_load_count, 1) | ||||
| 
 | ||||
| def test_main(): | ||||
|     from test.support import run_unittest | ||||
|     run_unittest(ImportModuleTests) | ||||
|  |  | |||
|  | @ -84,8 +84,9 @@ class mock_modules: | |||
| 
 | ||||
|     """A mock importer/loader.""" | ||||
| 
 | ||||
|     def __init__(self, *names): | ||||
|     def __init__(self, *names, module_code={}): | ||||
|         self.modules = {} | ||||
|         self.module_code = {} | ||||
|         for name in names: | ||||
|             if not name.endswith('.__init__'): | ||||
|                 import_name = name | ||||
|  | @ -105,6 +106,8 @@ def __init__(self, *names): | |||
|             if import_name != name: | ||||
|                 module.__path__ = ['<mock __path__>'] | ||||
|             self.modules[import_name] = module | ||||
|             if import_name in module_code: | ||||
|                 self.module_code[import_name] = module_code[import_name] | ||||
| 
 | ||||
|     def __getitem__(self, name): | ||||
|         return self.modules[name] | ||||
|  | @ -120,6 +123,8 @@ def load_module(self, fullname): | |||
|             raise ImportError | ||||
|         else: | ||||
|             sys.modules[fullname] = self.modules[fullname] | ||||
|             if fullname in self.module_code: | ||||
|                 self.module_code[fullname]() | ||||
|             return self.modules[fullname] | ||||
| 
 | ||||
|     def __enter__(self): | ||||
|  |  | |||
|  | @ -2548,6 +2548,9 @@ Core and Builtins | |||
| Library | ||||
| ------- | ||||
| 
 | ||||
| - Issue #13591: A bug in importlib has been fixed that caused import_module | ||||
|   to load a module twice. | ||||
| 
 | ||||
| - logging: added "handler of last resort". See http://bit.ly/last-resort-handler | ||||
| 
 | ||||
| - test.support: Added TestHandler and Matcher classes for better support of | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Meador Inge
						Meador Inge