diff --git a/Lib/test/test_importlib/extension/test_case_sensitivity.py b/Lib/test/test_importlib/extension/test_case_sensitivity.py --- a/Lib/test/test_importlib/extension/test_case_sensitivity.py +++ b/Lib/test/test_importlib/extension/test_case_sensitivity.py @@ -9,8 +9,6 @@ frozen_machinery, source_machinery = util.import_importlib('importlib.machinery') -# XXX find_spec tests - @unittest.skipIf(ext_util.FILENAME is None, '_testcapi not available') @util.case_insensitive_tests class ExtensionModuleCaseSensitivityTest: diff --git a/Lib/test/test_importlib/extension/test_finder.py b/Lib/test/test_importlib/extension/test_finder.py --- a/Lib/test/test_importlib/extension/test_finder.py +++ b/Lib/test/test_importlib/extension/test_finder.py @@ -7,7 +7,6 @@ import unittest import warnings -# XXX find_spec tests class FinderTests(abc.FinderTests): diff --git a/Lib/test/test_importlib/import_/test_path.py b/Lib/test/test_importlib/import_/test_path.py --- a/Lib/test/test_importlib/import_/test_path.py +++ b/Lib/test/test_importlib/import_/test_path.py @@ -16,11 +16,14 @@ """Tests for PathFinder.""" + find = None + check_found = None + def test_failure(self): # Test None returned upon not finding a suitable loader. module = '' with util.import_state(): - self.assertIsNone(self.machinery.PathFinder.find_module(module)) + self.assertIsNone(self.find(module)) def test_sys_path(self): # Test that sys.path is used when 'path' is None. @@ -30,8 +33,8 @@ importer = util.mock_spec(module) with util.import_state(path_importer_cache={path: importer}, path=[path]): - loader = self.machinery.PathFinder.find_module(module) - self.assertIs(loader, importer) + found = self.find(module) + self.check_found(found, importer) def test_path(self): # Test that 'path' is used when set. @@ -40,8 +43,8 @@ path = '' importer = util.mock_spec(module) with util.import_state(path_importer_cache={path: importer}): - loader = self.machinery.PathFinder.find_module(module, [path]) - self.assertIs(loader, importer) + found = self.find(module, [path]) + self.check_found(found, importer) def test_empty_list(self): # An empty list should not count as asking for sys.path. @@ -50,7 +53,7 @@ importer = util.mock_spec(module) with util.import_state(path_importer_cache={path: importer}, path=[path]): - self.assertIsNone(self.machinery.PathFinder.find_module('module', [])) + self.assertIsNone(self.find('module', [])) def test_path_hooks(self): # Test that sys.path_hooks is used. @@ -60,8 +63,8 @@ importer = util.mock_spec(module) hook = import_util.mock_path_hook(path, importer=importer) with util.import_state(path_hooks=[hook]): - loader = self.machinery.PathFinder.find_module(module, [path]) - self.assertIs(loader, importer) + found = self.find(module, [path]) + self.check_found(found, importer) self.assertIn(path, sys.path_importer_cache) self.assertIs(sys.path_importer_cache[path], importer) @@ -73,7 +76,7 @@ path=[path_entry]): with warnings.catch_warnings(record=True) as w: warnings.simplefilter('always') - self.assertIsNone(self.machinery.PathFinder.find_module('os')) + self.assertIsNone(self.find('os')) self.assertIsNone(sys.path_importer_cache[path_entry]) self.assertEqual(len(w), 1) self.assertTrue(issubclass(w[-1].category, ImportWarning)) @@ -85,8 +88,8 @@ importer = util.mock_spec(module) hook = import_util.mock_path_hook(os.getcwd(), importer=importer) with util.import_state(path=[path], path_hooks=[hook]): - loader = self.machinery.PathFinder.find_module(module) - self.assertIs(loader, importer) + found = self.find(module) + self.check_found(found, importer) self.assertIn(os.getcwd(), sys.path_importer_cache) def test_None_on_sys_path(self): @@ -112,12 +115,49 @@ if email is not missing: sys.modules['email'] = email -Frozen_FinderTests, Source_FinderTests = util.test_both( - FinderTests, importlib=importlib, machinery=machinery) + +class FindModuleTests(FinderTests): + def find(self, *args, **kwargs): + return self.machinery.PathFinder.find_module(*args, **kwargs) + def check_found(self, found, importer): + self.assertIs(found, importer) + + +Frozen_FindModuleTests, Source_FindModuleTests = util.test_both( + FindModuleTests, importlib=importlib, machinery=machinery) + + +class FindSpecTests(FinderTests): + def find(self, *args, **kwargs): + return self.machinery.PathFinder.find_spec(*args, **kwargs) + def check_found(self, found, importer): + self.assertIs(found.loader, importer) + + +Frozen_FindSpecTests, Source_FindSpecTests = util.test_both( + FindSpecTests, importlib=importlib, machinery=machinery) class PathEntryFinderTests: + def test_finder_with_failing_find_spec(self): + # PathEntryFinder with find_module() defined should work. + # Issue #20763. + class Finder: + path_location = 'test_finder_with_find_module' + def __init__(self, path): + if path != self.path_location: + raise ImportError + + @staticmethod + def find_module(fullname): + return None + + + with util.import_state(path=[Finder.path_location]+sys.path[:], + path_hooks=[Finder]): + self.machinery.PathFinder.find_spec('importlib') + def test_finder_with_failing_find_module(self): # PathEntryFinder with find_module() defined should work. # Issue #20763. @@ -134,7 +174,7 @@ with util.import_state(path=[Finder.path_location]+sys.path[:], path_hooks=[Finder]): - self.machinery.PathFinder.find_spec('importlib') + self.machinery.PathFinder.find_module('importlib') Frozen_PEFTests, Source_PEFTests = util.test_both( PathEntryFinderTests, machinery=machinery) diff --git a/Lib/test/test_importlib/source/test_file_loader.py b/Lib/test/test_importlib/source/test_file_loader.py --- a/Lib/test/test_importlib/source/test_file_loader.py +++ b/Lib/test/test_importlib/source/test_file_loader.py @@ -218,7 +218,7 @@ # PEP 302 with warnings.catch_warnings(): warnings.simplefilter('ignore', DeprecationWarning) - mod = loader.load_module('_temp') # XXX + mod = loader.load_module('_temp') # Sanity checks. self.assertEqual(mod.__cached__, compiled) self.assertEqual(mod.x, 5) @@ -244,12 +244,7 @@ class BadBytecodeTest: def import_(self, file, module_name): - loader = self.loader(module_name, file) - with warnings.catch_warnings(): - warnings.simplefilter('ignore', DeprecationWarning) - # XXX Change to use exec_module(). - module = loader.load_module(module_name) - self.assertIn(module_name, sys.modules) + raise NotImplementedError def manipulate_bytecode(self, name, mapping, manipulator, *, del_source=False): diff --git a/Lib/test/test_importlib/source/test_path_hook.py b/Lib/test/test_importlib/source/test_path_hook.py --- a/Lib/test/test_importlib/source/test_path_hook.py +++ b/Lib/test/test_importlib/source/test_path_hook.py @@ -17,12 +17,22 @@ def test_success(self): with source_util.create_modules('dummy') as mapping: self.assertTrue(hasattr(self.path_hook()(mapping['.root']), - 'find_module')) + 'find_spec')) + + def test_success_legacy(self): + with source_util.create_modules('dummy') as mapping: + self.assertTrue(hasattr(self.path_hook()(mapping['.root']), + 'find_module')) def test_empty_string(self): # The empty string represents the cwd. + self.assertTrue(hasattr(self.path_hook()(''), 'find_spec')) + + def test_empty_string_legacy(self): + # The empty string represents the cwd. self.assertTrue(hasattr(self.path_hook()(''), 'find_module')) + Frozen_PathHookTest, Source_PathHooktest = util.test_both(PathHookTest, machinery=machinery) diff --git a/Lib/test/test_importlib/test_abc.py b/Lib/test/test_importlib/test_abc.py --- a/Lib/test/test_importlib/test_abc.py +++ b/Lib/test/test_importlib/test_abc.py @@ -149,8 +149,6 @@ def find_module(self, fullname, path): return super().find_module(fullname, path) -Frozen_MPF, Source_MPF = make_abc_subclasses(MetaPathFinder) - class MetaPathFinderDefaultsTests: @@ -172,8 +170,6 @@ def find_loader(self, fullname): return super().find_loader(fullname) -Frozen_PEF, Source_PEF = make_abc_subclasses(PathEntryFinder) - class PathEntryFinderDefaultsTests: @@ -198,10 +194,11 @@ return super().load_module(fullname) -Frozen_L, Source_L = make_abc_subclasses(Loader) +class LoaderDefaultsTests: - -class LoaderDefaultsTests: + def test_create_module(self): + spec = 'a spec' + self.assertIsNone(self.ins.create_module(spec)) def test_load_module(self): with self.assertRaises(ImportError): @@ -227,9 +224,6 @@ return super().get_data(path) -Frozen_RL, Source_RL = make_abc_subclasses(ResourceLoader) - - class ResourceLoaderDefaultsTests: def test_get_data(self): @@ -273,6 +267,7 @@ def get_filename(self, fullname): return super().get_filename(fullname) + Frozen_EL, Source_EL = make_abc_subclasses(ExecutionLoader) @@ -512,6 +507,12 @@ support.unload(self.module_name) self.addCleanup(support.unload, self.module_name) + def load(self, loader): + spec = self.util.spec_from_loader(self.module_name, loader) + with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + return self.init._bootstrap._SpecMethods(spec)._load_unlocked() + def mock_get_code(self): return mock.patch.object(self.InspectLoaderSubclass, 'get_code') @@ -521,9 +522,7 @@ mocked_get_code.side_effect = ImportError with self.assertRaises(ImportError): loader = self.InspectLoaderSubclass() - with warnings.catch_warnings(): - warnings.simplefilter('ignore', DeprecationWarning) - loader.load_module(self.module_name) + self.load(loader) def test_get_code_None(self): # If get_code() returns None, raise ImportError. @@ -531,7 +530,7 @@ mocked_get_code.return_value = None with self.assertRaises(ImportError): loader = self.InspectLoaderSubclass() - loader.load_module(self.module_name) + self.load(loader) def test_module_returned(self): # The loaded module should be returned. @@ -539,15 +538,19 @@ with self.mock_get_code() as mocked_get_code: mocked_get_code.return_value = code loader = self.InspectLoaderSubclass() - module = loader.load_module(self.module_name) + module = self.load(loader) self.assertEqual(module, sys.modules[self.module_name]) class Frozen_ILLoadModuleTests(InspectLoaderLoadModuleTests, unittest.TestCase): InspectLoaderSubclass = Frozen_IL + init = frozen_init + util = frozen_util class Source_ILLoadModuleTests(InspectLoaderLoadModuleTests, unittest.TestCase): InspectLoaderSubclass = Source_IL + init = source_init + util = source_util ##### ExecutionLoader concrete methods ######################################### diff --git a/Lib/test/test_importlib/test_api.py b/Lib/test/test_importlib/test_api.py --- a/Lib/test/test_importlib/test_api.py +++ b/Lib/test/test_importlib/test_api.py @@ -100,9 +100,7 @@ class FindLoaderTests: - class FakeMetaFinder: - @staticmethod - def find_module(name, path=None): return name, path + FakeMetaFinder = None def test_sys_modules(self): # If a module with __loader__ is in sys.modules, then return it. @@ -171,10 +169,36 @@ warnings.simplefilter('ignore', DeprecationWarning) self.assertIsNone(self.init.find_loader('nevergoingtofindthismodule')) -class Frozen_FindLoaderTests(FindLoaderTests, unittest.TestCase): + +class FindLoaderPEP451Tests(FindLoaderTests): + + class FakeMetaFinder: + @staticmethod + def find_spec(name, path=None, target=None): + return source_machinery.ModuleSpec(name, (name, path)) + + +class Frozen_FindLoaderPEP451Tests(FindLoaderPEP451Tests, unittest.TestCase): init = frozen_init -class Source_FindLoaderTests(FindLoaderTests, unittest.TestCase): + +class Source_FindLoaderPEP451Tests(FindLoaderPEP451Tests, unittest.TestCase): + init = source_init + + +class FindLoaderPEP302Tests(FindLoaderTests): + + class FakeMetaFinder: + @staticmethod + def find_module(name, path=None): + return name, path + + +class Frozen_FindLoaderPEP302Tests(FindLoaderPEP302Tests, unittest.TestCase): + init = frozen_init + + +class Source_FindLoaderPEP302Tests(FindLoaderPEP302Tests, unittest.TestCase): init = source_init