python (3.12.0)
1 import io
2 import marshal
3 import os
4 import sys
5 from test.support import import_helper
6 import types
7 import unittest
8 from unittest import mock
9 import warnings
10
11 from test.test_importlib import util as test_util
12
13 init = test_util.import_importlib('importlib')
14 abc = test_util.import_importlib('importlib.abc')
15 machinery = test_util.import_importlib('importlib.machinery')
16 util = test_util.import_importlib('importlib.util')
17
18
19 ##### Inheritance ##############################################################
20 class ESC[4;38;5;81mInheritanceTests:
21
22 """Test that the specified class is a subclass/superclass of the expected
23 classes."""
24
25 subclasses = []
26 superclasses = []
27
28 def setUp(self):
29 self.superclasses = [getattr(self.abc, class_name)
30 for class_name in self.superclass_names]
31 if hasattr(self, 'subclass_names'):
32 # Because test.support.import_fresh_module() creates a new
33 # importlib._bootstrap per module, inheritance checks fail when
34 # checking across module boundaries (i.e. the _bootstrap in abc is
35 # not the same as the one in machinery). That means stealing one of
36 # the modules from the other to make sure the same instance is used.
37 machinery = self.abc.machinery
38 self.subclasses = [getattr(machinery, class_name)
39 for class_name in self.subclass_names]
40 assert self.subclasses or self.superclasses, self.__class__
41 self.__test = getattr(self.abc, self._NAME)
42
43 def test_subclasses(self):
44 # Test that the expected subclasses inherit.
45 for subclass in self.subclasses:
46 self.assertTrue(issubclass(subclass, self.__test),
47 "{0} is not a subclass of {1}".format(subclass, self.__test))
48
49 def test_superclasses(self):
50 # Test that the class inherits from the expected superclasses.
51 for superclass in self.superclasses:
52 self.assertTrue(issubclass(self.__test, superclass),
53 "{0} is not a superclass of {1}".format(superclass, self.__test))
54
55
56 class ESC[4;38;5;81mMetaPathFinder(ESC[4;38;5;149mInheritanceTests):
57 superclass_names = []
58 subclass_names = ['BuiltinImporter', 'FrozenImporter', 'PathFinder',
59 'WindowsRegistryFinder']
60
61
62 (Frozen_MetaPathFinderInheritanceTests,
63 Source_MetaPathFinderInheritanceTests
64 ) = test_util.test_both(MetaPathFinder, abc=abc)
65
66
67 class ESC[4;38;5;81mPathEntryFinder(ESC[4;38;5;149mInheritanceTests):
68 superclass_names = []
69 subclass_names = ['FileFinder']
70
71
72 (Frozen_PathEntryFinderInheritanceTests,
73 Source_PathEntryFinderInheritanceTests
74 ) = test_util.test_both(PathEntryFinder, abc=abc)
75
76
77 class ESC[4;38;5;81mResourceLoader(ESC[4;38;5;149mInheritanceTests):
78 superclass_names = ['Loader']
79
80
81 (Frozen_ResourceLoaderInheritanceTests,
82 Source_ResourceLoaderInheritanceTests
83 ) = test_util.test_both(ResourceLoader, abc=abc)
84
85
86 class ESC[4;38;5;81mInspectLoader(ESC[4;38;5;149mInheritanceTests):
87 superclass_names = ['Loader']
88 subclass_names = ['BuiltinImporter', 'FrozenImporter', 'ExtensionFileLoader']
89
90
91 (Frozen_InspectLoaderInheritanceTests,
92 Source_InspectLoaderInheritanceTests
93 ) = test_util.test_both(InspectLoader, abc=abc)
94
95
96 class ESC[4;38;5;81mExecutionLoader(ESC[4;38;5;149mInheritanceTests):
97 superclass_names = ['InspectLoader']
98 subclass_names = ['ExtensionFileLoader']
99
100
101 (Frozen_ExecutionLoaderInheritanceTests,
102 Source_ExecutionLoaderInheritanceTests
103 ) = test_util.test_both(ExecutionLoader, abc=abc)
104
105
106 class ESC[4;38;5;81mFileLoader(ESC[4;38;5;149mInheritanceTests):
107 superclass_names = ['ResourceLoader', 'ExecutionLoader']
108 subclass_names = ['SourceFileLoader', 'SourcelessFileLoader']
109
110
111 (Frozen_FileLoaderInheritanceTests,
112 Source_FileLoaderInheritanceTests
113 ) = test_util.test_both(FileLoader, abc=abc)
114
115
116 class ESC[4;38;5;81mSourceLoader(ESC[4;38;5;149mInheritanceTests):
117 superclass_names = ['ResourceLoader', 'ExecutionLoader']
118 subclass_names = ['SourceFileLoader']
119
120
121 (Frozen_SourceLoaderInheritanceTests,
122 Source_SourceLoaderInheritanceTests
123 ) = test_util.test_both(SourceLoader, abc=abc)
124
125
126 ##### Default return values ####################################################
127
128 def make_abc_subclasses(base_class, name=None, inst=False, **kwargs):
129 if name is None:
130 name = base_class.__name__
131 base = {kind: getattr(splitabc, name)
132 for kind, splitabc in abc.items()}
133 return {cls._KIND: cls() if inst else cls
134 for cls in test_util.split_frozen(base_class, base, **kwargs)}
135
136
137 class ESC[4;38;5;81mABCTestHarness:
138
139 @property
140 def ins(self):
141 # Lazily set ins on the class.
142 cls = self.SPLIT[self._KIND]
143 ins = cls()
144 self.__class__.ins = ins
145 return ins
146
147
148 class ESC[4;38;5;81mMetaPathFinder:
149
150 pass
151
152
153 class ESC[4;38;5;81mMetaPathFinderDefaultsTests(ESC[4;38;5;149mABCTestHarness):
154
155 SPLIT = make_abc_subclasses(MetaPathFinder)
156
157 def test_invalidate_caches(self):
158 # Calling the method is a no-op.
159 self.ins.invalidate_caches()
160
161
162 (Frozen_MPFDefaultTests,
163 Source_MPFDefaultTests
164 ) = test_util.test_both(MetaPathFinderDefaultsTests)
165
166
167 class ESC[4;38;5;81mPathEntryFinder:
168
169 pass
170
171
172 class ESC[4;38;5;81mPathEntryFinderDefaultsTests(ESC[4;38;5;149mABCTestHarness):
173
174 SPLIT = make_abc_subclasses(PathEntryFinder)
175
176 def test_invalidate_caches(self):
177 # Should be a no-op.
178 self.ins.invalidate_caches()
179
180
181 (Frozen_PEFDefaultTests,
182 Source_PEFDefaultTests
183 ) = test_util.test_both(PathEntryFinderDefaultsTests)
184
185
186 class ESC[4;38;5;81mLoader:
187
188 pass
189
190
191 class ESC[4;38;5;81mLoaderDefaultsTests(ESC[4;38;5;149mABCTestHarness):
192
193 SPLIT = make_abc_subclasses(Loader)
194
195 def test_create_module(self):
196 spec = 'a spec'
197 self.assertIsNone(self.ins.create_module(spec))
198
199 def test_load_module(self):
200 with self.assertRaises(ImportError):
201 self.ins.load_module('something')
202
203 def test_module_repr(self):
204 mod = types.ModuleType('blah')
205 with warnings.catch_warnings():
206 warnings.simplefilter("ignore", DeprecationWarning)
207 original_repr = repr(mod)
208 mod.__loader__ = self.ins
209 # Should still return a proper repr.
210 self.assertTrue(repr(mod))
211
212
213 (Frozen_LDefaultTests,
214 SourceLDefaultTests
215 ) = test_util.test_both(LoaderDefaultsTests)
216
217
218 class ESC[4;38;5;81mResourceLoader(ESC[4;38;5;149mLoader):
219
220 def get_data(self, path):
221 return super().get_data(path)
222
223
224 class ESC[4;38;5;81mResourceLoaderDefaultsTests(ESC[4;38;5;149mABCTestHarness):
225
226 SPLIT = make_abc_subclasses(ResourceLoader)
227
228 def test_get_data(self):
229 with self.assertRaises(IOError):
230 self.ins.get_data('/some/path')
231
232
233 (Frozen_RLDefaultTests,
234 Source_RLDefaultTests
235 ) = test_util.test_both(ResourceLoaderDefaultsTests)
236
237
238 class ESC[4;38;5;81mInspectLoader(ESC[4;38;5;149mLoader):
239
240 def is_package(self, fullname):
241 return super().is_package(fullname)
242
243 def get_source(self, fullname):
244 return super().get_source(fullname)
245
246
247 SPLIT_IL = make_abc_subclasses(InspectLoader)
248
249
250 class ESC[4;38;5;81mInspectLoaderDefaultsTests(ESC[4;38;5;149mABCTestHarness):
251
252 SPLIT = SPLIT_IL
253
254 def test_is_package(self):
255 with self.assertRaises(ImportError):
256 self.ins.is_package('blah')
257
258 def test_get_source(self):
259 with self.assertRaises(ImportError):
260 self.ins.get_source('blah')
261
262
263 (Frozen_ILDefaultTests,
264 Source_ILDefaultTests
265 ) = test_util.test_both(InspectLoaderDefaultsTests)
266
267
268 class ESC[4;38;5;81mExecutionLoader(ESC[4;38;5;149mInspectLoader):
269
270 def get_filename(self, fullname):
271 return super().get_filename(fullname)
272
273
274 SPLIT_EL = make_abc_subclasses(ExecutionLoader)
275
276
277 class ESC[4;38;5;81mExecutionLoaderDefaultsTests(ESC[4;38;5;149mABCTestHarness):
278
279 SPLIT = SPLIT_EL
280
281 def test_get_filename(self):
282 with self.assertRaises(ImportError):
283 self.ins.get_filename('blah')
284
285
286 (Frozen_ELDefaultTests,
287 Source_ELDefaultsTests
288 ) = test_util.test_both(InspectLoaderDefaultsTests)
289
290
291 class ESC[4;38;5;81mResourceReader:
292
293 def open_resource(self, *args, **kwargs):
294 return super().open_resource(*args, **kwargs)
295
296 def resource_path(self, *args, **kwargs):
297 return super().resource_path(*args, **kwargs)
298
299 def is_resource(self, *args, **kwargs):
300 return super().is_resource(*args, **kwargs)
301
302 def contents(self, *args, **kwargs):
303 return super().contents(*args, **kwargs)
304
305
306 ##### MetaPathFinder concrete methods ##########################################
307 class ESC[4;38;5;81mMetaPathFinderFindModuleTests:
308
309 @classmethod
310 def finder(cls, spec):
311 class ESC[4;38;5;81mMetaPathSpecFinder(ESC[4;38;5;149mclsESC[4;38;5;149m.ESC[4;38;5;149mabcESC[4;38;5;149m.ESC[4;38;5;149mMetaPathFinder):
312
313 def find_spec(self, fullname, path, target=None):
314 self.called_for = fullname, path
315 return spec
316
317 return MetaPathSpecFinder()
318
319 def test_find_spec_with_explicit_target(self):
320 loader = object()
321 spec = self.util.spec_from_loader('blah', loader)
322 finder = self.finder(spec)
323 found = finder.find_spec('blah', 'blah', None)
324 self.assertEqual(found, spec)
325
326 def test_no_spec(self):
327 finder = self.finder(None)
328 path = ['a', 'b', 'c']
329 name = 'blah'
330 found = finder.find_spec(name, path, None)
331 self.assertIsNone(found)
332 self.assertEqual(name, finder.called_for[0])
333 self.assertEqual(path, finder.called_for[1])
334
335 def test_spec(self):
336 loader = object()
337 spec = self.util.spec_from_loader('blah', loader)
338 finder = self.finder(spec)
339 found = finder.find_spec('blah', None)
340 self.assertIs(found, spec)
341
342
343 (Frozen_MPFFindModuleTests,
344 Source_MPFFindModuleTests
345 ) = test_util.test_both(MetaPathFinderFindModuleTests, abc=abc, util=util)
346
347
348 ##### Loader concrete methods ##################################################
349 class ESC[4;38;5;81mLoaderLoadModuleTests:
350
351 def loader(self):
352 class ESC[4;38;5;81mSpecLoader(ESC[4;38;5;149mselfESC[4;38;5;149m.ESC[4;38;5;149mabcESC[4;38;5;149m.ESC[4;38;5;149mLoader):
353 found = None
354 def exec_module(self, module):
355 self.found = module
356
357 def is_package(self, fullname):
358 """Force some non-default module state to be set."""
359 return True
360
361 return SpecLoader()
362
363 def test_fresh(self):
364 with warnings.catch_warnings():
365 warnings.simplefilter("ignore", DeprecationWarning)
366 loader = self.loader()
367 name = 'blah'
368 with test_util.uncache(name):
369 loader.load_module(name)
370 module = loader.found
371 self.assertIs(sys.modules[name], module)
372 self.assertEqual(loader, module.__loader__)
373 self.assertEqual(loader, module.__spec__.loader)
374 self.assertEqual(name, module.__name__)
375 self.assertEqual(name, module.__spec__.name)
376 self.assertIsNotNone(module.__path__)
377 self.assertIsNotNone(module.__path__,
378 module.__spec__.submodule_search_locations)
379
380 def test_reload(self):
381 with warnings.catch_warnings():
382 warnings.simplefilter("ignore", DeprecationWarning)
383 name = 'blah'
384 loader = self.loader()
385 module = types.ModuleType(name)
386 module.__spec__ = self.util.spec_from_loader(name, loader)
387 module.__loader__ = loader
388 with test_util.uncache(name):
389 sys.modules[name] = module
390 loader.load_module(name)
391 found = loader.found
392 self.assertIs(found, sys.modules[name])
393 self.assertIs(module, sys.modules[name])
394
395
396 (Frozen_LoaderLoadModuleTests,
397 Source_LoaderLoadModuleTests
398 ) = test_util.test_both(LoaderLoadModuleTests, abc=abc, util=util)
399
400
401 ##### InspectLoader concrete methods ###########################################
402 class ESC[4;38;5;81mInspectLoaderSourceToCodeTests:
403
404 def source_to_module(self, data, path=None):
405 """Help with source_to_code() tests."""
406 module = types.ModuleType('blah')
407 loader = self.InspectLoaderSubclass()
408 if path is None:
409 code = loader.source_to_code(data)
410 else:
411 code = loader.source_to_code(data, path)
412 exec(code, module.__dict__)
413 return module
414
415 def test_source_to_code_source(self):
416 # Since compile() can handle strings, so should source_to_code().
417 source = 'attr = 42'
418 module = self.source_to_module(source)
419 self.assertTrue(hasattr(module, 'attr'))
420 self.assertEqual(module.attr, 42)
421
422 def test_source_to_code_bytes(self):
423 # Since compile() can handle bytes, so should source_to_code().
424 source = b'attr = 42'
425 module = self.source_to_module(source)
426 self.assertTrue(hasattr(module, 'attr'))
427 self.assertEqual(module.attr, 42)
428
429 def test_source_to_code_path(self):
430 # Specifying a path should set it for the code object.
431 path = 'path/to/somewhere'
432 loader = self.InspectLoaderSubclass()
433 code = loader.source_to_code('', path)
434 self.assertEqual(code.co_filename, path)
435
436 def test_source_to_code_no_path(self):
437 # Not setting a path should still work and be set to <string> since that
438 # is a pre-existing practice as a default to compile().
439 loader = self.InspectLoaderSubclass()
440 code = loader.source_to_code('')
441 self.assertEqual(code.co_filename, '<string>')
442
443
444 (Frozen_ILSourceToCodeTests,
445 Source_ILSourceToCodeTests
446 ) = test_util.test_both(InspectLoaderSourceToCodeTests,
447 InspectLoaderSubclass=SPLIT_IL)
448
449
450 class ESC[4;38;5;81mInspectLoaderGetCodeTests:
451
452 def test_get_code(self):
453 # Test success.
454 module = types.ModuleType('blah')
455 with mock.patch.object(self.InspectLoaderSubclass, 'get_source') as mocked:
456 mocked.return_value = 'attr = 42'
457 loader = self.InspectLoaderSubclass()
458 code = loader.get_code('blah')
459 exec(code, module.__dict__)
460 self.assertEqual(module.attr, 42)
461
462 def test_get_code_source_is_None(self):
463 # If get_source() is None then this should be None.
464 with mock.patch.object(self.InspectLoaderSubclass, 'get_source') as mocked:
465 mocked.return_value = None
466 loader = self.InspectLoaderSubclass()
467 code = loader.get_code('blah')
468 self.assertIsNone(code)
469
470 def test_get_code_source_not_found(self):
471 # If there is no source then there is no code object.
472 loader = self.InspectLoaderSubclass()
473 with self.assertRaises(ImportError):
474 loader.get_code('blah')
475
476
477 (Frozen_ILGetCodeTests,
478 Source_ILGetCodeTests
479 ) = test_util.test_both(InspectLoaderGetCodeTests,
480 InspectLoaderSubclass=SPLIT_IL)
481
482
483 class ESC[4;38;5;81mInspectLoaderLoadModuleTests:
484
485 """Test InspectLoader.load_module()."""
486
487 module_name = 'blah'
488
489 def setUp(self):
490 import_helper.unload(self.module_name)
491 self.addCleanup(import_helper.unload, self.module_name)
492
493 def load(self, loader):
494 spec = self.util.spec_from_loader(self.module_name, loader)
495 with warnings.catch_warnings():
496 warnings.simplefilter('ignore', DeprecationWarning)
497 return self.init._bootstrap._load_unlocked(spec)
498
499 def mock_get_code(self):
500 return mock.patch.object(self.InspectLoaderSubclass, 'get_code')
501
502 def test_get_code_ImportError(self):
503 # If get_code() raises ImportError, it should propagate.
504 with self.mock_get_code() as mocked_get_code:
505 mocked_get_code.side_effect = ImportError
506 with self.assertRaises(ImportError):
507 loader = self.InspectLoaderSubclass()
508 self.load(loader)
509
510 def test_get_code_None(self):
511 # If get_code() returns None, raise ImportError.
512 with self.mock_get_code() as mocked_get_code:
513 mocked_get_code.return_value = None
514 with self.assertRaises(ImportError):
515 loader = self.InspectLoaderSubclass()
516 self.load(loader)
517
518 def test_module_returned(self):
519 # The loaded module should be returned.
520 code = compile('attr = 42', '<string>', 'exec')
521 with self.mock_get_code() as mocked_get_code:
522 mocked_get_code.return_value = code
523 loader = self.InspectLoaderSubclass()
524 module = self.load(loader)
525 self.assertEqual(module, sys.modules[self.module_name])
526
527
528 (Frozen_ILLoadModuleTests,
529 Source_ILLoadModuleTests
530 ) = test_util.test_both(InspectLoaderLoadModuleTests,
531 InspectLoaderSubclass=SPLIT_IL,
532 init=init,
533 util=util)
534
535
536 ##### ExecutionLoader concrete methods #########################################
537 class ESC[4;38;5;81mExecutionLoaderGetCodeTests:
538
539 def mock_methods(self, *, get_source=False, get_filename=False):
540 source_mock_context, filename_mock_context = None, None
541 if get_source:
542 source_mock_context = mock.patch.object(self.ExecutionLoaderSubclass,
543 'get_source')
544 if get_filename:
545 filename_mock_context = mock.patch.object(self.ExecutionLoaderSubclass,
546 'get_filename')
547 return source_mock_context, filename_mock_context
548
549 def test_get_code(self):
550 path = 'blah.py'
551 source_mock_context, filename_mock_context = self.mock_methods(
552 get_source=True, get_filename=True)
553 with source_mock_context as source_mock, filename_mock_context as name_mock:
554 source_mock.return_value = 'attr = 42'
555 name_mock.return_value = path
556 loader = self.ExecutionLoaderSubclass()
557 code = loader.get_code('blah')
558 self.assertEqual(code.co_filename, path)
559 module = types.ModuleType('blah')
560 exec(code, module.__dict__)
561 self.assertEqual(module.attr, 42)
562
563 def test_get_code_source_is_None(self):
564 # If get_source() is None then this should be None.
565 source_mock_context, _ = self.mock_methods(get_source=True)
566 with source_mock_context as mocked:
567 mocked.return_value = None
568 loader = self.ExecutionLoaderSubclass()
569 code = loader.get_code('blah')
570 self.assertIsNone(code)
571
572 def test_get_code_source_not_found(self):
573 # If there is no source then there is no code object.
574 loader = self.ExecutionLoaderSubclass()
575 with self.assertRaises(ImportError):
576 loader.get_code('blah')
577
578 def test_get_code_no_path(self):
579 # If get_filename() raises ImportError then simply skip setting the path
580 # on the code object.
581 source_mock_context, filename_mock_context = self.mock_methods(
582 get_source=True, get_filename=True)
583 with source_mock_context as source_mock, filename_mock_context as name_mock:
584 source_mock.return_value = 'attr = 42'
585 name_mock.side_effect = ImportError
586 loader = self.ExecutionLoaderSubclass()
587 code = loader.get_code('blah')
588 self.assertEqual(code.co_filename, '<string>')
589 module = types.ModuleType('blah')
590 exec(code, module.__dict__)
591 self.assertEqual(module.attr, 42)
592
593
594 (Frozen_ELGetCodeTests,
595 Source_ELGetCodeTests
596 ) = test_util.test_both(ExecutionLoaderGetCodeTests,
597 ExecutionLoaderSubclass=SPLIT_EL)
598
599
600 ##### SourceLoader concrete methods ############################################
601 class ESC[4;38;5;81mSourceOnlyLoader:
602
603 # Globals that should be defined for all modules.
604 source = (b"_ = '::'.join([__name__, __file__, __cached__, __package__, "
605 b"repr(__loader__)])")
606
607 def __init__(self, path):
608 self.path = path
609
610 def get_data(self, path):
611 if path != self.path:
612 raise IOError
613 return self.source
614
615 def get_filename(self, fullname):
616 return self.path
617
618
619 SPLIT_SOL = make_abc_subclasses(SourceOnlyLoader, 'SourceLoader')
620
621
622 class ESC[4;38;5;81mSourceLoader(ESC[4;38;5;149mSourceOnlyLoader):
623
624 source_mtime = 1
625
626 def __init__(self, path, magic=None):
627 super().__init__(path)
628 self.bytecode_path = self.util.cache_from_source(self.path)
629 self.source_size = len(self.source)
630 if magic is None:
631 magic = self.util.MAGIC_NUMBER
632 data = bytearray(magic)
633 data.extend(self.init._pack_uint32(0))
634 data.extend(self.init._pack_uint32(self.source_mtime))
635 data.extend(self.init._pack_uint32(self.source_size))
636 code_object = compile(self.source, self.path, 'exec',
637 dont_inherit=True)
638 data.extend(marshal.dumps(code_object))
639 self.bytecode = bytes(data)
640 self.written = {}
641
642 def get_data(self, path):
643 if path == self.path:
644 return super().get_data(path)
645 elif path == self.bytecode_path:
646 return self.bytecode
647 else:
648 raise OSError
649
650 def path_stats(self, path):
651 if path != self.path:
652 raise IOError
653 return {'mtime': self.source_mtime, 'size': self.source_size}
654
655 def set_data(self, path, data):
656 self.written[path] = bytes(data)
657 return path == self.bytecode_path
658
659
660 SPLIT_SL = make_abc_subclasses(SourceLoader, util=util, init=init)
661
662
663 class ESC[4;38;5;81mSourceLoaderTestHarness:
664
665 def setUp(self, *, is_package=True, **kwargs):
666 self.package = 'pkg'
667 if is_package:
668 self.path = os.path.join(self.package, '__init__.py')
669 self.name = self.package
670 else:
671 module_name = 'mod'
672 self.path = os.path.join(self.package, '.'.join(['mod', 'py']))
673 self.name = '.'.join([self.package, module_name])
674 self.cached = self.util.cache_from_source(self.path)
675 self.loader = self.loader_mock(self.path, **kwargs)
676
677 def verify_module(self, module):
678 self.assertEqual(module.__name__, self.name)
679 self.assertEqual(module.__file__, self.path)
680 self.assertEqual(module.__cached__, self.cached)
681 self.assertEqual(module.__package__, self.package)
682 self.assertEqual(module.__loader__, self.loader)
683 values = module._.split('::')
684 self.assertEqual(values[0], self.name)
685 self.assertEqual(values[1], self.path)
686 self.assertEqual(values[2], self.cached)
687 self.assertEqual(values[3], self.package)
688 self.assertEqual(values[4], repr(self.loader))
689
690 def verify_code(self, code_object):
691 module = types.ModuleType(self.name)
692 module.__file__ = self.path
693 module.__cached__ = self.cached
694 module.__package__ = self.package
695 module.__loader__ = self.loader
696 module.__path__ = []
697 exec(code_object, module.__dict__)
698 self.verify_module(module)
699
700
701 class ESC[4;38;5;81mSourceOnlyLoaderTests(ESC[4;38;5;149mSourceLoaderTestHarness):
702 """Test importlib.abc.SourceLoader for source-only loading."""
703
704 def test_get_source(self):
705 # Verify the source code is returned as a string.
706 # If an OSError is raised by get_data then raise ImportError.
707 expected_source = self.loader.source.decode('utf-8')
708 self.assertEqual(self.loader.get_source(self.name), expected_source)
709 def raise_OSError(path):
710 raise OSError
711 self.loader.get_data = raise_OSError
712 with self.assertRaises(ImportError) as cm:
713 self.loader.get_source(self.name)
714 self.assertEqual(cm.exception.name, self.name)
715
716 def test_is_package(self):
717 # Properly detect when loading a package.
718 self.setUp(is_package=False)
719 self.assertFalse(self.loader.is_package(self.name))
720 self.setUp(is_package=True)
721 self.assertTrue(self.loader.is_package(self.name))
722 self.assertFalse(self.loader.is_package(self.name + '.__init__'))
723
724 def test_get_code(self):
725 # Verify the code object is created.
726 code_object = self.loader.get_code(self.name)
727 self.verify_code(code_object)
728
729 def test_source_to_code(self):
730 # Verify the compiled code object.
731 code = self.loader.source_to_code(self.loader.source, self.path)
732 self.verify_code(code)
733
734 def test_load_module(self):
735 # Loading a module should set __name__, __loader__, __package__,
736 # __path__ (for packages), __file__, and __cached__.
737 # The module should also be put into sys.modules.
738 with warnings.catch_warnings():
739 warnings.simplefilter("ignore", ImportWarning)
740 with test_util.uncache(self.name):
741 with warnings.catch_warnings():
742 warnings.simplefilter('ignore', DeprecationWarning)
743 module = self.loader.load_module(self.name)
744 self.verify_module(module)
745 self.assertEqual(module.__path__, [os.path.dirname(self.path)])
746 self.assertIn(self.name, sys.modules)
747
748 def test_package_settings(self):
749 # __package__ needs to be set, while __path__ is set on if the module
750 # is a package.
751 # Testing the values for a package are covered by test_load_module.
752 with warnings.catch_warnings():
753 warnings.simplefilter("ignore", ImportWarning)
754 self.setUp(is_package=False)
755 with test_util.uncache(self.name):
756 with warnings.catch_warnings():
757 warnings.simplefilter('ignore', DeprecationWarning)
758 module = self.loader.load_module(self.name)
759 self.verify_module(module)
760 self.assertFalse(hasattr(module, '__path__'))
761
762 def test_get_source_encoding(self):
763 # Source is considered encoded in UTF-8 by default unless otherwise
764 # specified by an encoding line.
765 source = "_ = 'ü'"
766 self.loader.source = source.encode('utf-8')
767 returned_source = self.loader.get_source(self.name)
768 self.assertEqual(returned_source, source)
769 source = "# coding: latin-1\n_ = ü"
770 self.loader.source = source.encode('latin-1')
771 returned_source = self.loader.get_source(self.name)
772 self.assertEqual(returned_source, source)
773
774
775 (Frozen_SourceOnlyLoaderTests,
776 Source_SourceOnlyLoaderTests
777 ) = test_util.test_both(SourceOnlyLoaderTests, util=util,
778 loader_mock=SPLIT_SOL)
779
780
781 @unittest.skipIf(sys.dont_write_bytecode, "sys.dont_write_bytecode is true")
782 class ESC[4;38;5;81mSourceLoaderBytecodeTests(ESC[4;38;5;149mSourceLoaderTestHarness):
783
784 """Test importlib.abc.SourceLoader's use of bytecode.
785
786 Source-only testing handled by SourceOnlyLoaderTests.
787
788 """
789
790 def verify_code(self, code_object, *, bytecode_written=False):
791 super().verify_code(code_object)
792 if bytecode_written:
793 self.assertIn(self.cached, self.loader.written)
794 data = bytearray(self.util.MAGIC_NUMBER)
795 data.extend(self.init._pack_uint32(0))
796 data.extend(self.init._pack_uint32(self.loader.source_mtime))
797 data.extend(self.init._pack_uint32(self.loader.source_size))
798 data.extend(marshal.dumps(code_object))
799 self.assertEqual(self.loader.written[self.cached], bytes(data))
800
801 def test_code_with_everything(self):
802 # When everything should work.
803 code_object = self.loader.get_code(self.name)
804 self.verify_code(code_object)
805
806 def test_no_bytecode(self):
807 # If no bytecode exists then move on to the source.
808 self.loader.bytecode_path = "<does not exist>"
809 # Sanity check
810 with self.assertRaises(OSError):
811 bytecode_path = self.util.cache_from_source(self.path)
812 self.loader.get_data(bytecode_path)
813 code_object = self.loader.get_code(self.name)
814 self.verify_code(code_object, bytecode_written=True)
815
816 def test_code_bad_timestamp(self):
817 # Bytecode is only used when the timestamp matches the source EXACTLY.
818 for source_mtime in (0, 2):
819 assert source_mtime != self.loader.source_mtime
820 original = self.loader.source_mtime
821 self.loader.source_mtime = source_mtime
822 # If bytecode is used then EOFError would be raised by marshal.
823 self.loader.bytecode = self.loader.bytecode[8:]
824 code_object = self.loader.get_code(self.name)
825 self.verify_code(code_object, bytecode_written=True)
826 self.loader.source_mtime = original
827
828 def test_code_bad_magic(self):
829 # Skip over bytecode with a bad magic number.
830 self.setUp(magic=b'0000')
831 # If bytecode is used then EOFError would be raised by marshal.
832 self.loader.bytecode = self.loader.bytecode[8:]
833 code_object = self.loader.get_code(self.name)
834 self.verify_code(code_object, bytecode_written=True)
835
836 def test_dont_write_bytecode(self):
837 # Bytecode is not written if sys.dont_write_bytecode is true.
838 # Can assume it is false already thanks to the skipIf class decorator.
839 try:
840 sys.dont_write_bytecode = True
841 self.loader.bytecode_path = "<does not exist>"
842 code_object = self.loader.get_code(self.name)
843 self.assertNotIn(self.cached, self.loader.written)
844 finally:
845 sys.dont_write_bytecode = False
846
847 def test_no_set_data(self):
848 # If set_data is not defined, one can still read bytecode.
849 self.setUp(magic=b'0000')
850 original_set_data = self.loader.__class__.mro()[1].set_data
851 try:
852 del self.loader.__class__.mro()[1].set_data
853 code_object = self.loader.get_code(self.name)
854 self.verify_code(code_object)
855 finally:
856 self.loader.__class__.mro()[1].set_data = original_set_data
857
858 def test_set_data_raises_exceptions(self):
859 # Raising NotImplementedError or OSError is okay for set_data.
860 def raise_exception(exc):
861 def closure(*args, **kwargs):
862 raise exc
863 return closure
864
865 self.setUp(magic=b'0000')
866 self.loader.set_data = raise_exception(NotImplementedError)
867 code_object = self.loader.get_code(self.name)
868 self.verify_code(code_object)
869
870
871 (Frozen_SLBytecodeTests,
872 SourceSLBytecodeTests
873 ) = test_util.test_both(SourceLoaderBytecodeTests, init=init, util=util,
874 loader_mock=SPLIT_SL)
875
876
877 class ESC[4;38;5;81mSourceLoaderGetSourceTests:
878
879 """Tests for importlib.abc.SourceLoader.get_source()."""
880
881 def test_default_encoding(self):
882 # Should have no problems with UTF-8 text.
883 name = 'mod'
884 mock = self.SourceOnlyLoaderMock('mod.file')
885 source = 'x = "ü"'
886 mock.source = source.encode('utf-8')
887 returned_source = mock.get_source(name)
888 self.assertEqual(returned_source, source)
889
890 def test_decoded_source(self):
891 # Decoding should work.
892 name = 'mod'
893 mock = self.SourceOnlyLoaderMock("mod.file")
894 source = "# coding: Latin-1\nx='ü'"
895 assert source.encode('latin-1') != source.encode('utf-8')
896 mock.source = source.encode('latin-1')
897 returned_source = mock.get_source(name)
898 self.assertEqual(returned_source, source)
899
900 def test_universal_newlines(self):
901 # PEP 302 says universal newlines should be used.
902 name = 'mod'
903 mock = self.SourceOnlyLoaderMock('mod.file')
904 source = "x = 42\r\ny = -13\r\n"
905 mock.source = source.encode('utf-8')
906 expect = io.IncrementalNewlineDecoder(None, True).decode(source)
907 self.assertEqual(mock.get_source(name), expect)
908
909
910 (Frozen_SourceOnlyLoaderGetSourceTests,
911 Source_SourceOnlyLoaderGetSourceTests
912 ) = test_util.test_both(SourceLoaderGetSourceTests,
913 SourceOnlyLoaderMock=SPLIT_SOL)
914
915
916 if __name__ == '__main__':
917 unittest.main()