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