1from . import util as test_util 2 3init = test_util.import_importlib('importlib') 4util = test_util.import_importlib('importlib.util') 5machinery = test_util.import_importlib('importlib.machinery') 6 7import os.path 8import sys 9from test import support 10import types 11import unittest 12import warnings 13 14 15class ImportModuleTests: 16 17 """Test importlib.import_module.""" 18 19 def test_module_import(self): 20 # Test importing a top-level module. 21 with test_util.mock_modules('top_level') as mock: 22 with test_util.import_state(meta_path=[mock]): 23 module = self.init.import_module('top_level') 24 self.assertEqual(module.__name__, 'top_level') 25 26 def test_absolute_package_import(self): 27 # Test importing a module from a package with an absolute name. 28 pkg_name = 'pkg' 29 pkg_long_name = '{0}.__init__'.format(pkg_name) 30 name = '{0}.mod'.format(pkg_name) 31 with test_util.mock_modules(pkg_long_name, name) as mock: 32 with test_util.import_state(meta_path=[mock]): 33 module = self.init.import_module(name) 34 self.assertEqual(module.__name__, name) 35 36 def test_shallow_relative_package_import(self): 37 # Test importing a module from a package through a relative import. 38 pkg_name = 'pkg' 39 pkg_long_name = '{0}.__init__'.format(pkg_name) 40 module_name = 'mod' 41 absolute_name = '{0}.{1}'.format(pkg_name, module_name) 42 relative_name = '.{0}'.format(module_name) 43 with test_util.mock_modules(pkg_long_name, absolute_name) as mock: 44 with test_util.import_state(meta_path=[mock]): 45 self.init.import_module(pkg_name) 46 module = self.init.import_module(relative_name, pkg_name) 47 self.assertEqual(module.__name__, absolute_name) 48 49 def test_deep_relative_package_import(self): 50 modules = ['a.__init__', 'a.b.__init__', 'a.c'] 51 with test_util.mock_modules(*modules) as mock: 52 with test_util.import_state(meta_path=[mock]): 53 self.init.import_module('a') 54 self.init.import_module('a.b') 55 module = self.init.import_module('..c', 'a.b') 56 self.assertEqual(module.__name__, 'a.c') 57 58 def test_absolute_import_with_package(self): 59 # Test importing a module from a package with an absolute name with 60 # the 'package' argument given. 61 pkg_name = 'pkg' 62 pkg_long_name = '{0}.__init__'.format(pkg_name) 63 name = '{0}.mod'.format(pkg_name) 64 with test_util.mock_modules(pkg_long_name, name) as mock: 65 with test_util.import_state(meta_path=[mock]): 66 self.init.import_module(pkg_name) 67 module = self.init.import_module(name, pkg_name) 68 self.assertEqual(module.__name__, name) 69 70 def test_relative_import_wo_package(self): 71 # Relative imports cannot happen without the 'package' argument being 72 # set. 73 with self.assertRaises(TypeError): 74 self.init.import_module('.support') 75 76 77 def test_loaded_once(self): 78 # Issue #13591: Modules should only be loaded once when 79 # initializing the parent package attempts to import the 80 # module currently being imported. 81 b_load_count = 0 82 def load_a(): 83 self.init.import_module('a.b') 84 def load_b(): 85 nonlocal b_load_count 86 b_load_count += 1 87 code = {'a': load_a, 'a.b': load_b} 88 modules = ['a.__init__', 'a.b'] 89 with test_util.mock_modules(*modules, module_code=code) as mock: 90 with test_util.import_state(meta_path=[mock]): 91 self.init.import_module('a.b') 92 self.assertEqual(b_load_count, 1) 93 94 95(Frozen_ImportModuleTests, 96 Source_ImportModuleTests 97 ) = test_util.test_both(ImportModuleTests, init=init) 98 99 100class FindLoaderTests: 101 102 FakeMetaFinder = None 103 104 def test_sys_modules(self): 105 # If a module with __loader__ is in sys.modules, then return it. 106 name = 'some_mod' 107 with test_util.uncache(name): 108 module = types.ModuleType(name) 109 loader = 'a loader!' 110 module.__loader__ = loader 111 sys.modules[name] = module 112 with warnings.catch_warnings(): 113 warnings.simplefilter('ignore', DeprecationWarning) 114 found = self.init.find_loader(name) 115 self.assertEqual(loader, found) 116 117 def test_sys_modules_loader_is_None(self): 118 # If sys.modules[name].__loader__ is None, raise ValueError. 119 name = 'some_mod' 120 with test_util.uncache(name): 121 module = types.ModuleType(name) 122 module.__loader__ = None 123 sys.modules[name] = module 124 with self.assertRaises(ValueError): 125 with warnings.catch_warnings(): 126 warnings.simplefilter('ignore', DeprecationWarning) 127 self.init.find_loader(name) 128 129 def test_sys_modules_loader_is_not_set(self): 130 # Should raise ValueError 131 # Issue #17099 132 name = 'some_mod' 133 with test_util.uncache(name): 134 module = types.ModuleType(name) 135 try: 136 del module.__loader__ 137 except AttributeError: 138 pass 139 sys.modules[name] = module 140 with self.assertRaises(ValueError): 141 with warnings.catch_warnings(): 142 warnings.simplefilter('ignore', DeprecationWarning) 143 self.init.find_loader(name) 144 145 def test_success(self): 146 # Return the loader found on sys.meta_path. 147 name = 'some_mod' 148 with test_util.uncache(name): 149 with test_util.import_state(meta_path=[self.FakeMetaFinder]): 150 with warnings.catch_warnings(): 151 warnings.simplefilter('ignore', DeprecationWarning) 152 self.assertEqual((name, None), self.init.find_loader(name)) 153 154 def test_success_path(self): 155 # Searching on a path should work. 156 name = 'some_mod' 157 path = 'path to some place' 158 with test_util.uncache(name): 159 with test_util.import_state(meta_path=[self.FakeMetaFinder]): 160 with warnings.catch_warnings(): 161 warnings.simplefilter('ignore', DeprecationWarning) 162 self.assertEqual((name, path), 163 self.init.find_loader(name, path)) 164 165 def test_nothing(self): 166 # None is returned upon failure to find a loader. 167 with warnings.catch_warnings(): 168 warnings.simplefilter('ignore', DeprecationWarning) 169 self.assertIsNone(self.init.find_loader('nevergoingtofindthismodule')) 170 171 172class FindLoaderPEP451Tests(FindLoaderTests): 173 174 class FakeMetaFinder: 175 @staticmethod 176 def find_spec(name, path=None, target=None): 177 return machinery['Source'].ModuleSpec(name, (name, path)) 178 179 180(Frozen_FindLoaderPEP451Tests, 181 Source_FindLoaderPEP451Tests 182 ) = test_util.test_both(FindLoaderPEP451Tests, init=init) 183 184 185class FindLoaderPEP302Tests(FindLoaderTests): 186 187 class FakeMetaFinder: 188 @staticmethod 189 def find_module(name, path=None): 190 return name, path 191 192 193(Frozen_FindLoaderPEP302Tests, 194 Source_FindLoaderPEP302Tests 195 ) = test_util.test_both(FindLoaderPEP302Tests, init=init) 196 197 198class ReloadTests: 199 200 def test_reload_modules(self): 201 for mod in ('tokenize', 'time', 'marshal'): 202 with self.subTest(module=mod): 203 with support.CleanImport(mod): 204 module = self.init.import_module(mod) 205 self.init.reload(module) 206 207 def test_module_replaced(self): 208 def code(): 209 import sys 210 module = type(sys)('top_level') 211 module.spam = 3 212 sys.modules['top_level'] = module 213 mock = test_util.mock_modules('top_level', 214 module_code={'top_level': code}) 215 with mock: 216 with test_util.import_state(meta_path=[mock]): 217 module = self.init.import_module('top_level') 218 reloaded = self.init.reload(module) 219 actual = sys.modules['top_level'] 220 self.assertEqual(actual.spam, 3) 221 self.assertEqual(reloaded.spam, 3) 222 223 def test_reload_missing_loader(self): 224 with support.CleanImport('types'): 225 import types 226 loader = types.__loader__ 227 del types.__loader__ 228 reloaded = self.init.reload(types) 229 230 self.assertIs(reloaded, types) 231 self.assertIs(sys.modules['types'], types) 232 self.assertEqual(reloaded.__loader__.path, loader.path) 233 234 def test_reload_loader_replaced(self): 235 with support.CleanImport('types'): 236 import types 237 types.__loader__ = None 238 self.init.invalidate_caches() 239 reloaded = self.init.reload(types) 240 241 self.assertIsNot(reloaded.__loader__, None) 242 self.assertIs(reloaded, types) 243 self.assertIs(sys.modules['types'], types) 244 245 def test_reload_location_changed(self): 246 name = 'spam' 247 with support.temp_cwd(None) as cwd: 248 with test_util.uncache('spam'): 249 with support.DirsOnSysPath(cwd): 250 # Start as a plain module. 251 self.init.invalidate_caches() 252 path = os.path.join(cwd, name + '.py') 253 cached = self.util.cache_from_source(path) 254 expected = {'__name__': name, 255 '__package__': '', 256 '__file__': path, 257 '__cached__': cached, 258 '__doc__': None, 259 } 260 support.create_empty_file(path) 261 module = self.init.import_module(name) 262 ns = vars(module).copy() 263 loader = ns.pop('__loader__') 264 spec = ns.pop('__spec__') 265 ns.pop('__builtins__', None) # An implementation detail. 266 self.assertEqual(spec.name, name) 267 self.assertEqual(spec.loader, loader) 268 self.assertEqual(loader.path, path) 269 self.assertEqual(ns, expected) 270 271 # Change to a package. 272 self.init.invalidate_caches() 273 init_path = os.path.join(cwd, name, '__init__.py') 274 cached = self.util.cache_from_source(init_path) 275 expected = {'__name__': name, 276 '__package__': name, 277 '__file__': init_path, 278 '__cached__': cached, 279 '__path__': [os.path.dirname(init_path)], 280 '__doc__': None, 281 } 282 os.mkdir(name) 283 os.rename(path, init_path) 284 reloaded = self.init.reload(module) 285 ns = vars(reloaded).copy() 286 loader = ns.pop('__loader__') 287 spec = ns.pop('__spec__') 288 ns.pop('__builtins__', None) # An implementation detail. 289 self.assertEqual(spec.name, name) 290 self.assertEqual(spec.loader, loader) 291 self.assertIs(reloaded, module) 292 self.assertEqual(loader.path, init_path) 293 self.maxDiff = None 294 self.assertEqual(ns, expected) 295 296 def test_reload_namespace_changed(self): 297 name = 'spam' 298 with support.temp_cwd(None) as cwd: 299 with test_util.uncache('spam'): 300 with support.DirsOnSysPath(cwd): 301 # Start as a namespace package. 302 self.init.invalidate_caches() 303 bad_path = os.path.join(cwd, name, '__init.py') 304 cached = self.util.cache_from_source(bad_path) 305 expected = {'__name__': name, 306 '__package__': name, 307 '__doc__': None, 308 '__file__': None, 309 } 310 os.mkdir(name) 311 with open(bad_path, 'w') as init_file: 312 init_file.write('eggs = None') 313 module = self.init.import_module(name) 314 ns = vars(module).copy() 315 loader = ns.pop('__loader__') 316 path = ns.pop('__path__') 317 spec = ns.pop('__spec__') 318 ns.pop('__builtins__', None) # An implementation detail. 319 self.assertEqual(spec.name, name) 320 self.assertIsNotNone(spec.loader) 321 self.assertIsNotNone(loader) 322 self.assertEqual(spec.loader, loader) 323 self.assertEqual(set(path), 324 set([os.path.dirname(bad_path)])) 325 with self.assertRaises(AttributeError): 326 # a NamespaceLoader 327 loader.path 328 self.assertEqual(ns, expected) 329 330 # Change to a regular package. 331 self.init.invalidate_caches() 332 init_path = os.path.join(cwd, name, '__init__.py') 333 cached = self.util.cache_from_source(init_path) 334 expected = {'__name__': name, 335 '__package__': name, 336 '__file__': init_path, 337 '__cached__': cached, 338 '__path__': [os.path.dirname(init_path)], 339 '__doc__': None, 340 'eggs': None, 341 } 342 os.rename(bad_path, init_path) 343 reloaded = self.init.reload(module) 344 ns = vars(reloaded).copy() 345 loader = ns.pop('__loader__') 346 spec = ns.pop('__spec__') 347 ns.pop('__builtins__', None) # An implementation detail. 348 self.assertEqual(spec.name, name) 349 self.assertEqual(spec.loader, loader) 350 self.assertIs(reloaded, module) 351 self.assertEqual(loader.path, init_path) 352 self.assertEqual(ns, expected) 353 354 def test_reload_submodule(self): 355 # See #19851. 356 name = 'spam' 357 subname = 'ham' 358 with test_util.temp_module(name, pkg=True) as pkg_dir: 359 fullname, _ = test_util.submodule(name, subname, pkg_dir) 360 ham = self.init.import_module(fullname) 361 reloaded = self.init.reload(ham) 362 self.assertIs(reloaded, ham) 363 364 def test_module_missing_spec(self): 365 #Test that reload() throws ModuleNotFounderror when reloading 366 # a module who's missing a spec. (bpo-29851) 367 name = 'spam' 368 with test_util.uncache(name): 369 module = sys.modules[name] = types.ModuleType(name) 370 # Sanity check by attempting an import. 371 module = self.init.import_module(name) 372 self.assertIsNone(module.__spec__) 373 with self.assertRaises(ModuleNotFoundError): 374 self.init.reload(module) 375 376 377(Frozen_ReloadTests, 378 Source_ReloadTests 379 ) = test_util.test_both(ReloadTests, init=init, util=util) 380 381 382class InvalidateCacheTests: 383 384 def test_method_called(self): 385 # If defined the method should be called. 386 class InvalidatingNullFinder: 387 def __init__(self, *ignored): 388 self.called = False 389 def find_module(self, *args): 390 return None 391 def invalidate_caches(self): 392 self.called = True 393 394 key = 'gobledeegook' 395 meta_ins = InvalidatingNullFinder() 396 path_ins = InvalidatingNullFinder() 397 sys.meta_path.insert(0, meta_ins) 398 self.addCleanup(lambda: sys.path_importer_cache.__delitem__(key)) 399 sys.path_importer_cache[key] = path_ins 400 self.addCleanup(lambda: sys.meta_path.remove(meta_ins)) 401 self.init.invalidate_caches() 402 self.assertTrue(meta_ins.called) 403 self.assertTrue(path_ins.called) 404 405 def test_method_lacking(self): 406 # There should be no issues if the method is not defined. 407 key = 'gobbledeegook' 408 sys.path_importer_cache[key] = None 409 self.addCleanup(lambda: sys.path_importer_cache.pop(key, None)) 410 self.init.invalidate_caches() # Shouldn't trigger an exception. 411 412 413(Frozen_InvalidateCacheTests, 414 Source_InvalidateCacheTests 415 ) = test_util.test_both(InvalidateCacheTests, init=init) 416 417 418class FrozenImportlibTests(unittest.TestCase): 419 420 def test_no_frozen_importlib(self): 421 # Should be able to import w/o _frozen_importlib being defined. 422 # Can't do an isinstance() check since separate copies of importlib 423 # may have been used for import, so just check the name is not for the 424 # frozen loader. 425 source_init = init['Source'] 426 self.assertNotEqual(source_init.__loader__.__class__.__name__, 427 'FrozenImporter') 428 429 430class StartupTests: 431 432 def test_everyone_has___loader__(self): 433 # Issue #17098: all modules should have __loader__ defined. 434 for name, module in sys.modules.items(): 435 if isinstance(module, types.ModuleType): 436 with self.subTest(name=name): 437 self.assertTrue(hasattr(module, '__loader__'), 438 '{!r} lacks a __loader__ attribute'.format(name)) 439 if self.machinery.BuiltinImporter.find_module(name): 440 self.assertIsNot(module.__loader__, None) 441 elif self.machinery.FrozenImporter.find_module(name): 442 self.assertIsNot(module.__loader__, None) 443 444 def test_everyone_has___spec__(self): 445 for name, module in sys.modules.items(): 446 if isinstance(module, types.ModuleType): 447 with self.subTest(name=name): 448 self.assertTrue(hasattr(module, '__spec__')) 449 if self.machinery.BuiltinImporter.find_module(name): 450 self.assertIsNot(module.__spec__, None) 451 elif self.machinery.FrozenImporter.find_module(name): 452 self.assertIsNot(module.__spec__, None) 453 454 455(Frozen_StartupTests, 456 Source_StartupTests 457 ) = test_util.test_both(StartupTests, machinery=machinery) 458 459 460if __name__ == '__main__': 461 unittest.main() 462