blob: d4bf9153e93fa6cfeef9a5b5115ecdd8417ed1e5 [file] [log] [blame]
Brett Cannon0dbb4c72013-05-31 18:56:47 -04001import contextlib
Brett Cannon64ef00f2009-07-20 03:19:18 +00002import inspect
Brett Cannon100883f2013-04-09 16:59:39 -04003import io
4import marshal
5import os
6import sys
Brett Cannon0dbb4c72013-05-31 18:56:47 -04007from test import support
Brett Cannonef888022013-06-15 18:39:21 -04008import types
Brett Cannon2a922ed2009-03-09 03:35:50 +00009import unittest
Brett Cannon3b62ca82013-05-27 21:11:04 -040010from unittest import mock
Eric Snow1500d492014-01-06 20:49:04 -070011import warnings
Brett Cannon2a922ed2009-03-09 03:35:50 +000012
Eric Snow3497c0b2014-05-16 11:40:40 -060013from . import util as test_util
Brett Cannon2a922ed2009-03-09 03:35:50 +000014
Eric Snow3497c0b2014-05-16 11:40:40 -060015init = test_util.import_importlib('importlib')
16abc = test_util.import_importlib('importlib.abc')
17machinery = test_util.import_importlib('importlib.machinery')
18util = test_util.import_importlib('importlib.util')
19
Brett Cannon3ad327e2013-10-04 14:47:14 -040020
Brett Cannon9ffe85e2013-05-26 16:45:10 -040021##### Inheritance ##############################################################
Brett Cannon64ef00f2009-07-20 03:19:18 +000022class InheritanceTests:
Brett Cannon2a922ed2009-03-09 03:35:50 +000023
Brett Cannon64ef00f2009-07-20 03:19:18 +000024 """Test that the specified class is a subclass/superclass of the expected
25 classes."""
Brett Cannon2a922ed2009-03-09 03:35:50 +000026
Brett Cannon64ef00f2009-07-20 03:19:18 +000027 subclasses = []
28 superclasses = []
Brett Cannon2a922ed2009-03-09 03:35:50 +000029
Eric Snow3497c0b2014-05-16 11:40:40 -060030 def setUp(self):
Brett Cannon3ad327e2013-10-04 14:47:14 -040031 self.superclasses = [getattr(self.abc, class_name)
32 for class_name in self.superclass_names]
33 if hasattr(self, 'subclass_names'):
34 # Because test.support.import_fresh_module() creates a new
35 # importlib._bootstrap per module, inheritance checks fail when
36 # checking across module boundaries (i.e. the _bootstrap in abc is
37 # not the same as the one in machinery). That means stealing one of
38 # the modules from the other to make sure the same instance is used.
Eric Snow3497c0b2014-05-16 11:40:40 -060039 machinery = self.abc.machinery
40 self.subclasses = [getattr(machinery, class_name)
41 for class_name in self.subclass_names]
Brett Cannon64ef00f2009-07-20 03:19:18 +000042 assert self.subclasses or self.superclasses, self.__class__
Eric Snow3497c0b2014-05-16 11:40:40 -060043 self.__test = getattr(self.abc, self._NAME)
Brett Cannon2a922ed2009-03-09 03:35:50 +000044
Brett Cannon64ef00f2009-07-20 03:19:18 +000045 def test_subclasses(self):
46 # Test that the expected subclasses inherit.
47 for subclass in self.subclasses:
48 self.assertTrue(issubclass(subclass, self.__test),
49 "{0} is not a subclass of {1}".format(subclass, self.__test))
50
51 def test_superclasses(self):
52 # Test that the class inherits from the expected superclasses.
53 for superclass in self.superclasses:
54 self.assertTrue(issubclass(self.__test, superclass),
55 "{0} is not a superclass of {1}".format(superclass, self.__test))
56
Brett Cannonf4dc9202012-08-10 12:21:12 -040057
Brett Cannon3ad327e2013-10-04 14:47:14 -040058class MetaPathFinder(InheritanceTests):
59 superclass_names = ['Finder']
60 subclass_names = ['BuiltinImporter', 'FrozenImporter', 'PathFinder',
61 'WindowsRegistryFinder']
Nick Coghlan8a9080f2012-08-02 21:26:03 +100062
Eric Snow3497c0b2014-05-16 11:40:40 -060063
64(Frozen_MetaPathFinderInheritanceTests,
65 Source_MetaPathFinderInheritanceTests
66 ) = test_util.test_both(MetaPathFinder, abc=abc)
Brett Cannon64ef00f2009-07-20 03:19:18 +000067
Brett Cannonf4dc9202012-08-10 12:21:12 -040068
Brett Cannon3ad327e2013-10-04 14:47:14 -040069class PathEntryFinder(InheritanceTests):
70 superclass_names = ['Finder']
71 subclass_names = ['FileFinder']
Brett Cannon64ef00f2009-07-20 03:19:18 +000072
Eric Snow3497c0b2014-05-16 11:40:40 -060073
74(Frozen_PathEntryFinderInheritanceTests,
75 Source_PathEntryFinderInheritanceTests
76 ) = test_util.test_both(PathEntryFinder, abc=abc)
Brett Cannon64ef00f2009-07-20 03:19:18 +000077
78
Brett Cannon3ad327e2013-10-04 14:47:14 -040079class ResourceLoader(InheritanceTests):
80 superclass_names = ['Loader']
Brett Cannon64ef00f2009-07-20 03:19:18 +000081
Eric Snow3497c0b2014-05-16 11:40:40 -060082
83(Frozen_ResourceLoaderInheritanceTests,
84 Source_ResourceLoaderInheritanceTests
85 ) = test_util.test_both(ResourceLoader, abc=abc)
Brett Cannon64ef00f2009-07-20 03:19:18 +000086
87
Brett Cannon3ad327e2013-10-04 14:47:14 -040088class InspectLoader(InheritanceTests):
89 superclass_names = ['Loader']
90 subclass_names = ['BuiltinImporter', 'FrozenImporter', 'ExtensionFileLoader']
Brett Cannon69194272009-07-20 04:23:48 +000091
Eric Snow3497c0b2014-05-16 11:40:40 -060092
93(Frozen_InspectLoaderInheritanceTests,
94 Source_InspectLoaderInheritanceTests
95 ) = test_util.test_both(InspectLoader, abc=abc)
Brett Cannon69194272009-07-20 04:23:48 +000096
97
Brett Cannon3ad327e2013-10-04 14:47:14 -040098class ExecutionLoader(InheritanceTests):
99 superclass_names = ['InspectLoader']
Eric Snow7e70fa52013-10-04 20:28:52 -0600100 subclass_names = ['ExtensionFileLoader']
Brett Cannon938d44d2012-04-22 19:58:33 -0400101
Eric Snow3497c0b2014-05-16 11:40:40 -0600102
103(Frozen_ExecutionLoaderInheritanceTests,
104 Source_ExecutionLoaderInheritanceTests
105 ) = test_util.test_both(ExecutionLoader, abc=abc)
Brett Cannon938d44d2012-04-22 19:58:33 -0400106
107
Brett Cannon3ad327e2013-10-04 14:47:14 -0400108class FileLoader(InheritanceTests):
109 superclass_names = ['ResourceLoader', 'ExecutionLoader']
110 subclass_names = ['SourceFileLoader', 'SourcelessFileLoader']
Brett Cannonb7183d82010-06-28 05:46:25 +0000111
Eric Snow3497c0b2014-05-16 11:40:40 -0600112
113(Frozen_FileLoaderInheritanceTests,
114 Source_FileLoaderInheritanceTests
115 ) = test_util.test_both(FileLoader, abc=abc)
Brett Cannonb7183d82010-06-28 05:46:25 +0000116
117
Brett Cannon3ad327e2013-10-04 14:47:14 -0400118class SourceLoader(InheritanceTests):
119 superclass_names = ['ResourceLoader', 'ExecutionLoader']
120 subclass_names = ['SourceFileLoader']
121
Eric Snow3497c0b2014-05-16 11:40:40 -0600122
123(Frozen_SourceLoaderInheritanceTests,
124 Source_SourceLoaderInheritanceTests
125 ) = test_util.test_both(SourceLoader, abc=abc)
126
Brett Cannon3ad327e2013-10-04 14:47:14 -0400127
Brett Cannon9ffe85e2013-05-26 16:45:10 -0400128##### Default return values ####################################################
Brett Cannon3ad327e2013-10-04 14:47:14 -0400129
Eric Snow3497c0b2014-05-16 11:40:40 -0600130def make_abc_subclasses(base_class, name=None, inst=False, **kwargs):
131 if name is None:
132 name = base_class.__name__
133 base = {kind: getattr(splitabc, name)
134 for kind, splitabc in abc.items()}
135 return {cls._KIND: cls() if inst else cls
136 for cls in test_util.split_frozen(base_class, base, **kwargs)}
137
138
139class ABCTestHarness:
140
141 @property
142 def ins(self):
143 # Lazily set ins on the class.
144 cls = self.SPLIT[self._KIND]
145 ins = cls()
146 self.__class__.ins = ins
147 return ins
Brett Cannon3ad327e2013-10-04 14:47:14 -0400148
149
150class MetaPathFinder:
Brett Cannon100883f2013-04-09 16:59:39 -0400151
152 def find_module(self, fullname, path):
153 return super().find_module(fullname, path)
154
155
Eric Snow3497c0b2014-05-16 11:40:40 -0600156class MetaPathFinderDefaultsTests(ABCTestHarness):
Brett Cannon100883f2013-04-09 16:59:39 -0400157
Eric Snow3497c0b2014-05-16 11:40:40 -0600158 SPLIT = make_abc_subclasses(MetaPathFinder)
Brett Cannon100883f2013-04-09 16:59:39 -0400159
160 def test_find_module(self):
161 # Default should return None.
162 self.assertIsNone(self.ins.find_module('something', None))
163
164 def test_invalidate_caches(self):
165 # Calling the method is a no-op.
166 self.ins.invalidate_caches()
167
168
Eric Snow3497c0b2014-05-16 11:40:40 -0600169(Frozen_MPFDefaultTests,
170 Source_MPFDefaultTests
171 ) = test_util.test_both(MetaPathFinderDefaultsTests)
Brett Cannon3ad327e2013-10-04 14:47:14 -0400172
173
174class PathEntryFinder:
Brett Cannon100883f2013-04-09 16:59:39 -0400175
176 def find_loader(self, fullname):
177 return super().find_loader(fullname)
178
179
Eric Snow3497c0b2014-05-16 11:40:40 -0600180class PathEntryFinderDefaultsTests(ABCTestHarness):
Brett Cannon100883f2013-04-09 16:59:39 -0400181
Eric Snow3497c0b2014-05-16 11:40:40 -0600182 SPLIT = make_abc_subclasses(PathEntryFinder)
Brett Cannon100883f2013-04-09 16:59:39 -0400183
184 def test_find_loader(self):
185 self.assertEqual((None, []), self.ins.find_loader('something'))
186
187 def find_module(self):
188 self.assertEqual(None, self.ins.find_module('something'))
189
190 def test_invalidate_caches(self):
191 # Should be a no-op.
192 self.ins.invalidate_caches()
193
194
Eric Snow3497c0b2014-05-16 11:40:40 -0600195(Frozen_PEFDefaultTests,
196 Source_PEFDefaultTests
197 ) = test_util.test_both(PathEntryFinderDefaultsTests)
Brett Cannon3ad327e2013-10-04 14:47:14 -0400198
199
200class Loader:
Brett Cannon100883f2013-04-09 16:59:39 -0400201
202 def load_module(self, fullname):
203 return super().load_module(fullname)
204
205
Eric Snow3497c0b2014-05-16 11:40:40 -0600206class LoaderDefaultsTests(ABCTestHarness):
Brett Cannon100883f2013-04-09 16:59:39 -0400207
Eric Snow3497c0b2014-05-16 11:40:40 -0600208 SPLIT = make_abc_subclasses(Loader)
Brett Cannon100883f2013-04-09 16:59:39 -0400209
210 def test_load_module(self):
211 with self.assertRaises(ImportError):
212 self.ins.load_module('something')
213
214 def test_module_repr(self):
Brett Cannonef888022013-06-15 18:39:21 -0400215 mod = types.ModuleType('blah')
Brett Cannon100883f2013-04-09 16:59:39 -0400216 with self.assertRaises(NotImplementedError):
217 self.ins.module_repr(mod)
218 original_repr = repr(mod)
219 mod.__loader__ = self.ins
220 # Should still return a proper repr.
221 self.assertTrue(repr(mod))
222
223
Eric Snow3497c0b2014-05-16 11:40:40 -0600224(Frozen_LDefaultTests,
225 SourceLDefaultTests
226 ) = test_util.test_both(LoaderDefaultsTests)
Brett Cannon3ad327e2013-10-04 14:47:14 -0400227
228
229class ResourceLoader(Loader):
Brett Cannon100883f2013-04-09 16:59:39 -0400230
231 def get_data(self, path):
232 return super().get_data(path)
233
234
Eric Snow3497c0b2014-05-16 11:40:40 -0600235class ResourceLoaderDefaultsTests(ABCTestHarness):
Brett Cannon100883f2013-04-09 16:59:39 -0400236
Eric Snow3497c0b2014-05-16 11:40:40 -0600237 SPLIT = make_abc_subclasses(ResourceLoader)
Brett Cannon100883f2013-04-09 16:59:39 -0400238
239 def test_get_data(self):
240 with self.assertRaises(IOError):
241 self.ins.get_data('/some/path')
242
243
Eric Snow3497c0b2014-05-16 11:40:40 -0600244(Frozen_RLDefaultTests,
245 Source_RLDefaultTests
246 ) = test_util.test_both(ResourceLoaderDefaultsTests)
Brett Cannon3ad327e2013-10-04 14:47:14 -0400247
248
249class InspectLoader(Loader):
Brett Cannon100883f2013-04-09 16:59:39 -0400250
251 def is_package(self, fullname):
252 return super().is_package(fullname)
253
Brett Cannon100883f2013-04-09 16:59:39 -0400254 def get_source(self, fullname):
255 return super().get_source(fullname)
256
257
Eric Snow3497c0b2014-05-16 11:40:40 -0600258SPLIT_IL = make_abc_subclasses(InspectLoader)
Brett Cannon100883f2013-04-09 16:59:39 -0400259
Brett Cannon3ad327e2013-10-04 14:47:14 -0400260
Eric Snow3497c0b2014-05-16 11:40:40 -0600261class InspectLoaderDefaultsTests(ABCTestHarness):
262
263 SPLIT = SPLIT_IL
Brett Cannon100883f2013-04-09 16:59:39 -0400264
265 def test_is_package(self):
266 with self.assertRaises(ImportError):
267 self.ins.is_package('blah')
268
Brett Cannon100883f2013-04-09 16:59:39 -0400269 def test_get_source(self):
270 with self.assertRaises(ImportError):
271 self.ins.get_source('blah')
272
273
Eric Snow3497c0b2014-05-16 11:40:40 -0600274(Frozen_ILDefaultTests,
275 Source_ILDefaultTests
276 ) = test_util.test_both(InspectLoaderDefaultsTests)
Brett Cannon3ad327e2013-10-04 14:47:14 -0400277
278
279class ExecutionLoader(InspectLoader):
Brett Cannon100883f2013-04-09 16:59:39 -0400280
281 def get_filename(self, fullname):
282 return super().get_filename(fullname)
283
Eric Snow3497c0b2014-05-16 11:40:40 -0600284
285SPLIT_EL = make_abc_subclasses(ExecutionLoader)
Brett Cannon100883f2013-04-09 16:59:39 -0400286
Brett Cannon100883f2013-04-09 16:59:39 -0400287
Eric Snow3497c0b2014-05-16 11:40:40 -0600288class ExecutionLoaderDefaultsTests(ABCTestHarness):
289
290 SPLIT = SPLIT_EL
Brett Cannon100883f2013-04-09 16:59:39 -0400291
292 def test_get_filename(self):
293 with self.assertRaises(ImportError):
294 self.ins.get_filename('blah')
295
Brett Cannon3ad327e2013-10-04 14:47:14 -0400296
Eric Snow3497c0b2014-05-16 11:40:40 -0600297(Frozen_ELDefaultTests,
298 Source_ELDefaultsTests
299 ) = test_util.test_both(InspectLoaderDefaultsTests)
300
Brett Cannon3ad327e2013-10-04 14:47:14 -0400301
Brett Cannon8d942292014-01-07 15:52:42 -0500302##### MetaPathFinder concrete methods ##########################################
Brett Cannon8d942292014-01-07 15:52:42 -0500303class MetaPathFinderFindModuleTests:
304
305 @classmethod
306 def finder(cls, spec):
307 class MetaPathSpecFinder(cls.abc.MetaPathFinder):
308
309 def find_spec(self, fullname, path, target=None):
310 self.called_for = fullname, path
311 return spec
312
313 return MetaPathSpecFinder()
314
315 def test_no_spec(self):
316 finder = self.finder(None)
317 path = ['a', 'b', 'c']
318 name = 'blah'
319 found = finder.find_module(name, path)
320 self.assertIsNone(found)
321 self.assertEqual(name, finder.called_for[0])
322 self.assertEqual(path, finder.called_for[1])
323
324 def test_spec(self):
325 loader = object()
326 spec = self.util.spec_from_loader('blah', loader)
327 finder = self.finder(spec)
328 found = finder.find_module('blah', None)
329 self.assertIs(found, spec.loader)
330
331
Eric Snow3497c0b2014-05-16 11:40:40 -0600332(Frozen_MPFFindModuleTests,
333 Source_MPFFindModuleTests
334 ) = test_util.test_both(MetaPathFinderFindModuleTests, abc=abc, util=util)
335
Brett Cannon8d942292014-01-07 15:52:42 -0500336
337##### PathEntryFinder concrete methods #########################################
Brett Cannon8d942292014-01-07 15:52:42 -0500338class PathEntryFinderFindLoaderTests:
339
340 @classmethod
341 def finder(cls, spec):
342 class PathEntrySpecFinder(cls.abc.PathEntryFinder):
343
344 def find_spec(self, fullname, target=None):
345 self.called_for = fullname
346 return spec
347
348 return PathEntrySpecFinder()
349
350 def test_no_spec(self):
351 finder = self.finder(None)
352 name = 'blah'
353 found = finder.find_loader(name)
354 self.assertIsNone(found[0])
355 self.assertEqual([], found[1])
356 self.assertEqual(name, finder.called_for)
357
358 def test_spec_with_loader(self):
359 loader = object()
360 spec = self.util.spec_from_loader('blah', loader)
361 finder = self.finder(spec)
362 found = finder.find_loader('blah')
363 self.assertIs(found[0], spec.loader)
364
365 def test_spec_with_portions(self):
366 spec = self.machinery.ModuleSpec('blah', None)
367 paths = ['a', 'b', 'c']
368 spec.submodule_search_locations = paths
369 finder = self.finder(spec)
370 found = finder.find_loader('blah')
371 self.assertIsNone(found[0])
372 self.assertEqual(paths, found[1])
373
374
Eric Snow3497c0b2014-05-16 11:40:40 -0600375(Frozen_PEFFindLoaderTests,
376 Source_PEFFindLoaderTests
377 ) = test_util.test_both(PathEntryFinderFindLoaderTests, abc=abc, util=util,
378 machinery=machinery)
Brett Cannon8d942292014-01-07 15:52:42 -0500379
380
381##### Loader concrete methods ##################################################
382class LoaderLoadModuleTests:
383
384 def loader(self):
385 class SpecLoader(self.abc.Loader):
386 found = None
387 def exec_module(self, module):
388 self.found = module
389
390 def is_package(self, fullname):
391 """Force some non-default module state to be set."""
392 return True
393
394 return SpecLoader()
395
396 def test_fresh(self):
397 loader = self.loader()
398 name = 'blah'
Eric Snow3497c0b2014-05-16 11:40:40 -0600399 with test_util.uncache(name):
Brett Cannon8d942292014-01-07 15:52:42 -0500400 loader.load_module(name)
401 module = loader.found
402 self.assertIs(sys.modules[name], module)
403 self.assertEqual(loader, module.__loader__)
404 self.assertEqual(loader, module.__spec__.loader)
405 self.assertEqual(name, module.__name__)
406 self.assertEqual(name, module.__spec__.name)
407 self.assertIsNotNone(module.__path__)
408 self.assertIsNotNone(module.__path__,
409 module.__spec__.submodule_search_locations)
410
411 def test_reload(self):
412 name = 'blah'
413 loader = self.loader()
414 module = types.ModuleType(name)
415 module.__spec__ = self.util.spec_from_loader(name, loader)
416 module.__loader__ = loader
Eric Snow3497c0b2014-05-16 11:40:40 -0600417 with test_util.uncache(name):
Brett Cannon8d942292014-01-07 15:52:42 -0500418 sys.modules[name] = module
419 loader.load_module(name)
420 found = loader.found
421 self.assertIs(found, sys.modules[name])
422 self.assertIs(module, sys.modules[name])
423
424
Eric Snow3497c0b2014-05-16 11:40:40 -0600425(Frozen_LoaderLoadModuleTests,
426 Source_LoaderLoadModuleTests
427 ) = test_util.test_both(LoaderLoadModuleTests, abc=abc, util=util)
Brett Cannon8d942292014-01-07 15:52:42 -0500428
Brett Cannon3ad327e2013-10-04 14:47:14 -0400429
Brett Cannon9ffe85e2013-05-26 16:45:10 -0400430##### InspectLoader concrete methods ###########################################
Brett Cannon3ad327e2013-10-04 14:47:14 -0400431class InspectLoaderSourceToCodeTests:
Brett Cannon9ffe85e2013-05-26 16:45:10 -0400432
433 def source_to_module(self, data, path=None):
434 """Help with source_to_code() tests."""
Brett Cannonef888022013-06-15 18:39:21 -0400435 module = types.ModuleType('blah')
Brett Cannon3ad327e2013-10-04 14:47:14 -0400436 loader = self.InspectLoaderSubclass()
Brett Cannon9ffe85e2013-05-26 16:45:10 -0400437 if path is None:
438 code = loader.source_to_code(data)
439 else:
440 code = loader.source_to_code(data, path)
441 exec(code, module.__dict__)
442 return module
443
444 def test_source_to_code_source(self):
445 # Since compile() can handle strings, so should source_to_code().
446 source = 'attr = 42'
447 module = self.source_to_module(source)
448 self.assertTrue(hasattr(module, 'attr'))
449 self.assertEqual(module.attr, 42)
450
451 def test_source_to_code_bytes(self):
452 # Since compile() can handle bytes, so should source_to_code().
453 source = b'attr = 42'
454 module = self.source_to_module(source)
455 self.assertTrue(hasattr(module, 'attr'))
456 self.assertEqual(module.attr, 42)
457
458 def test_source_to_code_path(self):
459 # Specifying a path should set it for the code object.
460 path = 'path/to/somewhere'
Brett Cannon3ad327e2013-10-04 14:47:14 -0400461 loader = self.InspectLoaderSubclass()
Brett Cannon9ffe85e2013-05-26 16:45:10 -0400462 code = loader.source_to_code('', path)
463 self.assertEqual(code.co_filename, path)
464
465 def test_source_to_code_no_path(self):
466 # Not setting a path should still work and be set to <string> since that
467 # is a pre-existing practice as a default to compile().
Brett Cannon3ad327e2013-10-04 14:47:14 -0400468 loader = self.InspectLoaderSubclass()
Brett Cannon9ffe85e2013-05-26 16:45:10 -0400469 code = loader.source_to_code('')
470 self.assertEqual(code.co_filename, '<string>')
471
472
Eric Snow3497c0b2014-05-16 11:40:40 -0600473(Frozen_ILSourceToCodeTests,
474 Source_ILSourceToCodeTests
475 ) = test_util.test_both(InspectLoaderSourceToCodeTests,
476 InspectLoaderSubclass=SPLIT_IL)
Brett Cannon3ad327e2013-10-04 14:47:14 -0400477
478
479class InspectLoaderGetCodeTests:
Brett Cannon3b62ca82013-05-27 21:11:04 -0400480
481 def test_get_code(self):
482 # Test success.
Brett Cannonef888022013-06-15 18:39:21 -0400483 module = types.ModuleType('blah')
Brett Cannon3ad327e2013-10-04 14:47:14 -0400484 with mock.patch.object(self.InspectLoaderSubclass, 'get_source') as mocked:
Brett Cannon3b62ca82013-05-27 21:11:04 -0400485 mocked.return_value = 'attr = 42'
Brett Cannon3ad327e2013-10-04 14:47:14 -0400486 loader = self.InspectLoaderSubclass()
Brett Cannon3b62ca82013-05-27 21:11:04 -0400487 code = loader.get_code('blah')
488 exec(code, module.__dict__)
489 self.assertEqual(module.attr, 42)
490
491 def test_get_code_source_is_None(self):
492 # If get_source() is None then this should be None.
Brett Cannon3ad327e2013-10-04 14:47:14 -0400493 with mock.patch.object(self.InspectLoaderSubclass, 'get_source') as mocked:
Brett Cannon3b62ca82013-05-27 21:11:04 -0400494 mocked.return_value = None
Brett Cannon3ad327e2013-10-04 14:47:14 -0400495 loader = self.InspectLoaderSubclass()
Brett Cannon3b62ca82013-05-27 21:11:04 -0400496 code = loader.get_code('blah')
497 self.assertIsNone(code)
498
499 def test_get_code_source_not_found(self):
500 # If there is no source then there is no code object.
Brett Cannon3ad327e2013-10-04 14:47:14 -0400501 loader = self.InspectLoaderSubclass()
Brett Cannon3b62ca82013-05-27 21:11:04 -0400502 with self.assertRaises(ImportError):
503 loader.get_code('blah')
504
505
Eric Snow3497c0b2014-05-16 11:40:40 -0600506(Frozen_ILGetCodeTests,
507 Source_ILGetCodeTests
508 ) = test_util.test_both(InspectLoaderGetCodeTests,
509 InspectLoaderSubclass=SPLIT_IL)
Brett Cannon3ad327e2013-10-04 14:47:14 -0400510
511
Brett Cannon3ad327e2013-10-04 14:47:14 -0400512class InspectLoaderLoadModuleTests:
Brett Cannon0dbb4c72013-05-31 18:56:47 -0400513
514 """Test InspectLoader.load_module()."""
515
516 module_name = 'blah'
517
518 def setUp(self):
519 support.unload(self.module_name)
520 self.addCleanup(support.unload, self.module_name)
521
522 def mock_get_code(self):
Brett Cannon3ad327e2013-10-04 14:47:14 -0400523 return mock.patch.object(self.InspectLoaderSubclass, 'get_code')
Brett Cannon0dbb4c72013-05-31 18:56:47 -0400524
525 def test_get_code_ImportError(self):
526 # If get_code() raises ImportError, it should propagate.
527 with self.mock_get_code() as mocked_get_code:
528 mocked_get_code.side_effect = ImportError
529 with self.assertRaises(ImportError):
Brett Cannon3ad327e2013-10-04 14:47:14 -0400530 loader = self.InspectLoaderSubclass()
Eric Snow1500d492014-01-06 20:49:04 -0700531 with warnings.catch_warnings():
532 warnings.simplefilter('ignore', DeprecationWarning)
533 loader.load_module(self.module_name)
Brett Cannon0dbb4c72013-05-31 18:56:47 -0400534
535 def test_get_code_None(self):
536 # If get_code() returns None, raise ImportError.
537 with self.mock_get_code() as mocked_get_code:
538 mocked_get_code.return_value = None
539 with self.assertRaises(ImportError):
Brett Cannon3ad327e2013-10-04 14:47:14 -0400540 loader = self.InspectLoaderSubclass()
Brett Cannon0dbb4c72013-05-31 18:56:47 -0400541 loader.load_module(self.module_name)
542
543 def test_module_returned(self):
544 # The loaded module should be returned.
545 code = compile('attr = 42', '<string>', 'exec')
546 with self.mock_get_code() as mocked_get_code:
547 mocked_get_code.return_value = code
Brett Cannon3ad327e2013-10-04 14:47:14 -0400548 loader = self.InspectLoaderSubclass()
Brett Cannon0dbb4c72013-05-31 18:56:47 -0400549 module = loader.load_module(self.module_name)
550 self.assertEqual(module, sys.modules[self.module_name])
551
552
Eric Snow3497c0b2014-05-16 11:40:40 -0600553(Frozen_ILLoadModuleTests,
554 Source_ILLoadModuleTests
555 ) = test_util.test_both(InspectLoaderLoadModuleTests,
556 InspectLoaderSubclass=SPLIT_IL)
Brett Cannon3ad327e2013-10-04 14:47:14 -0400557
558
Brett Cannon3b62ca82013-05-27 21:11:04 -0400559##### ExecutionLoader concrete methods #########################################
Brett Cannon3ad327e2013-10-04 14:47:14 -0400560class ExecutionLoaderGetCodeTests:
Brett Cannon3b62ca82013-05-27 21:11:04 -0400561
562 def mock_methods(self, *, get_source=False, get_filename=False):
563 source_mock_context, filename_mock_context = None, None
564 if get_source:
Brett Cannon3ad327e2013-10-04 14:47:14 -0400565 source_mock_context = mock.patch.object(self.ExecutionLoaderSubclass,
Brett Cannon3b62ca82013-05-27 21:11:04 -0400566 'get_source')
567 if get_filename:
Brett Cannon3ad327e2013-10-04 14:47:14 -0400568 filename_mock_context = mock.patch.object(self.ExecutionLoaderSubclass,
Brett Cannon3b62ca82013-05-27 21:11:04 -0400569 'get_filename')
570 return source_mock_context, filename_mock_context
571
572 def test_get_code(self):
573 path = 'blah.py'
574 source_mock_context, filename_mock_context = self.mock_methods(
575 get_source=True, get_filename=True)
576 with source_mock_context as source_mock, filename_mock_context as name_mock:
577 source_mock.return_value = 'attr = 42'
578 name_mock.return_value = path
Brett Cannon3ad327e2013-10-04 14:47:14 -0400579 loader = self.ExecutionLoaderSubclass()
Brett Cannon3b62ca82013-05-27 21:11:04 -0400580 code = loader.get_code('blah')
581 self.assertEqual(code.co_filename, path)
Brett Cannonef888022013-06-15 18:39:21 -0400582 module = types.ModuleType('blah')
Brett Cannon3b62ca82013-05-27 21:11:04 -0400583 exec(code, module.__dict__)
584 self.assertEqual(module.attr, 42)
585
586 def test_get_code_source_is_None(self):
587 # If get_source() is None then this should be None.
588 source_mock_context, _ = self.mock_methods(get_source=True)
589 with source_mock_context as mocked:
590 mocked.return_value = None
Brett Cannon3ad327e2013-10-04 14:47:14 -0400591 loader = self.ExecutionLoaderSubclass()
Brett Cannon3b62ca82013-05-27 21:11:04 -0400592 code = loader.get_code('blah')
593 self.assertIsNone(code)
594
595 def test_get_code_source_not_found(self):
596 # If there is no source then there is no code object.
Brett Cannon3ad327e2013-10-04 14:47:14 -0400597 loader = self.ExecutionLoaderSubclass()
Brett Cannon3b62ca82013-05-27 21:11:04 -0400598 with self.assertRaises(ImportError):
599 loader.get_code('blah')
600
601 def test_get_code_no_path(self):
602 # If get_filename() raises ImportError then simply skip setting the path
603 # on the code object.
604 source_mock_context, filename_mock_context = self.mock_methods(
605 get_source=True, get_filename=True)
606 with source_mock_context as source_mock, filename_mock_context as name_mock:
607 source_mock.return_value = 'attr = 42'
608 name_mock.side_effect = ImportError
Brett Cannon3ad327e2013-10-04 14:47:14 -0400609 loader = self.ExecutionLoaderSubclass()
Brett Cannon3b62ca82013-05-27 21:11:04 -0400610 code = loader.get_code('blah')
611 self.assertEqual(code.co_filename, '<string>')
Brett Cannonef888022013-06-15 18:39:21 -0400612 module = types.ModuleType('blah')
Brett Cannon3b62ca82013-05-27 21:11:04 -0400613 exec(code, module.__dict__)
614 self.assertEqual(module.attr, 42)
615
616
Eric Snow3497c0b2014-05-16 11:40:40 -0600617(Frozen_ELGetCodeTests,
618 Source_ELGetCodeTests
619 ) = test_util.test_both(ExecutionLoaderGetCodeTests,
620 ExecutionLoaderSubclass=SPLIT_EL)
Brett Cannon3ad327e2013-10-04 14:47:14 -0400621
622
Brett Cannon9ffe85e2013-05-26 16:45:10 -0400623##### SourceLoader concrete methods ############################################
Eric Snow3497c0b2014-05-16 11:40:40 -0600624class SourceOnlyLoader:
Brett Cannon100883f2013-04-09 16:59:39 -0400625
626 # Globals that should be defined for all modules.
627 source = (b"_ = '::'.join([__name__, __file__, __cached__, __package__, "
628 b"repr(__loader__)])")
629
630 def __init__(self, path):
631 self.path = path
632
633 def get_data(self, path):
634 if path != self.path:
635 raise IOError
636 return self.source
637
638 def get_filename(self, fullname):
639 return self.path
640
641 def module_repr(self, module):
642 return '<module>'
643
644
Eric Snow3497c0b2014-05-16 11:40:40 -0600645SPLIT_SOL = make_abc_subclasses(SourceOnlyLoader, 'SourceLoader')
Brett Cannon3ad327e2013-10-04 14:47:14 -0400646
647
Eric Snow3497c0b2014-05-16 11:40:40 -0600648class SourceLoader(SourceOnlyLoader):
Brett Cannon100883f2013-04-09 16:59:39 -0400649
650 source_mtime = 1
651
Brett Cannon3ad327e2013-10-04 14:47:14 -0400652 def __init__(self, path, magic=None):
Brett Cannon100883f2013-04-09 16:59:39 -0400653 super().__init__(path)
Brett Cannon3ad327e2013-10-04 14:47:14 -0400654 self.bytecode_path = self.util.cache_from_source(self.path)
Brett Cannon100883f2013-04-09 16:59:39 -0400655 self.source_size = len(self.source)
Brett Cannon3ad327e2013-10-04 14:47:14 -0400656 if magic is None:
657 magic = self.util.MAGIC_NUMBER
Brett Cannon100883f2013-04-09 16:59:39 -0400658 data = bytearray(magic)
Brett Cannon3ad327e2013-10-04 14:47:14 -0400659 data.extend(self.init._w_long(self.source_mtime))
660 data.extend(self.init._w_long(self.source_size))
Brett Cannon100883f2013-04-09 16:59:39 -0400661 code_object = compile(self.source, self.path, 'exec',
662 dont_inherit=True)
663 data.extend(marshal.dumps(code_object))
664 self.bytecode = bytes(data)
665 self.written = {}
666
667 def get_data(self, path):
668 if path == self.path:
669 return super().get_data(path)
670 elif path == self.bytecode_path:
671 return self.bytecode
672 else:
673 raise OSError
674
675 def path_stats(self, path):
676 if path != self.path:
677 raise IOError
678 return {'mtime': self.source_mtime, 'size': self.source_size}
679
680 def set_data(self, path, data):
681 self.written[path] = bytes(data)
682 return path == self.bytecode_path
683
684
Eric Snow3497c0b2014-05-16 11:40:40 -0600685SPLIT_SL = make_abc_subclasses(SourceLoader, util=util, init=init)
Brett Cannon3ad327e2013-10-04 14:47:14 -0400686
687
688class SourceLoaderTestHarness:
Brett Cannon100883f2013-04-09 16:59:39 -0400689
690 def setUp(self, *, is_package=True, **kwargs):
691 self.package = 'pkg'
692 if is_package:
693 self.path = os.path.join(self.package, '__init__.py')
694 self.name = self.package
695 else:
696 module_name = 'mod'
697 self.path = os.path.join(self.package, '.'.join(['mod', 'py']))
698 self.name = '.'.join([self.package, module_name])
Brett Cannon3ad327e2013-10-04 14:47:14 -0400699 self.cached = self.util.cache_from_source(self.path)
Brett Cannon100883f2013-04-09 16:59:39 -0400700 self.loader = self.loader_mock(self.path, **kwargs)
701
702 def verify_module(self, module):
703 self.assertEqual(module.__name__, self.name)
704 self.assertEqual(module.__file__, self.path)
705 self.assertEqual(module.__cached__, self.cached)
706 self.assertEqual(module.__package__, self.package)
707 self.assertEqual(module.__loader__, self.loader)
708 values = module._.split('::')
709 self.assertEqual(values[0], self.name)
710 self.assertEqual(values[1], self.path)
711 self.assertEqual(values[2], self.cached)
712 self.assertEqual(values[3], self.package)
713 self.assertEqual(values[4], repr(self.loader))
714
715 def verify_code(self, code_object):
Brett Cannonef888022013-06-15 18:39:21 -0400716 module = types.ModuleType(self.name)
Brett Cannon100883f2013-04-09 16:59:39 -0400717 module.__file__ = self.path
718 module.__cached__ = self.cached
719 module.__package__ = self.package
720 module.__loader__ = self.loader
721 module.__path__ = []
722 exec(code_object, module.__dict__)
723 self.verify_module(module)
724
725
726class SourceOnlyLoaderTests(SourceLoaderTestHarness):
727
728 """Test importlib.abc.SourceLoader for source-only loading.
729
730 Reload testing is subsumed by the tests for
731 importlib.util.module_for_loader.
732
733 """
734
Brett Cannon100883f2013-04-09 16:59:39 -0400735 def test_get_source(self):
736 # Verify the source code is returned as a string.
737 # If an OSError is raised by get_data then raise ImportError.
738 expected_source = self.loader.source.decode('utf-8')
739 self.assertEqual(self.loader.get_source(self.name), expected_source)
740 def raise_OSError(path):
741 raise OSError
742 self.loader.get_data = raise_OSError
743 with self.assertRaises(ImportError) as cm:
744 self.loader.get_source(self.name)
745 self.assertEqual(cm.exception.name, self.name)
746
747 def test_is_package(self):
748 # Properly detect when loading a package.
749 self.setUp(is_package=False)
750 self.assertFalse(self.loader.is_package(self.name))
751 self.setUp(is_package=True)
752 self.assertTrue(self.loader.is_package(self.name))
753 self.assertFalse(self.loader.is_package(self.name + '.__init__'))
754
755 def test_get_code(self):
756 # Verify the code object is created.
757 code_object = self.loader.get_code(self.name)
758 self.verify_code(code_object)
759
760 def test_source_to_code(self):
761 # Verify the compiled code object.
762 code = self.loader.source_to_code(self.loader.source, self.path)
763 self.verify_code(code)
764
765 def test_load_module(self):
766 # Loading a module should set __name__, __loader__, __package__,
767 # __path__ (for packages), __file__, and __cached__.
768 # The module should also be put into sys.modules.
Eric Snow3497c0b2014-05-16 11:40:40 -0600769 with test_util.uncache(self.name):
Eric Snow1500d492014-01-06 20:49:04 -0700770 with warnings.catch_warnings():
771 warnings.simplefilter('ignore', DeprecationWarning)
772 module = self.loader.load_module(self.name)
Brett Cannon100883f2013-04-09 16:59:39 -0400773 self.verify_module(module)
774 self.assertEqual(module.__path__, [os.path.dirname(self.path)])
775 self.assertIn(self.name, sys.modules)
776
777 def test_package_settings(self):
778 # __package__ needs to be set, while __path__ is set on if the module
779 # is a package.
780 # Testing the values for a package are covered by test_load_module.
781 self.setUp(is_package=False)
Eric Snow3497c0b2014-05-16 11:40:40 -0600782 with test_util.uncache(self.name):
Eric Snow1500d492014-01-06 20:49:04 -0700783 with warnings.catch_warnings():
784 warnings.simplefilter('ignore', DeprecationWarning)
785 module = self.loader.load_module(self.name)
Brett Cannon100883f2013-04-09 16:59:39 -0400786 self.verify_module(module)
Serhiy Storchaka344f8312014-07-07 14:08:19 +0300787 self.assertFalse(hasattr(module, '__path__'))
Brett Cannon100883f2013-04-09 16:59:39 -0400788
789 def test_get_source_encoding(self):
790 # Source is considered encoded in UTF-8 by default unless otherwise
791 # specified by an encoding line.
792 source = "_ = 'ü'"
793 self.loader.source = source.encode('utf-8')
794 returned_source = self.loader.get_source(self.name)
795 self.assertEqual(returned_source, source)
796 source = "# coding: latin-1\n_ = ü"
797 self.loader.source = source.encode('latin-1')
798 returned_source = self.loader.get_source(self.name)
799 self.assertEqual(returned_source, source)
800
801
Eric Snow3497c0b2014-05-16 11:40:40 -0600802(Frozen_SourceOnlyLoaderTests,
803 Source_SourceOnlyLoaderTests
804 ) = test_util.test_both(SourceOnlyLoaderTests, util=util,
805 loader_mock=SPLIT_SOL)
Brett Cannon3ad327e2013-10-04 14:47:14 -0400806
807
Brett Cannon100883f2013-04-09 16:59:39 -0400808@unittest.skipIf(sys.dont_write_bytecode, "sys.dont_write_bytecode is true")
809class SourceLoaderBytecodeTests(SourceLoaderTestHarness):
810
811 """Test importlib.abc.SourceLoader's use of bytecode.
812
813 Source-only testing handled by SourceOnlyLoaderTests.
814
815 """
816
Brett Cannon100883f2013-04-09 16:59:39 -0400817 def verify_code(self, code_object, *, bytecode_written=False):
818 super().verify_code(code_object)
819 if bytecode_written:
820 self.assertIn(self.cached, self.loader.written)
Brett Cannon3ad327e2013-10-04 14:47:14 -0400821 data = bytearray(self.util.MAGIC_NUMBER)
822 data.extend(self.init._w_long(self.loader.source_mtime))
823 data.extend(self.init._w_long(self.loader.source_size))
Brett Cannon100883f2013-04-09 16:59:39 -0400824 data.extend(marshal.dumps(code_object))
825 self.assertEqual(self.loader.written[self.cached], bytes(data))
826
827 def test_code_with_everything(self):
828 # When everything should work.
829 code_object = self.loader.get_code(self.name)
830 self.verify_code(code_object)
831
832 def test_no_bytecode(self):
833 # If no bytecode exists then move on to the source.
834 self.loader.bytecode_path = "<does not exist>"
835 # Sanity check
836 with self.assertRaises(OSError):
Brett Cannon3ad327e2013-10-04 14:47:14 -0400837 bytecode_path = self.util.cache_from_source(self.path)
Brett Cannon100883f2013-04-09 16:59:39 -0400838 self.loader.get_data(bytecode_path)
839 code_object = self.loader.get_code(self.name)
840 self.verify_code(code_object, bytecode_written=True)
841
842 def test_code_bad_timestamp(self):
843 # Bytecode is only used when the timestamp matches the source EXACTLY.
844 for source_mtime in (0, 2):
845 assert source_mtime != self.loader.source_mtime
846 original = self.loader.source_mtime
847 self.loader.source_mtime = source_mtime
848 # If bytecode is used then EOFError would be raised by marshal.
849 self.loader.bytecode = self.loader.bytecode[8:]
850 code_object = self.loader.get_code(self.name)
851 self.verify_code(code_object, bytecode_written=True)
852 self.loader.source_mtime = original
853
854 def test_code_bad_magic(self):
855 # Skip over bytecode with a bad magic number.
856 self.setUp(magic=b'0000')
857 # If bytecode is used then EOFError would be raised by marshal.
858 self.loader.bytecode = self.loader.bytecode[8:]
859 code_object = self.loader.get_code(self.name)
860 self.verify_code(code_object, bytecode_written=True)
861
862 def test_dont_write_bytecode(self):
863 # Bytecode is not written if sys.dont_write_bytecode is true.
864 # Can assume it is false already thanks to the skipIf class decorator.
865 try:
866 sys.dont_write_bytecode = True
867 self.loader.bytecode_path = "<does not exist>"
868 code_object = self.loader.get_code(self.name)
869 self.assertNotIn(self.cached, self.loader.written)
870 finally:
871 sys.dont_write_bytecode = False
872
873 def test_no_set_data(self):
874 # If set_data is not defined, one can still read bytecode.
875 self.setUp(magic=b'0000')
Brett Cannon3ad327e2013-10-04 14:47:14 -0400876 original_set_data = self.loader.__class__.mro()[1].set_data
Brett Cannon100883f2013-04-09 16:59:39 -0400877 try:
Brett Cannon3ad327e2013-10-04 14:47:14 -0400878 del self.loader.__class__.mro()[1].set_data
Brett Cannon100883f2013-04-09 16:59:39 -0400879 code_object = self.loader.get_code(self.name)
880 self.verify_code(code_object)
881 finally:
Brett Cannon3ad327e2013-10-04 14:47:14 -0400882 self.loader.__class__.mro()[1].set_data = original_set_data
Brett Cannon100883f2013-04-09 16:59:39 -0400883
884 def test_set_data_raises_exceptions(self):
885 # Raising NotImplementedError or OSError is okay for set_data.
886 def raise_exception(exc):
887 def closure(*args, **kwargs):
888 raise exc
889 return closure
890
891 self.setUp(magic=b'0000')
892 self.loader.set_data = raise_exception(NotImplementedError)
893 code_object = self.loader.get_code(self.name)
894 self.verify_code(code_object)
895
896
Eric Snow3497c0b2014-05-16 11:40:40 -0600897(Frozen_SLBytecodeTests,
898 SourceSLBytecodeTests
899 ) = test_util.test_both(SourceLoaderBytecodeTests, init=init, util=util,
900 loader_mock=SPLIT_SL)
Brett Cannon3ad327e2013-10-04 14:47:14 -0400901
902
903class SourceLoaderGetSourceTests:
Brett Cannon100883f2013-04-09 16:59:39 -0400904
905 """Tests for importlib.abc.SourceLoader.get_source()."""
906
907 def test_default_encoding(self):
908 # Should have no problems with UTF-8 text.
909 name = 'mod'
Brett Cannon3ad327e2013-10-04 14:47:14 -0400910 mock = self.SourceOnlyLoaderMock('mod.file')
Brett Cannon100883f2013-04-09 16:59:39 -0400911 source = 'x = "ü"'
912 mock.source = source.encode('utf-8')
913 returned_source = mock.get_source(name)
914 self.assertEqual(returned_source, source)
915
916 def test_decoded_source(self):
917 # Decoding should work.
918 name = 'mod'
Brett Cannon3ad327e2013-10-04 14:47:14 -0400919 mock = self.SourceOnlyLoaderMock("mod.file")
Brett Cannon100883f2013-04-09 16:59:39 -0400920 source = "# coding: Latin-1\nx='ü'"
921 assert source.encode('latin-1') != source.encode('utf-8')
922 mock.source = source.encode('latin-1')
923 returned_source = mock.get_source(name)
924 self.assertEqual(returned_source, source)
925
926 def test_universal_newlines(self):
927 # PEP 302 says universal newlines should be used.
928 name = 'mod'
Brett Cannon3ad327e2013-10-04 14:47:14 -0400929 mock = self.SourceOnlyLoaderMock('mod.file')
Brett Cannon100883f2013-04-09 16:59:39 -0400930 source = "x = 42\r\ny = -13\r\n"
931 mock.source = source.encode('utf-8')
932 expect = io.IncrementalNewlineDecoder(None, True).decode(source)
933 self.assertEqual(mock.get_source(name), expect)
Brett Cannon2a922ed2009-03-09 03:35:50 +0000934
935
Eric Snow3497c0b2014-05-16 11:40:40 -0600936(Frozen_SourceOnlyLoaderGetSourceTests,
937 Source_SourceOnlyLoaderGetSourceTests
938 ) = test_util.test_both(SourceLoaderGetSourceTests,
939 SourceOnlyLoaderMock=SPLIT_SOL)
Brett Cannon3ad327e2013-10-04 14:47:14 -0400940
941
Brett Cannon2a922ed2009-03-09 03:35:50 +0000942if __name__ == '__main__':
Brett Cannon100883f2013-04-09 16:59:39 -0400943 unittest.main()