»Core Development>Code coverage>Lib/test/test_importlib/test_abc.py

Python code coverage for Lib/test/test_importlib/test_abc.py

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