1 from . import util as test_util 2 3 init = test_util.import_importlib('importlib') 4 util = test_util.import_importlib('importlib.util') 5 machinery = test_util.import_importlib('importlib.machinery') 6 7 import os.path 8 import sys 9 from test import support 10 import types 11 import unittest 12 import warnings 13 14 15 class 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 100 class 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 172 class 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 185 class 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 198 class ReloadTests: 199 200 """Test module reloading for builtin and extension modules.""" 201 202 def test_reload_modules(self): 203 for mod in ('tokenize', 'time', 'marshal'): 204 with self.subTest(module=mod): 205 with support.CleanImport(mod): 206 module = self.init.import_module(mod) 207 self.init.reload(module) 208 209 def test_module_replaced(self): 210 def code(): 211 import sys 212 module = type(sys)('top_level') 213 module.spam = 3 214 sys.modules['top_level'] = module 215 mock = test_util.mock_modules('top_level', 216 module_code={'top_level': code}) 217 with mock: 218 with test_util.import_state(meta_path=[mock]): 219 module = self.init.import_module('top_level') 220 reloaded = self.init.reload(module) 221 actual = sys.modules['top_level'] 222 self.assertEqual(actual.spam, 3) 223 self.assertEqual(reloaded.spam, 3) 224 225 def test_reload_missing_loader(self): 226 with support.CleanImport('types'): 227 import types 228 loader = types.__loader__ 229 del types.__loader__ 230 reloaded = self.init.reload(types) 231 232 self.assertIs(reloaded, types) 233 self.assertIs(sys.modules['types'], types) 234 self.assertEqual(reloaded.__loader__.path, loader.path) 235 236 def test_reload_loader_replaced(self): 237 with support.CleanImport('types'): 238 import types 239 types.__loader__ = None 240 self.init.invalidate_caches() 241 reloaded = self.init.reload(types) 242 243 self.assertIsNot(reloaded.__loader__, None) 244 self.assertIs(reloaded, types) 245 self.assertIs(sys.modules['types'], types) 246 247 def test_reload_location_changed(self): 248 name = 'spam' 249 with support.temp_cwd(None) as cwd: 250 with test_util.uncache('spam'): 251 with support.DirsOnSysPath(cwd): 252 # Start as a plain module. 253 self.init.invalidate_caches() 254 path = os.path.join(cwd, name + '.py') 255 cached = self.util.cache_from_source(path) 256 expected = {'__name__': name, 257 '__package__': '', 258 '__file__': path, 259 '__cached__': cached, 260 '__doc__': None, 261 } 262 support.create_empty_file(path) 263 module = self.init.import_module(name) 264 ns = vars(module).copy() 265 loader = ns.pop('__loader__') 266 spec = ns.pop('__spec__') 267 ns.pop('__builtins__', None) # An implementation detail. 268 self.assertEqual(spec.name, name) 269 self.assertEqual(spec.loader, loader) 270 self.assertEqual(loader.path, path) 271 self.assertEqual(ns, expected) 272 273 # Change to a package. 274 self.init.invalidate_caches() 275 init_path = os.path.join(cwd, name, '__init__.py') 276 cached = self.util.cache_from_source(init_path) 277 expected = {'__name__': name, 278 '__package__': name, 279 '__file__': init_path, 280 '__cached__': cached, 281 '__path__': [os.path.dirname(init_path)], 282 '__doc__': None, 283 } 284 os.mkdir(name) 285 os.rename(path, init_path) 286 reloaded = self.init.reload(module) 287 ns = vars(reloaded).copy() 288 loader = ns.pop('__loader__') 289 spec = ns.pop('__spec__') 290 ns.pop('__builtins__', None) # An implementation detail. 291 self.assertEqual(spec.name, name) 292 self.assertEqual(spec.loader, loader) 293 self.assertIs(reloaded, module) 294 self.assertEqual(loader.path, init_path) 295 self.maxDiff = None 296 self.assertEqual(ns, expected) 297 298 def test_reload_namespace_changed(self): 299 name = 'spam' 300 with support.temp_cwd(None) as cwd: 301 with test_util.uncache('spam'): 302 with support.DirsOnSysPath(cwd): 303 # Start as a namespace package. 304 self.init.invalidate_caches() 305 bad_path = os.path.join(cwd, name, '__init.py') 306 cached = self.util.cache_from_source(bad_path) 307 expected = {'__name__': name, 308 '__package__': name, 309 '__doc__': None, 310 } 311 os.mkdir(name) 312 with open(bad_path, 'w') as init_file: 313 init_file.write('eggs = None') 314 module = self.init.import_module(name) 315 ns = vars(module).copy() 316 loader = ns.pop('__loader__') 317 path = ns.pop('__path__') 318 spec = ns.pop('__spec__') 319 ns.pop('__builtins__', None) # An implementation detail. 320 self.assertEqual(spec.name, name) 321 self.assertIs(spec.loader, None) 322 self.assertIsNot(loader, None) 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 365 (Frozen_ReloadTests, 366 Source_ReloadTests 367 ) = test_util.test_both(ReloadTests, init=init, util=util) 368 369 370 class InvalidateCacheTests: 371 372 def test_method_called(self): 373 # If defined the method should be called. 374 class InvalidatingNullFinder: 375 def __init__(self, *ignored): 376 self.called = False 377 def find_module(self, *args): 378 return None 379 def invalidate_caches(self): 380 self.called = True 381 382 key = 'gobledeegook' 383 meta_ins = InvalidatingNullFinder() 384 path_ins = InvalidatingNullFinder() 385 sys.meta_path.insert(0, meta_ins) 386 self.addCleanup(lambda: sys.path_importer_cache.__delitem__(key)) 387 sys.path_importer_cache[key] = path_ins 388 self.addCleanup(lambda: sys.meta_path.remove(meta_ins)) 389 self.init.invalidate_caches() 390 self.assertTrue(meta_ins.called) 391 self.assertTrue(path_ins.called) 392 393 def test_method_lacking(self): 394 # There should be no issues if the method is not defined. 395 key = 'gobbledeegook' 396 sys.path_importer_cache[key] = None 397 self.addCleanup(lambda: sys.path_importer_cache.__delitem__(key)) 398 self.init.invalidate_caches() # Shouldn't trigger an exception. 399 400 401 (Frozen_InvalidateCacheTests, 402 Source_InvalidateCacheTests 403 ) = test_util.test_both(InvalidateCacheTests, init=init) 404 405 406 class FrozenImportlibTests(unittest.TestCase): 407 408 def test_no_frozen_importlib(self): 409 # Should be able to import w/o _frozen_importlib being defined. 410 # Can't do an isinstance() check since separate copies of importlib 411 # may have been used for import, so just check the name is not for the 412 # frozen loader. 413 source_init = init['Source'] 414 self.assertNotEqual(source_init.__loader__.__class__.__name__, 415 'FrozenImporter') 416 417 418 class StartupTests: 419 420 def test_everyone_has___loader__(self): 421 # Issue #17098: all modules should have __loader__ defined. 422 for name, module in sys.modules.items(): 423 if isinstance(module, types.ModuleType): 424 with self.subTest(name=name): 425 self.assertTrue(hasattr(module, '__loader__'), 426 '{!r} lacks a __loader__ attribute'.format(name)) 427 if self.machinery.BuiltinImporter.find_module(name): 428 self.assertIsNot(module.__loader__, None) 429 elif self.machinery.FrozenImporter.find_module(name): 430 self.assertIsNot(module.__loader__, None) 431 432 def test_everyone_has___spec__(self): 433 for name, module in sys.modules.items(): 434 if isinstance(module, types.ModuleType): 435 with self.subTest(name=name): 436 self.assertTrue(hasattr(module, '__spec__')) 437 if self.machinery.BuiltinImporter.find_module(name): 438 self.assertIsNot(module.__spec__, None) 439 elif self.machinery.FrozenImporter.find_module(name): 440 self.assertIsNot(module.__spec__, None) 441 442 443 (Frozen_StartupTests, 444 Source_StartupTests 445 ) = test_util.test_both(StartupTests, machinery=machinery) 446 447 448 if __name__ == '__main__': 449 unittest.main() 450