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