1"""Test that sys.modules is used properly by import.""" 2from test.test_importlib import util 3import sys 4from types import MethodType 5import unittest 6import warnings 7 8 9class UseCache: 10 11 """When it comes to sys.modules, import prefers it over anything else. 12 13 Once a name has been resolved, sys.modules is checked to see if it contains 14 the module desired. If so, then it is returned [use cache]. If it is not 15 found, then the proper steps are taken to perform the import, but 16 sys.modules is still used to return the imported module (e.g., not what a 17 loader returns) [from cache on return]. This also applies to imports of 18 things contained within a package and thus get assigned as an attribute 19 [from cache to attribute] or pulled in thanks to a fromlist import 20 [from cache for fromlist]. But if sys.modules contains None then 21 ImportError is raised [None in cache]. 22 23 """ 24 25 def test_using_cache(self): 26 # [use cache] 27 module_to_use = "some module found!" 28 with util.uncache('some_module'): 29 sys.modules['some_module'] = module_to_use 30 module = self.__import__('some_module') 31 self.assertEqual(id(module_to_use), id(module)) 32 33 def test_None_in_cache(self): 34 #[None in cache] 35 name = 'using_None' 36 with util.uncache(name): 37 sys.modules[name] = None 38 with self.assertRaises(ImportError) as cm: 39 self.__import__(name) 40 self.assertEqual(cm.exception.name, name) 41 42 43(Frozen_UseCache, 44 Source_UseCache 45 ) = util.test_both(UseCache, __import__=util.__import__) 46 47 48class ImportlibUseCache(UseCache, unittest.TestCase): 49 50 # Pertinent only to PEP 302; exec_module() doesn't return a module. 51 52 __import__ = util.__import__['Source'] 53 54 def create_mock(self, *names, return_=None): 55 mock = util.mock_modules(*names) 56 original_load = mock.load_module 57 def load_module(self, fullname): 58 original_load(fullname) 59 return return_ 60 mock.load_module = MethodType(load_module, mock) 61 return mock 62 63 # __import__ inconsistent between loaders and built-in import when it comes 64 # to when to use the module in sys.modules and when not to. 65 def test_using_cache_after_loader(self): 66 # [from cache on return] 67 with warnings.catch_warnings(): 68 warnings.simplefilter("ignore", ImportWarning) 69 with self.create_mock('module') as mock: 70 with util.import_state(meta_path=[mock]): 71 module = self.__import__('module') 72 self.assertEqual(id(module), id(sys.modules['module'])) 73 74 # See test_using_cache_after_loader() for reasoning. 75 def test_using_cache_for_assigning_to_attribute(self): 76 # [from cache to attribute] 77 with warnings.catch_warnings(): 78 warnings.simplefilter("ignore", ImportWarning) 79 with self.create_mock('pkg.__init__', 'pkg.module') as importer: 80 with util.import_state(meta_path=[importer]): 81 module = self.__import__('pkg.module') 82 self.assertTrue(hasattr(module, 'module')) 83 self.assertEqual(id(module.module), 84 id(sys.modules['pkg.module'])) 85 86 # See test_using_cache_after_loader() for reasoning. 87 def test_using_cache_for_fromlist(self): 88 # [from cache for fromlist] 89 with warnings.catch_warnings(): 90 warnings.simplefilter("ignore", ImportWarning) 91 with self.create_mock('pkg.__init__', 'pkg.module') as importer: 92 with util.import_state(meta_path=[importer]): 93 module = self.__import__('pkg', fromlist=['module']) 94 self.assertTrue(hasattr(module, 'module')) 95 self.assertEqual(id(module.module), 96 id(sys.modules['pkg.module'])) 97 98 99if __name__ == '__main__': 100 unittest.main() 101