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