summaryrefslogtreecommitdiff
path: root/Lib/test/test_importlib
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/test/test_importlib')
-rw-r--r--Lib/test/test_importlib/__init__.py34
-rw-r--r--Lib/test/test_importlib/__main__.py22
-rw-r--r--Lib/test/test_importlib/abc.py9
-rw-r--r--Lib/test/test_importlib/builtin/__init__.py13
-rw-r--r--Lib/test/test_importlib/builtin/__main__.py4
-rw-r--r--Lib/test/test_importlib/builtin/test_finder.py60
-rw-r--r--Lib/test/test_importlib/builtin/test_loader.py49
-rw-r--r--Lib/test/test_importlib/extension/__init__.py16
-rw-r--r--Lib/test/test_importlib/extension/__main__.py4
-rw-r--r--Lib/test/test_importlib/extension/test_case_sensitivity.py29
-rw-r--r--Lib/test/test_importlib/extension/test_finder.py25
-rw-r--r--Lib/test/test_importlib/extension/test_loader.py30
-rw-r--r--Lib/test/test_importlib/extension/test_path_hook.py20
-rw-r--r--Lib/test/test_importlib/extension/util.py1
-rw-r--r--Lib/test/test_importlib/frozen/__init__.py16
-rw-r--r--Lib/test/test_importlib/frozen/__main__.py4
-rw-r--r--Lib/test/test_importlib/frozen/test_finder.py49
-rw-r--r--Lib/test/test_importlib/frozen/test_loader.py156
-rw-r--r--Lib/test/test_importlib/import_/__init__.py16
-rw-r--r--Lib/test/test_importlib/import_/__main__.py4
-rw-r--r--Lib/test/test_importlib/import_/test___loader__.py70
-rw-r--r--Lib/test/test_importlib/import_/test___package__.py56
-rw-r--r--Lib/test/test_importlib/import_/test_api.py73
-rw-r--r--Lib/test/test_importlib/import_/test_caching.py32
-rw-r--r--Lib/test/test_importlib/import_/test_fromlist.py38
-rw-r--r--Lib/test/test_importlib/import_/test_meta_path.py68
-rw-r--r--Lib/test/test_importlib/import_/test_packages.py44
-rw-r--r--Lib/test/test_importlib/import_/test_path.py76
-rw-r--r--Lib/test/test_importlib/import_/test_relative_imports.py53
-rw-r--r--Lib/test/test_importlib/import_/util.py20
-rw-r--r--Lib/test/test_importlib/namespace_pkgs/both_portions/foo/one.py1
-rw-r--r--Lib/test/test_importlib/namespace_pkgs/both_portions/foo/two.py1
-rw-r--r--Lib/test/test_importlib/namespace_pkgs/missing_directory.zipbin0 -> 515 bytes
-rw-r--r--Lib/test/test_importlib/namespace_pkgs/module_and_namespace_package/a_test.py1
-rw-r--r--Lib/test/test_importlib/namespace_pkgs/module_and_namespace_package/a_test/empty0
-rw-r--r--Lib/test/test_importlib/namespace_pkgs/nested_portion1.zipbin0 -> 556 bytes
-rw-r--r--Lib/test/test_importlib/namespace_pkgs/not_a_namespace_pkg/foo/__init__.py0
-rw-r--r--Lib/test/test_importlib/namespace_pkgs/not_a_namespace_pkg/foo/one.py1
-rw-r--r--Lib/test/test_importlib/namespace_pkgs/portion1/foo/one.py1
-rw-r--r--Lib/test/test_importlib/namespace_pkgs/portion2/foo/two.py1
-rw-r--r--Lib/test/test_importlib/namespace_pkgs/project1/parent/child/one.py1
-rw-r--r--Lib/test/test_importlib/namespace_pkgs/project2/parent/child/two.py1
-rw-r--r--Lib/test/test_importlib/namespace_pkgs/project3/parent/child/three.py1
-rw-r--r--Lib/test/test_importlib/namespace_pkgs/top_level_portion1.zipbin0 -> 332 bytes
-rw-r--r--Lib/test/test_importlib/source/__init__.py16
-rw-r--r--Lib/test/test_importlib/source/__main__.py4
-rw-r--r--Lib/test/test_importlib/source/test_abc_loader.py906
-rw-r--r--Lib/test/test_importlib/source/test_case_sensitivity.py53
-rw-r--r--Lib/test/test_importlib/source/test_file_loader.py230
-rw-r--r--Lib/test/test_importlib/source/test_finder.py83
-rw-r--r--Lib/test/test_importlib/source/test_path_hook.py18
-rw-r--r--Lib/test/test_importlib/source/test_source_encoding.py66
-rw-r--r--Lib/test/test_importlib/source/util.py1
-rw-r--r--Lib/test/test_importlib/test_abc.py930
-rw-r--r--Lib/test/test_importlib/test_api.py331
-rw-r--r--Lib/test/test_importlib/test_locks.py71
-rw-r--r--Lib/test/test_importlib/test_namespace_pkgs.py293
-rw-r--r--Lib/test/test_importlib/test_spec.py957
-rw-r--r--Lib/test/test_importlib/test_util.py450
-rw-r--r--Lib/test/test_importlib/test_windows.py29
-rw-r--r--Lib/test/test_importlib/util.py105
61 files changed, 4032 insertions, 1611 deletions
diff --git a/Lib/test/test_importlib/__init__.py b/Lib/test/test_importlib/__init__.py
index 0e345cdc2d..4b16ecc311 100644
--- a/Lib/test/test_importlib/__init__.py
+++ b/Lib/test/test_importlib/__init__.py
@@ -1,33 +1,5 @@
import os
-import sys
-from test import support
-import unittest
+from test.support import load_package_tests
-def test_suite(package=__package__, directory=os.path.dirname(__file__)):
- suite = unittest.TestSuite()
- for name in os.listdir(directory):
- if name.startswith(('.', '__')):
- continue
- path = os.path.join(directory, name)
- if (os.path.isfile(path) and name.startswith('test_') and
- name.endswith('.py')):
- submodule_name = os.path.splitext(name)[0]
- module_name = "{0}.{1}".format(package, submodule_name)
- __import__(module_name, level=0)
- module_tests = unittest.findTestCases(sys.modules[module_name])
- suite.addTest(module_tests)
- elif os.path.isdir(path):
- package_name = "{0}.{1}".format(package, name)
- __import__(package_name, level=0)
- package_tests = getattr(sys.modules[package_name], 'test_suite')()
- suite.addTest(package_tests)
- else:
- continue
- return suite
-
-
-def test_main():
- start_dir = os.path.dirname(__file__)
- top_dir = os.path.dirname(os.path.dirname(start_dir))
- test_loader = unittest.TestLoader()
- support.run_unittest(test_loader.discover(start_dir, top_level_dir=top_dir))
+def load_tests(*args):
+ return load_package_tests(os.path.dirname(__file__), *args)
diff --git a/Lib/test/test_importlib/__main__.py b/Lib/test/test_importlib/__main__.py
index c39712871f..40a23a297e 100644
--- a/Lib/test/test_importlib/__main__.py
+++ b/Lib/test/test_importlib/__main__.py
@@ -1,20 +1,4 @@
-"""Run importlib's test suite.
+from . import load_tests
+import unittest
-Specifying the ``--builtin`` flag will run tests, where applicable, with
-builtins.__import__ instead of importlib.__import__.
-
-"""
-from . import test_main
-
-
-if __name__ == '__main__':
- import argparse
-
- parser = argparse.ArgumentParser(description='Execute the importlib test '
- 'suite')
- parser.add_argument('-b', '--builtin', action='store_true', default=False,
- help='use builtins.__import__() instead of importlib')
- args = parser.parse_args()
- if args.builtin:
- util.using___import__ = True
- test_main()
+unittest.main()
diff --git a/Lib/test/test_importlib/abc.py b/Lib/test/test_importlib/abc.py
index 2c17ac329b..2070dadc23 100644
--- a/Lib/test/test_importlib/abc.py
+++ b/Lib/test/test_importlib/abc.py
@@ -2,7 +2,7 @@ import abc
import unittest
-class FinderTests(unittest.TestCase, metaclass=abc.ABCMeta):
+class FinderTests(metaclass=abc.ABCMeta):
"""Basic tests for a finder to pass."""
@@ -39,7 +39,7 @@ class FinderTests(unittest.TestCase, metaclass=abc.ABCMeta):
pass
-class LoaderTests(unittest.TestCase, metaclass=abc.ABCMeta):
+class LoaderTests(metaclass=abc.ABCMeta):
@abc.abstractmethod
def test_module(self):
@@ -81,11 +81,6 @@ class LoaderTests(unittest.TestCase, metaclass=abc.ABCMeta):
pass
@abc.abstractmethod
- def test_module_reuse(self):
- """If a module is already in sys.modules, it should be reused."""
- pass
-
- @abc.abstractmethod
def test_state_after_failure(self):
"""If a module is already in sys.modules and a reload fails
(e.g. a SyntaxError), the module should be in the state it was before
diff --git a/Lib/test/test_importlib/builtin/__init__.py b/Lib/test/test_importlib/builtin/__init__.py
index 15c0ade207..4b16ecc311 100644
--- a/Lib/test/test_importlib/builtin/__init__.py
+++ b/Lib/test/test_importlib/builtin/__init__.py
@@ -1,12 +1,5 @@
-from .. import test_suite
import os
+from test.support import load_package_tests
-
-def test_suite():
- directory = os.path.dirname(__file__)
- return test_suite('importlib.test.builtin', directory)
-
-
-if __name__ == '__main__':
- from test.support import run_unittest
- run_unittest(test_suite())
+def load_tests(*args):
+ return load_package_tests(os.path.dirname(__file__), *args)
diff --git a/Lib/test/test_importlib/builtin/__main__.py b/Lib/test/test_importlib/builtin/__main__.py
new file mode 100644
index 0000000000..40a23a297e
--- /dev/null
+++ b/Lib/test/test_importlib/builtin/__main__.py
@@ -0,0 +1,4 @@
+from . import load_tests
+import unittest
+
+unittest.main()
diff --git a/Lib/test/test_importlib/builtin/test_finder.py b/Lib/test/test_importlib/builtin/test_finder.py
index da0ef28589..934562feb6 100644
--- a/Lib/test/test_importlib/builtin/test_finder.py
+++ b/Lib/test/test_importlib/builtin/test_finder.py
@@ -1,11 +1,53 @@
-from importlib import machinery
from .. import abc
from .. import util
from . import util as builtin_util
+frozen_machinery, source_machinery = util.import_importlib('importlib.machinery')
+
import sys
import unittest
+
+class FindSpecTests(abc.FinderTests):
+
+ """Test find_spec() for built-in modules."""
+
+ def test_module(self):
+ # Common case.
+ with util.uncache(builtin_util.NAME):
+ found = self.machinery.BuiltinImporter.find_spec(builtin_util.NAME)
+ self.assertTrue(found)
+ self.assertEqual(found.origin, 'built-in')
+
+ # Built-in modules cannot be a package.
+ test_package = None
+
+ # Built-in modules cannobt be in a package.
+ test_module_in_package = None
+
+ # Built-in modules cannot be a package.
+ test_package_in_package = None
+
+ # Built-in modules cannot be a package.
+ test_package_over_module = None
+
+ def test_failure(self):
+ name = 'importlib'
+ assert name not in sys.builtin_module_names
+ spec = self.machinery.BuiltinImporter.find_spec(name)
+ self.assertIsNone(spec)
+
+ def test_ignore_path(self):
+ # The value for 'path' should always trigger a failed import.
+ with util.uncache(builtin_util.NAME):
+ spec = self.machinery.BuiltinImporter.find_spec(builtin_util.NAME,
+ ['pkg'])
+ self.assertIsNone(spec)
+
+Frozen_FindSpecTests, Source_FindSpecTests = util.test_both(FindSpecTests,
+ machinery=[frozen_machinery, source_machinery])
+
+
class FinderTests(abc.FinderTests):
"""Test find_module() for built-in modules."""
@@ -13,8 +55,9 @@ class FinderTests(abc.FinderTests):
def test_module(self):
# Common case.
with util.uncache(builtin_util.NAME):
- found = machinery.BuiltinImporter.find_module(builtin_util.NAME)
+ found = self.machinery.BuiltinImporter.find_module(builtin_util.NAME)
self.assertTrue(found)
+ self.assertTrue(hasattr(found, 'load_module'))
# Built-in modules cannot be a package.
test_package = test_package_in_package = test_package_over_module = None
@@ -24,22 +67,19 @@ class FinderTests(abc.FinderTests):
def test_failure(self):
assert 'importlib' not in sys.builtin_module_names
- loader = machinery.BuiltinImporter.find_module('importlib')
+ loader = self.machinery.BuiltinImporter.find_module('importlib')
self.assertIsNone(loader)
def test_ignore_path(self):
# The value for 'path' should always trigger a failed import.
with util.uncache(builtin_util.NAME):
- loader = machinery.BuiltinImporter.find_module(builtin_util.NAME,
+ loader = self.machinery.BuiltinImporter.find_module(builtin_util.NAME,
['pkg'])
self.assertIsNone(loader)
-
-
-def test_main():
- from test.support import run_unittest
- run_unittest(FinderTests)
+Frozen_FinderTests, Source_FinderTests = util.test_both(FinderTests,
+ machinery=[frozen_machinery, source_machinery])
if __name__ == '__main__':
- test_main()
+ unittest.main()
diff --git a/Lib/test/test_importlib/builtin/test_loader.py b/Lib/test/test_importlib/builtin/test_loader.py
index 12a79c6ba9..1f8357402f 100644
--- a/Lib/test/test_importlib/builtin/test_loader.py
+++ b/Lib/test/test_importlib/builtin/test_loader.py
@@ -1,9 +1,9 @@
-import importlib
-from importlib import machinery
from .. import abc
from .. import util
from . import util as builtin_util
+frozen_machinery, source_machinery = util.import_importlib('importlib.machinery')
+
import sys
import types
import unittest
@@ -13,8 +13,9 @@ class LoaderTests(abc.LoaderTests):
"""Test load_module() for built-in modules."""
- verification = {'__name__': 'errno', '__package__': '',
- '__loader__': machinery.BuiltinImporter}
+ def setUp(self):
+ self.verification = {'__name__': 'errno', '__package__': '',
+ '__loader__': self.machinery.BuiltinImporter}
def verify(self, module):
"""Verify that the module matches against what it should have."""
@@ -23,8 +24,8 @@ class LoaderTests(abc.LoaderTests):
self.assertEqual(getattr(module, attr), value)
self.assertIn(module.__name__, sys.modules)
- load_module = staticmethod(lambda name:
- machinery.BuiltinImporter.load_module(name))
+ def load_module(self, name):
+ return self.machinery.BuiltinImporter.load_module(name)
def test_module(self):
# Common case.
@@ -55,45 +56,51 @@ class LoaderTests(abc.LoaderTests):
def test_already_imported(self):
# Using the name of a module already imported but not a built-in should
# still fail.
- assert hasattr(importlib, '__file__') # Not a built-in.
+ module_name = 'builtin_reload_test'
+ assert module_name not in sys.builtin_module_names
+ with util.uncache(module_name):
+ module = types.ModuleType(module_name)
+ sys.modules[module_name] = module
with self.assertRaises(ImportError) as cm:
- self.load_module('importlib')
- self.assertEqual(cm.exception.name, 'importlib')
+ self.load_module(module_name)
+ self.assertEqual(cm.exception.name, module_name)
+
+
+Frozen_LoaderTests, Source_LoaderTests = util.test_both(LoaderTests,
+ machinery=[frozen_machinery, source_machinery])
-class InspectLoaderTests(unittest.TestCase):
+class InspectLoaderTests:
"""Tests for InspectLoader methods for BuiltinImporter."""
def test_get_code(self):
# There is no code object.
- result = machinery.BuiltinImporter.get_code(builtin_util.NAME)
+ result = self.machinery.BuiltinImporter.get_code(builtin_util.NAME)
self.assertIsNone(result)
def test_get_source(self):
# There is no source.
- result = machinery.BuiltinImporter.get_source(builtin_util.NAME)
+ result = self.machinery.BuiltinImporter.get_source(builtin_util.NAME)
self.assertIsNone(result)
def test_is_package(self):
# Cannot be a package.
- result = machinery.BuiltinImporter.is_package(builtin_util.NAME)
- self.assertTrue(not result)
+ result = self.machinery.BuiltinImporter.is_package(builtin_util.NAME)
+ self.assertFalse(result)
def test_not_builtin(self):
# Modules not built-in should raise ImportError.
for meth_name in ('get_code', 'get_source', 'is_package'):
- method = getattr(machinery.BuiltinImporter, meth_name)
+ method = getattr(self.machinery.BuiltinImporter, meth_name)
with self.assertRaises(ImportError) as cm:
method(builtin_util.BAD_NAME)
self.assertRaises(builtin_util.BAD_NAME)
-
-
-def test_main():
- from test.support import run_unittest
- run_unittest(LoaderTests, InspectLoaderTests)
+Frozen_InspectLoaderTests, Source_InspectLoaderTests = util.test_both(
+ InspectLoaderTests,
+ machinery=[frozen_machinery, source_machinery])
if __name__ == '__main__':
- test_main()
+ unittest.main()
diff --git a/Lib/test/test_importlib/extension/__init__.py b/Lib/test/test_importlib/extension/__init__.py
index c0339236fa..4b16ecc311 100644
--- a/Lib/test/test_importlib/extension/__init__.py
+++ b/Lib/test/test_importlib/extension/__init__.py
@@ -1,13 +1,5 @@
-from .. import test_suite
-import os.path
-import unittest
+import os
+from test.support import load_package_tests
-
-def test_suite():
- directory = os.path.dirname(__file__)
- return test_suite('importlib.test.extension', directory)
-
-
-if __name__ == '__main__':
- from test.support import run_unittest
- run_unittest(test_suite())
+def load_tests(*args):
+ return load_package_tests(os.path.dirname(__file__), *args)
diff --git a/Lib/test/test_importlib/extension/__main__.py b/Lib/test/test_importlib/extension/__main__.py
new file mode 100644
index 0000000000..40a23a297e
--- /dev/null
+++ b/Lib/test/test_importlib/extension/__main__.py
@@ -0,0 +1,4 @@
+from . import load_tests
+import unittest
+
+unittest.main()
diff --git a/Lib/test/test_importlib/extension/test_case_sensitivity.py b/Lib/test/test_importlib/extension/test_case_sensitivity.py
index 76c53e4fd6..bb2528e626 100644
--- a/Lib/test/test_importlib/extension/test_case_sensitivity.py
+++ b/Lib/test/test_importlib/extension/test_case_sensitivity.py
@@ -1,22 +1,27 @@
-import imp
+from importlib import _bootstrap
import sys
from test import support
import unittest
-from importlib import _bootstrap
+
from .. import util
from . import util as ext_util
+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(unittest.TestCase):
+class ExtensionModuleCaseSensitivityTest:
def find_module(self):
good_name = ext_util.NAME
bad_name = good_name.upper()
assert good_name != bad_name
- finder = _bootstrap.FileFinder(ext_util.PATH,
- (_bootstrap.ExtensionFileLoader,
- _bootstrap.EXTENSION_SUFFIXES))
+ finder = self.machinery.FileFinder(ext_util.PATH,
+ (self.machinery.ExtensionFileLoader,
+ self.machinery.EXTENSION_SUFFIXES))
return finder.find_module(bad_name)
def test_case_sensitive(self):
@@ -37,14 +42,10 @@ class ExtensionModuleCaseSensitivityTest(unittest.TestCase):
loader = self.find_module()
self.assertTrue(hasattr(loader, 'load_module'))
-
-
-
-def test_main():
- if ext_util.FILENAME is None:
- return
- support.run_unittest(ExtensionModuleCaseSensitivityTest)
+Frozen_ExtensionCaseSensitivity, Source_ExtensionCaseSensitivity = util.test_both(
+ ExtensionModuleCaseSensitivityTest,
+ machinery=[frozen_machinery, source_machinery])
if __name__ == '__main__':
- test_main()
+ unittest.main()
diff --git a/Lib/test/test_importlib/extension/test_finder.py b/Lib/test/test_importlib/extension/test_finder.py
index 37f67727b0..990f29c4e5 100644
--- a/Lib/test/test_importlib/extension/test_finder.py
+++ b/Lib/test/test_importlib/extension/test_finder.py
@@ -1,18 +1,25 @@
-from importlib import machinery
from .. import abc
+from .. import util as test_util
from . import util
+machinery = test_util.import_importlib('importlib.machinery')
+
import unittest
+import warnings
+
+# XXX find_spec tests
class FinderTests(abc.FinderTests):
"""Test the finder for extension modules."""
def find_module(self, fullname):
- importer = machinery.FileFinder(util.PATH,
- (machinery.ExtensionFileLoader,
- machinery.EXTENSION_SUFFIXES))
- return importer.find_module(fullname)
+ importer = self.machinery.FileFinder(util.PATH,
+ (self.machinery.ExtensionFileLoader,
+ self.machinery.EXTENSION_SUFFIXES))
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ return importer.find_module(fullname)
def test_module(self):
self.assertTrue(self.find_module(util.NAME))
@@ -29,11 +36,9 @@ class FinderTests(abc.FinderTests):
def test_failure(self):
self.assertIsNone(self.find_module('asdfjkl;'))
-
-def test_main():
- from test.support import run_unittest
- run_unittest(FinderTests)
+Frozen_FinderTests, Source_FinderTests = test_util.test_both(
+ FinderTests, machinery=machinery)
if __name__ == '__main__':
- test_main()
+ unittest.main()
diff --git a/Lib/test/test_importlib/extension/test_loader.py b/Lib/test/test_importlib/extension/test_loader.py
index e790675f58..fd9abf269b 100644
--- a/Lib/test/test_importlib/extension/test_loader.py
+++ b/Lib/test/test_importlib/extension/test_loader.py
@@ -1,10 +1,12 @@
-from importlib import machinery
from . import util as ext_util
from .. import abc
from .. import util
+machinery = util.import_importlib('importlib.machinery')
+
import os.path
import sys
+import types
import unittest
@@ -13,8 +15,8 @@ class LoaderTests(abc.LoaderTests):
"""Test load_module() for extension modules."""
def setUp(self):
- self.loader = machinery.ExtensionFileLoader(ext_util.NAME,
- ext_util.FILEPATH)
+ self.loader = self.machinery.ExtensionFileLoader(ext_util.NAME,
+ ext_util.FILEPATH)
def load_module(self, fullname):
return self.loader.load_module(fullname)
@@ -26,6 +28,15 @@ class LoaderTests(abc.LoaderTests):
with self.assertRaises(ImportError):
self.load_module('XXX')
+ def test_equality(self):
+ other = self.machinery.ExtensionFileLoader(ext_util.NAME,
+ ext_util.FILEPATH)
+ self.assertEqual(self.loader, other)
+
+ def test_inequality(self):
+ other = self.machinery.ExtensionFileLoader('_' + ext_util.NAME,
+ ext_util.FILEPATH)
+ self.assertNotEqual(self.loader, other)
def test_module(self):
with util.uncache(ext_util.NAME):
@@ -36,7 +47,7 @@ class LoaderTests(abc.LoaderTests):
self.assertEqual(getattr(module, attr), value)
self.assertIn(ext_util.NAME, sys.modules)
self.assertIsInstance(module.__loader__,
- machinery.ExtensionFileLoader)
+ self.machinery.ExtensionFileLoader)
# No extension module as __init__ available for testing.
test_package = None
@@ -61,16 +72,15 @@ class LoaderTests(abc.LoaderTests):
def test_is_package(self):
self.assertFalse(self.loader.is_package(ext_util.NAME))
- for suffix in machinery.EXTENSION_SUFFIXES:
+ for suffix in self.machinery.EXTENSION_SUFFIXES:
path = os.path.join('some', 'path', 'pkg', '__init__' + suffix)
- loader = machinery.ExtensionFileLoader('pkg', path)
+ loader = self.machinery.ExtensionFileLoader('pkg', path)
self.assertTrue(loader.is_package('pkg'))
+Frozen_LoaderTests, Source_LoaderTests = util.test_both(
+ LoaderTests, machinery=machinery)
-def test_main():
- from test.support import run_unittest
- run_unittest(LoaderTests)
if __name__ == '__main__':
- test_main()
+ unittest.main()
diff --git a/Lib/test/test_importlib/extension/test_path_hook.py b/Lib/test/test_importlib/extension/test_path_hook.py
index 1d969a1b28..49d6734711 100644
--- a/Lib/test/test_importlib/extension/test_path_hook.py
+++ b/Lib/test/test_importlib/extension/test_path_hook.py
@@ -1,32 +1,32 @@
-from importlib import machinery
+from .. import util as test_util
from . import util
+machinery = test_util.import_importlib('importlib.machinery')
+
import collections
-import imp
import sys
import unittest
-class PathHookTests(unittest.TestCase):
+class PathHookTests:
"""Test the path hook for extension modules."""
# XXX Should it only succeed for pre-existing directories?
# XXX Should it only work for directories containing an extension module?
def hook(self, entry):
- return machinery.FileFinder.path_hook((machinery.ExtensionFileLoader,
- machinery.EXTENSION_SUFFIXES))(entry)
+ return self.machinery.FileFinder.path_hook(
+ (self.machinery.ExtensionFileLoader,
+ self.machinery.EXTENSION_SUFFIXES))(entry)
def test_success(self):
# Path hook should handle a directory where a known extension module
# exists.
self.assertTrue(hasattr(self.hook(util.PATH), 'find_module'))
-
-def test_main():
- from test.support import run_unittest
- run_unittest(PathHookTests)
+Frozen_PathHooksTests, Source_PathHooksTests = test_util.test_both(
+ PathHookTests, machinery=machinery)
if __name__ == '__main__':
- test_main()
+ unittest.main()
diff --git a/Lib/test/test_importlib/extension/util.py b/Lib/test/test_importlib/extension/util.py
index a266dd98c8..8d089f0d7c 100644
--- a/Lib/test/test_importlib/extension/util.py
+++ b/Lib/test/test_importlib/extension/util.py
@@ -1,4 +1,3 @@
-import imp
from importlib import machinery
import os
import sys
diff --git a/Lib/test/test_importlib/frozen/__init__.py b/Lib/test/test_importlib/frozen/__init__.py
index 9ef103bce7..4b16ecc311 100644
--- a/Lib/test/test_importlib/frozen/__init__.py
+++ b/Lib/test/test_importlib/frozen/__init__.py
@@ -1,13 +1,5 @@
-from .. import test_suite
-import os.path
-import unittest
+import os
+from test.support import load_package_tests
-
-def test_suite():
- directory = os.path.dirname(__file__)
- return test_suite('importlib.test.frozen', directory)
-
-
-if __name__ == '__main__':
- from test.support import run_unittest
- run_unittest(test_suite())
+def load_tests(*args):
+ return load_package_tests(os.path.dirname(__file__), *args)
diff --git a/Lib/test/test_importlib/frozen/__main__.py b/Lib/test/test_importlib/frozen/__main__.py
new file mode 100644
index 0000000000..40a23a297e
--- /dev/null
+++ b/Lib/test/test_importlib/frozen/__main__.py
@@ -0,0 +1,4 @@
+from . import load_tests
+import unittest
+
+unittest.main()
diff --git a/Lib/test/test_importlib/frozen/test_finder.py b/Lib/test/test_importlib/frozen/test_finder.py
index f0abe0e989..f9f97f3851 100644
--- a/Lib/test/test_importlib/frozen/test_finder.py
+++ b/Lib/test/test_importlib/frozen/test_finder.py
@@ -1,15 +1,52 @@
-from importlib import machinery
from .. import abc
+from .. import util
+
+machinery = util.import_importlib('importlib.machinery')
import unittest
+class FindSpecTests(abc.FinderTests):
+
+ """Test finding frozen modules."""
+
+ def find(self, name, path=None):
+ finder = self.machinery.FrozenImporter
+ return finder.find_spec(name, path)
+
+ def test_module(self):
+ name = '__hello__'
+ spec = self.find(name)
+ self.assertEqual(spec.origin, 'frozen')
+
+ def test_package(self):
+ spec = self.find('__phello__')
+ self.assertIsNotNone(spec)
+
+ def test_module_in_package(self):
+ spec = self.find('__phello__.spam', ['__phello__'])
+ self.assertIsNotNone(spec)
+
+ # No frozen package within another package to test with.
+ test_package_in_package = None
+
+ # No easy way to test.
+ test_package_over_module = None
+
+ def test_failure(self):
+ spec = self.find('<not real>')
+ self.assertIsNone(spec)
+
+Frozen_FindSpecTests, Source_FindSpecTests = util.test_both(FindSpecTests,
+ machinery=machinery)
+
+
class FinderTests(abc.FinderTests):
"""Test finding frozen modules."""
def find(self, name, path=None):
- finder = machinery.FrozenImporter
+ finder = self.machinery.FrozenImporter
return finder.find_module(name, path)
def test_module(self):
@@ -35,11 +72,9 @@ class FinderTests(abc.FinderTests):
loader = self.find('<not real>')
self.assertIsNone(loader)
-
-def test_main():
- from test.support import run_unittest
- run_unittest(FinderTests)
+Frozen_FinderTests, Source_FinderTests = util.test_both(FinderTests,
+ machinery=machinery)
if __name__ == '__main__':
- test_main()
+ unittest.main()
diff --git a/Lib/test/test_importlib/frozen/test_loader.py b/Lib/test/test_importlib/frozen/test_loader.py
index f3a8bf67c7..7c0146456d 100644
--- a/Lib/test/test_importlib/frozen/test_loader.py
+++ b/Lib/test/test_importlib/frozen/test_loader.py
@@ -1,18 +1,104 @@
-from importlib import machinery
-import imp
-import unittest
from .. import abc
from .. import util
+
+machinery = util.import_importlib('importlib.machinery')
+
+
+import sys
from test.support import captured_stdout
+import types
+import unittest
+import warnings
+
+
+class ExecModuleTests(abc.LoaderTests):
+
+ def exec_module(self, name):
+ with util.uncache(name), captured_stdout() as stdout:
+ spec = self.machinery.ModuleSpec(
+ name, self.machinery.FrozenImporter, origin='frozen',
+ is_package=self.machinery.FrozenImporter.is_package(name))
+ module = types.ModuleType(name)
+ module.__spec__ = spec
+ assert not hasattr(module, 'initialized')
+ self.machinery.FrozenImporter.exec_module(module)
+ self.assertTrue(module.initialized)
+ self.assertTrue(hasattr(module, '__spec__'))
+ self.assertEqual(module.__spec__.origin, 'frozen')
+ return module, stdout.getvalue()
+
+ def test_module(self):
+ name = '__hello__'
+ module, output = self.exec_module(name)
+ check = {'__name__': name}
+ for attr, value in check.items():
+ self.assertEqual(getattr(module, attr), value)
+ self.assertEqual(output, 'Hello world!\n')
+ self.assertTrue(hasattr(module, '__spec__'))
+
+ def test_package(self):
+ name = '__phello__'
+ module, output = self.exec_module(name)
+ check = {'__name__': name}
+ for attr, value in check.items():
+ attr_value = getattr(module, attr)
+ self.assertEqual(attr_value, value,
+ 'for {name}.{attr}, {given!r} != {expected!r}'.format(
+ name=name, attr=attr, given=attr_value,
+ expected=value))
+ self.assertEqual(output, 'Hello world!\n')
+
+ def test_lacking_parent(self):
+ name = '__phello__.spam'
+ with util.uncache('__phello__'):
+ module, output = self.exec_module(name)
+ check = {'__name__': name}
+ for attr, value in check.items():
+ attr_value = getattr(module, attr)
+ self.assertEqual(attr_value, value,
+ 'for {name}.{attr}, {given} != {expected!r}'.format(
+ name=name, attr=attr, given=attr_value,
+ expected=value))
+ self.assertEqual(output, 'Hello world!\n')
+
+ def test_module_repr(self):
+ name = '__hello__'
+ module, output = self.exec_module(name)
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ repr_str = self.machinery.FrozenImporter.module_repr(module)
+ self.assertEqual(repr_str,
+ "<module '__hello__' (frozen)>")
+
+ def test_module_repr_indirect(self):
+ name = '__hello__'
+ module, output = self.exec_module(name)
+ self.assertEqual(repr(module),
+ "<module '__hello__' (frozen)>")
+
+ # No way to trigger an error in a frozen module.
+ test_state_after_failure = None
+
+ def test_unloadable(self):
+ assert self.machinery.FrozenImporter.find_module('_not_real') is None
+ with self.assertRaises(ImportError) as cm:
+ self.exec_module('_not_real')
+ self.assertEqual(cm.exception.name, '_not_real')
+
+Frozen_ExecModuleTests, Source_ExecModuleTests = util.test_both(ExecModuleTests,
+ machinery=machinery)
+
class LoaderTests(abc.LoaderTests):
def test_module(self):
with util.uncache('__hello__'), captured_stdout() as stdout:
- module = machinery.FrozenImporter.load_module('__hello__')
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ module = self.machinery.FrozenImporter.load_module('__hello__')
check = {'__name__': '__hello__',
'__package__': '',
- '__loader__': machinery.FrozenImporter,
+ '__loader__': self.machinery.FrozenImporter,
}
for attr, value in check.items():
self.assertEqual(getattr(module, attr), value)
@@ -21,11 +107,13 @@ class LoaderTests(abc.LoaderTests):
def test_package(self):
with util.uncache('__phello__'), captured_stdout() as stdout:
- module = machinery.FrozenImporter.load_module('__phello__')
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ module = self.machinery.FrozenImporter.load_module('__phello__')
check = {'__name__': '__phello__',
'__package__': '__phello__',
- '__path__': ['__phello__'],
- '__loader__': machinery.FrozenImporter,
+ '__path__': [],
+ '__loader__': self.machinery.FrozenImporter,
}
for attr, value in check.items():
attr_value = getattr(module, attr)
@@ -38,10 +126,12 @@ class LoaderTests(abc.LoaderTests):
def test_lacking_parent(self):
with util.uncache('__phello__', '__phello__.spam'), \
captured_stdout() as stdout:
- module = machinery.FrozenImporter.load_module('__phello__.spam')
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ module = self.machinery.FrozenImporter.load_module('__phello__.spam')
check = {'__name__': '__phello__.spam',
'__package__': '__phello__',
- '__loader__': machinery.FrozenImporter,
+ '__loader__': self.machinery.FrozenImporter,
}
for attr, value in check.items():
attr_value = getattr(module, attr)
@@ -53,29 +143,43 @@ class LoaderTests(abc.LoaderTests):
def test_module_reuse(self):
with util.uncache('__hello__'), captured_stdout() as stdout:
- module1 = machinery.FrozenImporter.load_module('__hello__')
- module2 = machinery.FrozenImporter.load_module('__hello__')
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ module1 = self.machinery.FrozenImporter.load_module('__hello__')
+ module2 = self.machinery.FrozenImporter.load_module('__hello__')
self.assertIs(module1, module2)
self.assertEqual(stdout.getvalue(),
'Hello world!\nHello world!\n')
def test_module_repr(self):
with util.uncache('__hello__'), captured_stdout():
- module = machinery.FrozenImporter.load_module('__hello__')
- self.assertEqual(repr(module),
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ module = self.machinery.FrozenImporter.load_module('__hello__')
+ repr_str = self.machinery.FrozenImporter.module_repr(module)
+ self.assertEqual(repr_str,
"<module '__hello__' (frozen)>")
+ def test_module_repr_indirect(self):
+ with util.uncache('__hello__'), captured_stdout():
+ module = self.machinery.FrozenImporter.load_module('__hello__')
+ self.assertEqual(repr(module),
+ "<module '__hello__' (frozen)>")
+
# No way to trigger an error in a frozen module.
test_state_after_failure = None
def test_unloadable(self):
- assert machinery.FrozenImporter.find_module('_not_real') is None
+ assert self.machinery.FrozenImporter.find_module('_not_real') is None
with self.assertRaises(ImportError) as cm:
- machinery.FrozenImporter.load_module('_not_real')
+ self.machinery.FrozenImporter.load_module('_not_real')
self.assertEqual(cm.exception.name, '_not_real')
+Frozen_LoaderTests, Source_LoaderTests = util.test_both(LoaderTests,
+ machinery=machinery)
-class InspectLoaderTests(unittest.TestCase):
+
+class InspectLoaderTests:
"""Tests for the InspectLoader methods for FrozenImporter."""
@@ -83,15 +187,15 @@ class InspectLoaderTests(unittest.TestCase):
# Make sure that the code object is good.
name = '__hello__'
with captured_stdout() as stdout:
- code = machinery.FrozenImporter.get_code(name)
- mod = imp.new_module(name)
+ code = self.machinery.FrozenImporter.get_code(name)
+ mod = types.ModuleType(name)
exec(code, mod.__dict__)
self.assertTrue(hasattr(mod, 'initialized'))
self.assertEqual(stdout.getvalue(), 'Hello world!\n')
def test_get_source(self):
# Should always return None.
- result = machinery.FrozenImporter.get_source('__hello__')
+ result = self.machinery.FrozenImporter.get_source('__hello__')
self.assertIsNone(result)
def test_is_package(self):
@@ -99,22 +203,20 @@ class InspectLoaderTests(unittest.TestCase):
test_for = (('__hello__', False), ('__phello__', True),
('__phello__.spam', False))
for name, is_package in test_for:
- result = machinery.FrozenImporter.is_package(name)
+ result = self.machinery.FrozenImporter.is_package(name)
self.assertEqual(bool(result), is_package)
def test_failure(self):
# Raise ImportError for modules that are not frozen.
for meth_name in ('get_code', 'get_source', 'is_package'):
- method = getattr(machinery.FrozenImporter, meth_name)
+ method = getattr(self.machinery.FrozenImporter, meth_name)
with self.assertRaises(ImportError) as cm:
method('importlib')
self.assertEqual(cm.exception.name, 'importlib')
-
-def test_main():
- from test.support import run_unittest
- run_unittest(LoaderTests, InspectLoaderTests)
+Frozen_ILTests, Source_ILTests = util.test_both(InspectLoaderTests,
+ machinery=machinery)
if __name__ == '__main__':
- test_main()
+ unittest.main()
diff --git a/Lib/test/test_importlib/import_/__init__.py b/Lib/test/test_importlib/import_/__init__.py
index 366e531333..4b16ecc311 100644
--- a/Lib/test/test_importlib/import_/__init__.py
+++ b/Lib/test/test_importlib/import_/__init__.py
@@ -1,13 +1,5 @@
-from .. import test_suite
-import os.path
-import unittest
+import os
+from test.support import load_package_tests
-
-def test_suite():
- directory = os.path.dirname(__file__)
- return test_suite('importlib.test.import_', directory)
-
-
-if __name__ == '__main__':
- from test.support import run_unittest
- run_unittest(test_suite())
+def load_tests(*args):
+ return load_package_tests(os.path.dirname(__file__), *args)
diff --git a/Lib/test/test_importlib/import_/__main__.py b/Lib/test/test_importlib/import_/__main__.py
new file mode 100644
index 0000000000..40a23a297e
--- /dev/null
+++ b/Lib/test/test_importlib/import_/__main__.py
@@ -0,0 +1,4 @@
+from . import load_tests
+import unittest
+
+unittest.main()
diff --git a/Lib/test/test_importlib/import_/test___loader__.py b/Lib/test/test_importlib/import_/test___loader__.py
new file mode 100644
index 0000000000..6df80101fa
--- /dev/null
+++ b/Lib/test/test_importlib/import_/test___loader__.py
@@ -0,0 +1,70 @@
+from importlib import machinery
+import sys
+import types
+import unittest
+
+from .. import util
+from . import util as import_util
+
+
+class SpecLoaderMock:
+
+ def find_spec(self, fullname, path=None, target=None):
+ return machinery.ModuleSpec(fullname, self)
+
+ def exec_module(self, module):
+ pass
+
+
+class SpecLoaderAttributeTests:
+
+ def test___loader__(self):
+ loader = SpecLoaderMock()
+ with util.uncache('blah'), util.import_state(meta_path=[loader]):
+ module = self.__import__('blah')
+ self.assertEqual(loader, module.__loader__)
+
+Frozen_SpecTests, Source_SpecTests = util.test_both(
+ SpecLoaderAttributeTests, __import__=import_util.__import__)
+
+
+class LoaderMock:
+
+ def find_module(self, fullname, path=None):
+ return self
+
+ def load_module(self, fullname):
+ sys.modules[fullname] = self.module
+ return self.module
+
+
+class LoaderAttributeTests:
+
+ def test___loader___missing(self):
+ module = types.ModuleType('blah')
+ try:
+ del module.__loader__
+ except AttributeError:
+ pass
+ loader = LoaderMock()
+ loader.module = module
+ with util.uncache('blah'), util.import_state(meta_path=[loader]):
+ module = self.__import__('blah')
+ self.assertEqual(loader, module.__loader__)
+
+ def test___loader___is_None(self):
+ module = types.ModuleType('blah')
+ module.__loader__ = None
+ loader = LoaderMock()
+ loader.module = module
+ with util.uncache('blah'), util.import_state(meta_path=[loader]):
+ returned_module = self.__import__('blah')
+ self.assertEqual(loader, module.__loader__)
+
+
+Frozen_Tests, Source_Tests = util.test_both(LoaderAttributeTests,
+ __import__=import_util.__import__)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/Lib/test/test_importlib/import_/test___package__.py b/Lib/test/test_importlib/import_/test___package__.py
index 783cde1729..2e19725680 100644
--- a/Lib/test/test_importlib/import_/test___package__.py
+++ b/Lib/test/test_importlib/import_/test___package__.py
@@ -9,7 +9,7 @@ from .. import util
from . import util as import_util
-class Using__package__(unittest.TestCase):
+class Using__package__:
"""Use of __package__ supercedes the use of __name__/__path__ to calculate
what package a module belongs to. The basic algorithm is [__package__]::
@@ -36,10 +36,10 @@ class Using__package__(unittest.TestCase):
def test_using___package__(self):
# [__package__]
- with util.mock_modules('pkg.__init__', 'pkg.fake') as importer:
+ with self.mock_modules('pkg.__init__', 'pkg.fake') as importer:
with util.import_state(meta_path=[importer]):
- import_util.import_('pkg.fake')
- module = import_util.import_('',
+ self.__import__('pkg.fake')
+ module = self.__import__('',
globals={'__package__': 'pkg.fake'},
fromlist=['attr'], level=2)
self.assertEqual(module.__name__, 'pkg')
@@ -49,10 +49,10 @@ class Using__package__(unittest.TestCase):
globals_ = {'__name__': 'pkg.fake', '__path__': []}
if package_as_None:
globals_['__package__'] = None
- with util.mock_modules('pkg.__init__', 'pkg.fake') as importer:
+ with self.mock_modules('pkg.__init__', 'pkg.fake') as importer:
with util.import_state(meta_path=[importer]):
- import_util.import_('pkg.fake')
- module = import_util.import_('', globals= globals_,
+ self.__import__('pkg.fake')
+ module = self.__import__('', globals= globals_,
fromlist=['attr'], level=2)
self.assertEqual(module.__name__, 'pkg')
@@ -63,16 +63,27 @@ class Using__package__(unittest.TestCase):
def test_bad__package__(self):
globals = {'__package__': '<not real>'}
with self.assertRaises(SystemError):
- import_util.import_('', globals, {}, ['relimport'], 1)
+ self.__import__('', globals, {}, ['relimport'], 1)
def test_bunk__package__(self):
globals = {'__package__': 42}
with self.assertRaises(TypeError):
- import_util.import_('', globals, {}, ['relimport'], 1)
+ self.__import__('', globals, {}, ['relimport'], 1)
+class Using__package__PEP302(Using__package__):
+ mock_modules = util.mock_modules
-@import_util.importlib_only
-class Setting__package__(unittest.TestCase):
+Frozen_UsingPackagePEP302, Source_UsingPackagePEP302 = util.test_both(
+ Using__package__PEP302, __import__=import_util.__import__)
+
+class Using__package__PEP302(Using__package__):
+ mock_modules = util.mock_spec
+
+Frozen_UsingPackagePEP451, Source_UsingPackagePEP451 = util.test_both(
+ Using__package__PEP302, __import__=import_util.__import__)
+
+
+class Setting__package__:
"""Because __package__ is a new feature, it is not always set by a loader.
Import will set it as needed to help with the transition to relying on
@@ -84,36 +95,39 @@ class Setting__package__(unittest.TestCase):
"""
+ __import__ = import_util.__import__[1]
+
# [top-level]
def test_top_level(self):
- with util.mock_modules('top_level') as mock:
+ with self.mock_modules('top_level') as mock:
with util.import_state(meta_path=[mock]):
del mock['top_level'].__package__
- module = import_util.import_('top_level')
+ module = self.__import__('top_level')
self.assertEqual(module.__package__, '')
# [package]
def test_package(self):
- with util.mock_modules('pkg.__init__') as mock:
+ with self.mock_modules('pkg.__init__') as mock:
with util.import_state(meta_path=[mock]):
del mock['pkg'].__package__
- module = import_util.import_('pkg')
+ module = self.__import__('pkg')
self.assertEqual(module.__package__, 'pkg')
# [submodule]
def test_submodule(self):
- with util.mock_modules('pkg.__init__', 'pkg.mod') as mock:
+ with self.mock_modules('pkg.__init__', 'pkg.mod') as mock:
with util.import_state(meta_path=[mock]):
del mock['pkg.mod'].__package__
- pkg = import_util.import_('pkg.mod')
+ pkg = self.__import__('pkg.mod')
module = getattr(pkg, 'mod')
self.assertEqual(module.__package__, 'pkg')
+class Setting__package__PEP302(Setting__package__, unittest.TestCase):
+ mock_modules = util.mock_modules
-def test_main():
- from test.support import run_unittest
- run_unittest(Using__package__, Setting__package__)
+class Setting__package__PEP451(Setting__package__, unittest.TestCase):
+ mock_modules = util.mock_spec
if __name__ == '__main__':
- test_main()
+ unittest.main()
diff --git a/Lib/test/test_importlib/import_/test_api.py b/Lib/test/test_importlib/import_/test_api.py
index 3d4cd94889..439c105e9b 100644
--- a/Lib/test/test_importlib/import_/test_api.py
+++ b/Lib/test/test_importlib/import_/test_api.py
@@ -1,23 +1,41 @@
-from .. import util as importlib_test_util
-from . import util
-import imp
+from .. import util
+from . import util as import_util
+
+from importlib import machinery
import sys
+import types
import unittest
+PKG_NAME = 'fine'
+SUBMOD_NAME = 'fine.bogus'
+
+
+class BadSpecFinderLoader:
+ @classmethod
+ def find_spec(cls, fullname, path=None, target=None):
+ if fullname == SUBMOD_NAME:
+ spec = machinery.ModuleSpec(fullname, cls)
+ return spec
+
+ @staticmethod
+ def exec_module(module):
+ if module.__name__ == SUBMOD_NAME:
+ raise ImportError('I cannot be loaded!')
+
class BadLoaderFinder:
- bad = 'fine.bogus'
@classmethod
def find_module(cls, fullname, path):
- if fullname == cls.bad:
+ if fullname == SUBMOD_NAME:
return cls
+
@classmethod
def load_module(cls, fullname):
- if fullname == cls.bad:
+ if fullname == SUBMOD_NAME:
raise ImportError('I cannot be loaded!')
-class APITest(unittest.TestCase):
+class APITest:
"""Test API-specific details for __import__ (e.g. raising the right
exception when passing in an int for the module name)."""
@@ -25,43 +43,52 @@ class APITest(unittest.TestCase):
def test_name_requires_rparition(self):
# Raise TypeError if a non-string is passed in for the module name.
with self.assertRaises(TypeError):
- util.import_(42)
+ self.__import__(42)
def test_negative_level(self):
# Raise ValueError when a negative level is specified.
# PEP 328 did away with sys.module None entries and the ambiguity of
# absolute/relative imports.
with self.assertRaises(ValueError):
- util.import_('os', globals(), level=-1)
+ self.__import__('os', globals(), level=-1)
def test_nonexistent_fromlist_entry(self):
# If something in fromlist doesn't exist, that's okay.
# issue15715
- mod = imp.new_module('fine')
+ mod = types.ModuleType(PKG_NAME)
mod.__path__ = ['XXX']
- with importlib_test_util.import_state(meta_path=[BadLoaderFinder]):
- with importlib_test_util.uncache('fine'):
- sys.modules['fine'] = mod
- util.import_('fine', fromlist=['not here'])
+ with util.import_state(meta_path=[self.bad_finder_loader]):
+ with util.uncache(PKG_NAME):
+ sys.modules[PKG_NAME] = mod
+ self.__import__(PKG_NAME, fromlist=['not here'])
def test_fromlist_load_error_propagates(self):
# If something in fromlist triggers an exception not related to not
# existing, let that exception propagate.
# issue15316
- mod = imp.new_module('fine')
+ mod = types.ModuleType(PKG_NAME)
mod.__path__ = ['XXX']
- with importlib_test_util.import_state(meta_path=[BadLoaderFinder]):
- with importlib_test_util.uncache('fine'):
- sys.modules['fine'] = mod
+ with util.import_state(meta_path=[self.bad_finder_loader]):
+ with util.uncache(PKG_NAME):
+ sys.modules[PKG_NAME] = mod
with self.assertRaises(ImportError):
- util.import_('fine', fromlist=['bogus'])
+ self.__import__(PKG_NAME,
+ fromlist=[SUBMOD_NAME.rpartition('.')[-1]])
+
+
+class OldAPITests(APITest):
+ bad_finder_loader = BadLoaderFinder
+
+Frozen_OldAPITests, Source_OldAPITests = util.test_both(
+ OldAPITests, __import__=import_util.__import__)
+class SpecAPITests(APITest):
+ bad_finder_loader = BadSpecFinderLoader
-def test_main():
- from test.support import run_unittest
- run_unittest(APITest)
+Frozen_SpecAPITests, Source_SpecAPITests = util.test_both(
+ SpecAPITests, __import__=import_util.__import__)
if __name__ == '__main__':
- test_main()
+ unittest.main()
diff --git a/Lib/test/test_importlib/import_/test_caching.py b/Lib/test/test_importlib/import_/test_caching.py
index 207378a6fb..c292ee4ac2 100644
--- a/Lib/test/test_importlib/import_/test_caching.py
+++ b/Lib/test/test_importlib/import_/test_caching.py
@@ -6,7 +6,7 @@ from types import MethodType
import unittest
-class UseCache(unittest.TestCase):
+class UseCache:
"""When it comes to sys.modules, import prefers it over anything else.
@@ -21,12 +21,13 @@ class UseCache(unittest.TestCase):
ImportError is raised [None in cache].
"""
+
def test_using_cache(self):
# [use cache]
module_to_use = "some module found!"
with util.uncache('some_module'):
sys.modules['some_module'] = module_to_use
- module = import_util.import_('some_module')
+ module = self.__import__('some_module')
self.assertEqual(id(module_to_use), id(module))
def test_None_in_cache(self):
@@ -35,9 +36,19 @@ class UseCache(unittest.TestCase):
with util.uncache(name):
sys.modules[name] = None
with self.assertRaises(ImportError) as cm:
- import_util.import_(name)
+ self.__import__(name)
self.assertEqual(cm.exception.name, name)
+Frozen_UseCache, Source_UseCache = util.test_both(
+ UseCache, __import__=import_util.__import__)
+
+
+class ImportlibUseCache(UseCache, unittest.TestCase):
+
+ # Pertinent only to PEP 302; exec_module() doesn't return a module.
+
+ __import__ = import_util.__import__[1]
+
def create_mock(self, *names, return_=None):
mock = util.mock_modules(*names)
original_load = mock.load_module
@@ -49,40 +60,33 @@ class UseCache(unittest.TestCase):
# __import__ inconsistent between loaders and built-in import when it comes
# to when to use the module in sys.modules and when not to.
- @import_util.importlib_only
def test_using_cache_after_loader(self):
# [from cache on return]
with self.create_mock('module') as mock:
with util.import_state(meta_path=[mock]):
- module = import_util.import_('module')
+ module = self.__import__('module')
self.assertEqual(id(module), id(sys.modules['module']))
# See test_using_cache_after_loader() for reasoning.
- @import_util.importlib_only
def test_using_cache_for_assigning_to_attribute(self):
# [from cache to attribute]
with self.create_mock('pkg.__init__', 'pkg.module') as importer:
with util.import_state(meta_path=[importer]):
- module = import_util.import_('pkg.module')
+ module = self.__import__('pkg.module')
self.assertTrue(hasattr(module, 'module'))
self.assertEqual(id(module.module),
id(sys.modules['pkg.module']))
# See test_using_cache_after_loader() for reasoning.
- @import_util.importlib_only
def test_using_cache_for_fromlist(self):
# [from cache for fromlist]
with self.create_mock('pkg.__init__', 'pkg.module') as importer:
with util.import_state(meta_path=[importer]):
- module = import_util.import_('pkg', fromlist=['module'])
+ module = self.__import__('pkg', fromlist=['module'])
self.assertTrue(hasattr(module, 'module'))
self.assertEqual(id(module.module),
id(sys.modules['pkg.module']))
-def test_main():
- from test.support import run_unittest
- run_unittest(UseCache)
-
if __name__ == '__main__':
- test_main()
+ unittest.main()
diff --git a/Lib/test/test_importlib/import_/test_fromlist.py b/Lib/test/test_importlib/import_/test_fromlist.py
index c16c33710f..a755b75a73 100644
--- a/Lib/test/test_importlib/import_/test_fromlist.py
+++ b/Lib/test/test_importlib/import_/test_fromlist.py
@@ -1,10 +1,10 @@
"""Test that the semantics relating to the 'fromlist' argument are correct."""
from .. import util
from . import util as import_util
-import imp
import unittest
-class ReturnValue(unittest.TestCase):
+
+class ReturnValue:
"""The use of fromlist influences what import returns.
@@ -17,20 +17,23 @@ class ReturnValue(unittest.TestCase):
def test_return_from_import(self):
# [import return]
- with util.mock_modules('pkg.__init__', 'pkg.module') as importer:
+ with util.mock_spec('pkg.__init__', 'pkg.module') as importer:
with util.import_state(meta_path=[importer]):
- module = import_util.import_('pkg.module')
+ module = self.__import__('pkg.module')
self.assertEqual(module.__name__, 'pkg')
def test_return_from_from_import(self):
# [from return]
with util.mock_modules('pkg.__init__', 'pkg.module')as importer:
with util.import_state(meta_path=[importer]):
- module = import_util.import_('pkg.module', fromlist=['attr'])
+ module = self.__import__('pkg.module', fromlist=['attr'])
self.assertEqual(module.__name__, 'pkg.module')
+Frozen_ReturnValue, Source_ReturnValue = util.test_both(
+ ReturnValue, __import__=import_util.__import__)
+
-class HandlingFromlist(unittest.TestCase):
+class HandlingFromlist:
"""Using fromlist triggers different actions based on what is being asked
of it.
@@ -49,22 +52,22 @@ class HandlingFromlist(unittest.TestCase):
# [object case]
with util.mock_modules('module') as importer:
with util.import_state(meta_path=[importer]):
- module = import_util.import_('module', fromlist=['attr'])
+ module = self.__import__('module', fromlist=['attr'])
self.assertEqual(module.__name__, 'module')
def test_nonexistent_object(self):
# [bad object]
with util.mock_modules('module') as importer:
with util.import_state(meta_path=[importer]):
- module = import_util.import_('module', fromlist=['non_existent'])
+ module = self.__import__('module', fromlist=['non_existent'])
self.assertEqual(module.__name__, 'module')
- self.assertTrue(not hasattr(module, 'non_existent'))
+ self.assertFalse(hasattr(module, 'non_existent'))
def test_module_from_package(self):
# [module]
with util.mock_modules('pkg.__init__', 'pkg.module') as importer:
with util.import_state(meta_path=[importer]):
- module = import_util.import_('pkg', fromlist=['module'])
+ module = self.__import__('pkg', fromlist=['module'])
self.assertEqual(module.__name__, 'pkg')
self.assertTrue(hasattr(module, 'module'))
self.assertEqual(module.module.__name__, 'pkg.module')
@@ -79,13 +82,13 @@ class HandlingFromlist(unittest.TestCase):
module_code={'pkg.mod': module_code}) as importer:
with util.import_state(meta_path=[importer]):
with self.assertRaises(ImportError) as exc:
- import_util.import_('pkg', fromlist=['mod'])
+ self.__import__('pkg', fromlist=['mod'])
self.assertEqual('i_do_not_exist', exc.exception.name)
def test_empty_string(self):
with util.mock_modules('pkg.__init__', 'pkg.mod') as importer:
with util.import_state(meta_path=[importer]):
- module = import_util.import_('pkg.mod', fromlist=[''])
+ module = self.__import__('pkg.mod', fromlist=[''])
self.assertEqual(module.__name__, 'pkg.mod')
def basic_star_test(self, fromlist=['*']):
@@ -93,7 +96,7 @@ class HandlingFromlist(unittest.TestCase):
with util.mock_modules('pkg.__init__', 'pkg.module') as mock:
with util.import_state(meta_path=[mock]):
mock['pkg'].__all__ = ['module']
- module = import_util.import_('pkg', fromlist=fromlist)
+ module = self.__import__('pkg', fromlist=fromlist)
self.assertEqual(module.__name__, 'pkg')
self.assertTrue(hasattr(module, 'module'))
self.assertEqual(module.module.__name__, 'pkg.module')
@@ -111,17 +114,16 @@ class HandlingFromlist(unittest.TestCase):
with context as mock:
with util.import_state(meta_path=[mock]):
mock['pkg'].__all__ = ['module1']
- module = import_util.import_('pkg', fromlist=['module2', '*'])
+ module = self.__import__('pkg', fromlist=['module2', '*'])
self.assertEqual(module.__name__, 'pkg')
self.assertTrue(hasattr(module, 'module1'))
self.assertTrue(hasattr(module, 'module2'))
self.assertEqual(module.module1.__name__, 'pkg.module1')
self.assertEqual(module.module2.__name__, 'pkg.module2')
+Frozen_FromList, Source_FromList = util.test_both(
+ HandlingFromlist, __import__=import_util.__import__)
-def test_main():
- from test.support import run_unittest
- run_unittest(ReturnValue, HandlingFromlist)
if __name__ == '__main__':
- test_main()
+ unittest.main()
diff --git a/Lib/test/test_importlib/import_/test_meta_path.py b/Lib/test/test_importlib/import_/test_meta_path.py
index 4d85f80e67..5eeb1458d3 100644
--- a/Lib/test/test_importlib/import_/test_meta_path.py
+++ b/Lib/test/test_importlib/import_/test_meta_path.py
@@ -7,7 +7,7 @@ import unittest
import warnings
-class CallingOrder(unittest.TestCase):
+class CallingOrder:
"""Calls to the importers on sys.meta_path happen in order that they are
specified in the sequence, starting with the first importer
@@ -18,23 +18,18 @@ class CallingOrder(unittest.TestCase):
def test_first_called(self):
# [first called]
mod = 'top_level'
- first = util.mock_modules(mod)
- second = util.mock_modules(mod)
- with util.mock_modules(mod) as first, util.mock_modules(mod) as second:
- first.modules[mod] = 42
- second.modules[mod] = -13
+ with util.mock_spec(mod) as first, util.mock_spec(mod) as second:
with util.import_state(meta_path=[first, second]):
- self.assertEqual(import_util.import_(mod), 42)
+ self.assertIs(self.__import__(mod), first.modules[mod])
def test_continuing(self):
# [continuing]
mod_name = 'for_real'
- with util.mock_modules('nonexistent') as first, \
- util.mock_modules(mod_name) as second:
- first.find_module = lambda self, fullname, path=None: None
- second.modules[mod_name] = 42
+ with util.mock_spec('nonexistent') as first, \
+ util.mock_spec(mod_name) as second:
+ first.find_spec = lambda self, fullname, path=None, parent=None: None
with util.import_state(meta_path=[first, second]):
- self.assertEqual(import_util.import_(mod_name), 42)
+ self.assertIs(self.__import__(mod_name), second.modules[mod_name])
def test_empty(self):
# Raise an ImportWarning if sys.meta_path is empty.
@@ -46,41 +41,42 @@ class CallingOrder(unittest.TestCase):
with util.import_state(meta_path=[]):
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
- self.assertIsNone(importlib._bootstrap._find_module('nothing',
- None))
+ self.assertIsNone(importlib._bootstrap._find_spec('nothing',
+ None))
self.assertEqual(len(w), 1)
self.assertTrue(issubclass(w[-1].category, ImportWarning))
+Frozen_CallingOrder, Source_CallingOrder = util.test_both(
+ CallingOrder, __import__=import_util.__import__)
-class CallSignature(unittest.TestCase):
+
+class CallSignature:
"""If there is no __path__ entry on the parent module, then 'path' is None
[no path]. Otherwise, the value for __path__ is passed in for the 'path'
argument [path set]."""
- def log(self, fxn):
+ def log_finder(self, importer):
+ fxn = getattr(importer, self.finder_name)
log = []
def wrapper(self, *args, **kwargs):
log.append([args, kwargs])
return fxn(*args, **kwargs)
return log, wrapper
-
def test_no_path(self):
# [no path]
mod_name = 'top_level'
assert '.' not in mod_name
- with util.mock_modules(mod_name) as importer:
- log, wrapped_call = self.log(importer.find_module)
- importer.find_module = MethodType(wrapped_call, importer)
+ with self.mock_modules(mod_name) as importer:
+ log, wrapped_call = self.log_finder(importer)
+ setattr(importer, self.finder_name, MethodType(wrapped_call, importer))
with util.import_state(meta_path=[importer]):
- import_util.import_(mod_name)
+ self.__import__(mod_name)
assert len(log) == 1
args = log[0][0]
kwargs = log[0][1]
# Assuming all arguments are positional.
- self.assertEqual(len(args), 2)
- self.assertEqual(len(kwargs), 0)
self.assertEqual(args[0], mod_name)
self.assertIsNone(args[1])
@@ -90,26 +86,34 @@ class CallSignature(unittest.TestCase):
mod_name = pkg_name + '.module'
path = [42]
assert '.' in mod_name
- with util.mock_modules(pkg_name+'.__init__', mod_name) as importer:
+ with self.mock_modules(pkg_name+'.__init__', mod_name) as importer:
importer.modules[pkg_name].__path__ = path
- log, wrapped_call = self.log(importer.find_module)
- importer.find_module = MethodType(wrapped_call, importer)
+ log, wrapped_call = self.log_finder(importer)
+ setattr(importer, self.finder_name, MethodType(wrapped_call, importer))
with util.import_state(meta_path=[importer]):
- import_util.import_(mod_name)
+ self.__import__(mod_name)
assert len(log) == 2
args = log[1][0]
kwargs = log[1][1]
# Assuming all arguments are positional.
- self.assertTrue(not kwargs)
+ self.assertFalse(kwargs)
self.assertEqual(args[0], mod_name)
self.assertIs(args[1], path)
+class CallSignaturePEP302(CallSignature):
+ mock_modules = util.mock_modules
+ finder_name = 'find_module'
+
+Frozen_CallSignaturePEP302, Source_CallSignaturePEP302 = util.test_both(
+ CallSignaturePEP302, __import__=import_util.__import__)
+class CallSignaturePEP451(CallSignature):
+ mock_modules = util.mock_spec
+ finder_name = 'find_spec'
-def test_main():
- from test.support import run_unittest
- run_unittest(CallingOrder, CallSignature)
+Frozen_CallSignaturePEP451, Source_CallSignaturePEP451 = util.test_both(
+ CallSignaturePEP451, __import__=import_util.__import__)
if __name__ == '__main__':
- test_main()
+ unittest.main()
diff --git a/Lib/test/test_importlib/import_/test_packages.py b/Lib/test/test_importlib/import_/test_packages.py
index bfa18dc217..55a5d14985 100644
--- a/Lib/test/test_importlib/import_/test_packages.py
+++ b/Lib/test/test_importlib/import_/test_packages.py
@@ -6,37 +6,37 @@ import importlib
from test import support
-class ParentModuleTests(unittest.TestCase):
+class ParentModuleTests:
"""Importing a submodule should import the parent modules."""
def test_import_parent(self):
- with util.mock_modules('pkg.__init__', 'pkg.module') as mock:
+ with util.mock_spec('pkg.__init__', 'pkg.module') as mock:
with util.import_state(meta_path=[mock]):
- module = import_util.import_('pkg.module')
+ module = self.__import__('pkg.module')
self.assertIn('pkg', sys.modules)
def test_bad_parent(self):
- with util.mock_modules('pkg.module') as mock:
+ with util.mock_spec('pkg.module') as mock:
with util.import_state(meta_path=[mock]):
with self.assertRaises(ImportError) as cm:
- import_util.import_('pkg.module')
+ self.__import__('pkg.module')
self.assertEqual(cm.exception.name, 'pkg')
def test_raising_parent_after_importing_child(self):
def __init__():
import pkg.module
1/0
- mock = util.mock_modules('pkg.__init__', 'pkg.module',
+ mock = util.mock_spec('pkg.__init__', 'pkg.module',
module_code={'pkg': __init__})
with mock:
with util.import_state(meta_path=[mock]):
with self.assertRaises(ZeroDivisionError):
- import_util.import_('pkg')
+ self.__import__('pkg')
self.assertNotIn('pkg', sys.modules)
self.assertIn('pkg.module', sys.modules)
with self.assertRaises(ZeroDivisionError):
- import_util.import_('pkg.module')
+ self.__import__('pkg.module')
self.assertNotIn('pkg', sys.modules)
self.assertIn('pkg.module', sys.modules)
@@ -44,17 +44,17 @@ class ParentModuleTests(unittest.TestCase):
def __init__():
from . import module
1/0
- mock = util.mock_modules('pkg.__init__', 'pkg.module',
+ mock = util.mock_spec('pkg.__init__', 'pkg.module',
module_code={'pkg': __init__})
with mock:
with util.import_state(meta_path=[mock]):
with self.assertRaises((ZeroDivisionError, ImportError)):
# This raises ImportError on the "from . import module"
# line, not sure why.
- import_util.import_('pkg')
+ self.__import__('pkg')
self.assertNotIn('pkg', sys.modules)
with self.assertRaises((ZeroDivisionError, ImportError)):
- import_util.import_('pkg.module')
+ self.__import__('pkg.module')
self.assertNotIn('pkg', sys.modules)
# XXX False
#self.assertIn('pkg.module', sys.modules)
@@ -63,7 +63,7 @@ class ParentModuleTests(unittest.TestCase):
def __init__():
from ..subpkg import module
1/0
- mock = util.mock_modules('pkg.__init__', 'pkg.subpkg.__init__',
+ mock = util.mock_spec('pkg.__init__', 'pkg.subpkg.__init__',
'pkg.subpkg.module',
module_code={'pkg.subpkg': __init__})
with mock:
@@ -71,10 +71,10 @@ class ParentModuleTests(unittest.TestCase):
with self.assertRaises((ZeroDivisionError, ImportError)):
# This raises ImportError on the "from ..subpkg import module"
# line, not sure why.
- import_util.import_('pkg.subpkg')
+ self.__import__('pkg.subpkg')
self.assertNotIn('pkg.subpkg', sys.modules)
with self.assertRaises((ZeroDivisionError, ImportError)):
- import_util.import_('pkg.subpkg.module')
+ self.__import__('pkg.subpkg.module')
self.assertNotIn('pkg.subpkg', sys.modules)
# XXX False
#self.assertIn('pkg.subpkg.module', sys.modules)
@@ -83,7 +83,7 @@ class ParentModuleTests(unittest.TestCase):
# Try to import a submodule from a non-package should raise ImportError.
assert not hasattr(sys, '__path__')
with self.assertRaises(ImportError) as cm:
- import_util.import_('sys.no_submodules_here')
+ self.__import__('sys.no_submodules_here')
self.assertEqual(cm.exception.name, 'sys.no_submodules_here')
def test_module_not_package_but_side_effects(self):
@@ -93,20 +93,18 @@ class ParentModuleTests(unittest.TestCase):
subname = name + '.b'
def module_injection():
sys.modules[subname] = 'total bunk'
- mock_modules = util.mock_modules('mod',
+ mock_spec = util.mock_spec('mod',
module_code={'mod': module_injection})
- with mock_modules as mock:
+ with mock_spec as mock:
with util.import_state(meta_path=[mock]):
try:
- submodule = import_util.import_(subname)
+ submodule = self.__import__(subname)
finally:
support.unload(subname)
-
-def test_main():
- from test.support import run_unittest
- run_unittest(ParentModuleTests)
+Frozen_ParentTests, Source_ParentTests = util.test_both(
+ ParentModuleTests, __import__=import_util.__import__)
if __name__ == '__main__':
- test_main()
+ unittest.main()
diff --git a/Lib/test/test_importlib/import_/test_path.py b/Lib/test/test_importlib/import_/test_path.py
index d82b7f6b0c..1274f8cb9e 100644
--- a/Lib/test/test_importlib/import_/test_path.py
+++ b/Lib/test/test_importlib/import_/test_path.py
@@ -1,8 +1,9 @@
-from importlib import _bootstrap
-from importlib import machinery
-from importlib import import_module
from .. import util
from . import util as import_util
+
+importlib = util.import_importlib('importlib')
+machinery = util.import_importlib('importlib.machinery')
+
import os
import sys
from types import ModuleType
@@ -11,25 +12,25 @@ import warnings
import zipimport
-class FinderTests(unittest.TestCase):
+class FinderTests:
"""Tests for PathFinder."""
def test_failure(self):
- # Test None returned upon not finding a suitable finder.
+ # Test None returned upon not finding a suitable loader.
module = '<test module>'
with util.import_state():
- self.assertIsNone(machinery.PathFinder.find_module(module))
+ self.assertIsNone(self.machinery.PathFinder.find_module(module))
def test_sys_path(self):
# Test that sys.path is used when 'path' is None.
# Implicitly tests that sys.path_importer_cache is used.
module = '<test module>'
path = '<test path>'
- importer = util.mock_modules(module)
+ importer = util.mock_spec(module)
with util.import_state(path_importer_cache={path: importer},
path=[path]):
- loader = machinery.PathFinder.find_module(module)
+ loader = self.machinery.PathFinder.find_module(module)
self.assertIs(loader, importer)
def test_path(self):
@@ -37,29 +38,29 @@ class FinderTests(unittest.TestCase):
# Implicitly tests that sys.path_importer_cache is used.
module = '<test module>'
path = '<test path>'
- importer = util.mock_modules(module)
+ importer = util.mock_spec(module)
with util.import_state(path_importer_cache={path: importer}):
- loader = machinery.PathFinder.find_module(module, [path])
+ loader = self.machinery.PathFinder.find_module(module, [path])
self.assertIs(loader, importer)
def test_empty_list(self):
# An empty list should not count as asking for sys.path.
module = 'module'
path = '<test path>'
- importer = util.mock_modules(module)
+ importer = util.mock_spec(module)
with util.import_state(path_importer_cache={path: importer},
path=[path]):
- self.assertIsNone(machinery.PathFinder.find_module('module', []))
+ self.assertIsNone(self.machinery.PathFinder.find_module('module', []))
def test_path_hooks(self):
# Test that sys.path_hooks is used.
# Test that sys.path_importer_cache is set.
module = '<test module>'
path = '<test path>'
- importer = util.mock_modules(module)
+ importer = util.mock_spec(module)
hook = import_util.mock_path_hook(path, importer=importer)
with util.import_state(path_hooks=[hook]):
- loader = machinery.PathFinder.find_module(module, [path])
+ loader = self.machinery.PathFinder.find_module(module, [path])
self.assertIs(loader, importer)
self.assertIn(path, sys.path_importer_cache)
self.assertIs(sys.path_importer_cache[path], importer)
@@ -72,7 +73,7 @@ class FinderTests(unittest.TestCase):
path=[path_entry]):
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
- self.assertIsNone(machinery.PathFinder.find_module('os'))
+ self.assertIsNone(self.machinery.PathFinder.find_module('os'))
self.assertIsNone(sys.path_importer_cache[path_entry])
self.assertEqual(len(w), 1)
self.assertTrue(issubclass(w[-1].category, ImportWarning))
@@ -81,12 +82,12 @@ class FinderTests(unittest.TestCase):
# The empty string should create a finder using the cwd.
path = ''
module = '<test module>'
- importer = util.mock_modules(module)
- hook = import_util.mock_path_hook(os.curdir, importer=importer)
+ 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 = machinery.PathFinder.find_module(module)
+ loader = self.machinery.PathFinder.find_module(module)
self.assertIs(loader, importer)
- self.assertIn(os.curdir, sys.path_importer_cache)
+ self.assertIn(os.getcwd(), sys.path_importer_cache)
def test_None_on_sys_path(self):
# Putting None in sys.path[0] caused an import regression from Python
@@ -96,8 +97,8 @@ class FinderTests(unittest.TestCase):
new_path_importer_cache = sys.path_importer_cache.copy()
new_path_importer_cache.pop(None, None)
new_path_hooks = [zipimport.zipimporter,
- _bootstrap.FileFinder.path_hook(
- *_bootstrap._get_supported_file_loaders())]
+ self.machinery.FileFinder.path_hook(
+ *self.importlib._bootstrap._get_supported_file_loaders())]
missing = object()
email = sys.modules.pop('email', missing)
try:
@@ -105,16 +106,39 @@ class FinderTests(unittest.TestCase):
path=new_path,
path_importer_cache=new_path_importer_cache,
path_hooks=new_path_hooks):
- module = import_module('email')
+ module = self.importlib.import_module('email')
self.assertIsInstance(module, ModuleType)
finally:
if email is not missing:
sys.modules['email'] = email
+Frozen_FinderTests, Source_FinderTests = util.test_both(
+ FinderTests, importlib=importlib, machinery=machinery)
+
+
+class PathEntryFinderTests:
+
+ def test_finder_with_failing_find_module(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')
+
+Frozen_PEFTests, Source_PEFTests = util.test_both(
+ PathEntryFinderTests, machinery=machinery)
-def test_main():
- from test.support import run_unittest
- run_unittest(FinderTests)
if __name__ == '__main__':
- test_main()
+ unittest.main()
diff --git a/Lib/test/test_importlib/import_/test_relative_imports.py b/Lib/test/test_importlib/import_/test_relative_imports.py
index 4569c26424..b216e9cc13 100644
--- a/Lib/test/test_importlib/import_/test_relative_imports.py
+++ b/Lib/test/test_importlib/import_/test_relative_imports.py
@@ -4,7 +4,7 @@ from . import util as import_util
import sys
import unittest
-class RelativeImports(unittest.TestCase):
+class RelativeImports:
"""PEP 328 introduced relative imports. This allows for imports to occur
from within a package without having to specify the actual package name.
@@ -64,7 +64,7 @@ class RelativeImports(unittest.TestCase):
uncache_names.append(name)
else:
uncache_names.append(name[:-len('.__init__')])
- with util.mock_modules(*create) as importer:
+ with util.mock_spec(*create) as importer:
with util.import_state(meta_path=[importer]):
for global_ in globals_:
with util.uncache(*uncache_names):
@@ -76,8 +76,8 @@ class RelativeImports(unittest.TestCase):
create = 'pkg.__init__', 'pkg.mod2'
globals_ = {'__package__': 'pkg'}, {'__name__': 'pkg.mod1'}
def callback(global_):
- import_util.import_('pkg') # For __import__().
- module = import_util.import_('', global_, fromlist=['mod2'], level=1)
+ self.__import__('pkg') # For __import__().
+ module = self.__import__('', global_, fromlist=['mod2'], level=1)
self.assertEqual(module.__name__, 'pkg')
self.assertTrue(hasattr(module, 'mod2'))
self.assertEqual(module.mod2.attr, 'pkg.mod2')
@@ -88,8 +88,8 @@ class RelativeImports(unittest.TestCase):
create = 'pkg.__init__', 'pkg.mod2'
globals_ = {'__package__': 'pkg'}, {'__name__': 'pkg.mod1'}
def callback(global_):
- import_util.import_('pkg') # For __import__().
- module = import_util.import_('mod2', global_, fromlist=['attr'],
+ self.__import__('pkg') # For __import__().
+ module = self.__import__('mod2', global_, fromlist=['attr'],
level=1)
self.assertEqual(module.__name__, 'pkg.mod2')
self.assertEqual(module.attr, 'pkg.mod2')
@@ -101,8 +101,8 @@ class RelativeImports(unittest.TestCase):
globals_ = ({'__package__': 'pkg'},
{'__name__': 'pkg', '__path__': ['blah']})
def callback(global_):
- import_util.import_('pkg') # For __import__().
- module = import_util.import_('', global_, fromlist=['module'],
+ self.__import__('pkg') # For __import__().
+ module = self.__import__('', global_, fromlist=['module'],
level=1)
self.assertEqual(module.__name__, 'pkg')
self.assertTrue(hasattr(module, 'module'))
@@ -114,8 +114,8 @@ class RelativeImports(unittest.TestCase):
create = 'pkg.__init__', 'pkg.module'
globals_ = {'__package__': 'pkg'}, {'__name__': 'pkg.module'}
def callback(global_):
- import_util.import_('pkg') # For __import__().
- module = import_util.import_('', global_, fromlist=['attr'], level=1)
+ self.__import__('pkg') # For __import__().
+ module = self.__import__('', global_, fromlist=['attr'], level=1)
self.assertEqual(module.__name__, 'pkg')
self.relative_import_test(create, globals_, callback)
@@ -126,7 +126,7 @@ class RelativeImports(unittest.TestCase):
globals_ = ({'__package__': 'pkg.subpkg1'},
{'__name__': 'pkg.subpkg1', '__path__': ['blah']})
def callback(global_):
- module = import_util.import_('', global_, fromlist=['subpkg2'],
+ module = self.__import__('', global_, fromlist=['subpkg2'],
level=2)
self.assertEqual(module.__name__, 'pkg')
self.assertTrue(hasattr(module, 'subpkg2'))
@@ -142,8 +142,8 @@ class RelativeImports(unittest.TestCase):
{'__name__': 'pkg.pkg1.pkg2.pkg3.pkg4.pkg5',
'__path__': ['blah']})
def callback(global_):
- import_util.import_(globals_[0]['__package__'])
- module = import_util.import_('', global_, fromlist=['attr'], level=6)
+ self.__import__(globals_[0]['__package__'])
+ module = self.__import__('', global_, fromlist=['attr'], level=6)
self.assertEqual(module.__name__, 'pkg')
self.relative_import_test(create, globals_, callback)
@@ -153,9 +153,9 @@ class RelativeImports(unittest.TestCase):
globals_ = ({'__package__': 'pkg'},
{'__name__': 'pkg', '__path__': ['blah']})
def callback(global_):
- import_util.import_('pkg')
+ self.__import__('pkg')
with self.assertRaises(ValueError):
- import_util.import_('', global_, fromlist=['top_level'],
+ self.__import__('', global_, fromlist=['top_level'],
level=2)
self.relative_import_test(create, globals_, callback)
@@ -164,16 +164,16 @@ class RelativeImports(unittest.TestCase):
create = ['top_level', 'pkg.__init__', 'pkg.module']
globals_ = {'__package__': 'pkg'}, {'__name__': 'pkg.module'}
def callback(global_):
- import_util.import_('pkg')
+ self.__import__('pkg')
with self.assertRaises(ValueError):
- import_util.import_('', global_, fromlist=['top_level'],
+ self.__import__('', global_, fromlist=['top_level'],
level=2)
self.relative_import_test(create, globals_, callback)
def test_empty_name_w_level_0(self):
# [empty name]
with self.assertRaises(ValueError):
- import_util.import_('')
+ self.__import__('')
def test_import_from_different_package(self):
# Test importing from a different package than the caller.
@@ -186,8 +186,8 @@ class RelativeImports(unittest.TestCase):
'__runpy_pkg__.uncle.cousin.nephew']
globals_ = {'__package__': '__runpy_pkg__.__runpy_pkg__'}
def callback(global_):
- import_util.import_('__runpy_pkg__.__runpy_pkg__')
- module = import_util.import_('uncle.cousin', globals_, {},
+ self.__import__('__runpy_pkg__.__runpy_pkg__')
+ module = self.__import__('uncle.cousin', globals_, {},
fromlist=['nephew'],
level=2)
self.assertEqual(module.__name__, '__runpy_pkg__.uncle.cousin')
@@ -198,20 +198,19 @@ class RelativeImports(unittest.TestCase):
create = ['crash.__init__', 'crash.mod']
globals_ = [{'__package__': 'crash', '__name__': 'crash'}]
def callback(global_):
- import_util.import_('crash')
- mod = import_util.import_('mod', global_, {}, [], 1)
+ self.__import__('crash')
+ mod = self.__import__('mod', global_, {}, [], 1)
self.assertEqual(mod.__name__, 'crash.mod')
self.relative_import_test(create, globals_, callback)
def test_relative_import_no_globals(self):
# No globals for a relative import is an error.
with self.assertRaises(KeyError):
- import_util.import_('sys', level=1)
+ self.__import__('sys', level=1)
+Frozen_RelativeImports, Source_RelativeImports = util.test_both(
+ RelativeImports, __import__=import_util.__import__)
-def test_main():
- from test.support import run_unittest
- run_unittest(RelativeImports)
if __name__ == '__main__':
- test_main()
+ unittest.main()
diff --git a/Lib/test/test_importlib/import_/util.py b/Lib/test/test_importlib/import_/util.py
index 86ac065e64..dcb490f967 100644
--- a/Lib/test/test_importlib/import_/util.py
+++ b/Lib/test/test_importlib/import_/util.py
@@ -1,22 +1,14 @@
+from .. import util
+
+frozen_importlib, source_importlib = util.import_importlib('importlib')
+
+import builtins
import functools
import importlib
import unittest
-using___import__ = False
-
-
-def import_(*args, **kwargs):
- """Delegate to allow for injecting different implementations of import."""
- if using___import__:
- return __import__(*args, **kwargs)
- else:
- return importlib.__import__(*args, **kwargs)
-
-
-def importlib_only(fxn):
- """Decorator to skip a test if using __builtins__.__import__."""
- return unittest.skipIf(using___import__, "importlib-specific test")(fxn)
+__import__ = staticmethod(builtins.__import__), staticmethod(source_importlib.__import__)
def mock_path_hook(*entries, importer):
diff --git a/Lib/test/test_importlib/namespace_pkgs/both_portions/foo/one.py b/Lib/test/test_importlib/namespace_pkgs/both_portions/foo/one.py
new file mode 100644
index 0000000000..3080f6f8f1
--- /dev/null
+++ b/Lib/test/test_importlib/namespace_pkgs/both_portions/foo/one.py
@@ -0,0 +1 @@
+attr = 'both_portions foo one'
diff --git a/Lib/test/test_importlib/namespace_pkgs/both_portions/foo/two.py b/Lib/test/test_importlib/namespace_pkgs/both_portions/foo/two.py
new file mode 100644
index 0000000000..4131d3d4be
--- /dev/null
+++ b/Lib/test/test_importlib/namespace_pkgs/both_portions/foo/two.py
@@ -0,0 +1 @@
+attr = 'both_portions foo two'
diff --git a/Lib/test/test_importlib/namespace_pkgs/missing_directory.zip b/Lib/test/test_importlib/namespace_pkgs/missing_directory.zip
new file mode 100644
index 0000000000..836a9106bc
--- /dev/null
+++ b/Lib/test/test_importlib/namespace_pkgs/missing_directory.zip
Binary files differ
diff --git a/Lib/test/test_importlib/namespace_pkgs/module_and_namespace_package/a_test.py b/Lib/test/test_importlib/namespace_pkgs/module_and_namespace_package/a_test.py
new file mode 100644
index 0000000000..43cbedbbdb
--- /dev/null
+++ b/Lib/test/test_importlib/namespace_pkgs/module_and_namespace_package/a_test.py
@@ -0,0 +1 @@
+attr = 'in module'
diff --git a/Lib/test/test_importlib/namespace_pkgs/module_and_namespace_package/a_test/empty b/Lib/test/test_importlib/namespace_pkgs/module_and_namespace_package/a_test/empty
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/Lib/test/test_importlib/namespace_pkgs/module_and_namespace_package/a_test/empty
diff --git a/Lib/test/test_importlib/namespace_pkgs/nested_portion1.zip b/Lib/test/test_importlib/namespace_pkgs/nested_portion1.zip
new file mode 100644
index 0000000000..8d22406f23
--- /dev/null
+++ b/Lib/test/test_importlib/namespace_pkgs/nested_portion1.zip
Binary files differ
diff --git a/Lib/test/test_importlib/namespace_pkgs/not_a_namespace_pkg/foo/__init__.py b/Lib/test/test_importlib/namespace_pkgs/not_a_namespace_pkg/foo/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/Lib/test/test_importlib/namespace_pkgs/not_a_namespace_pkg/foo/__init__.py
diff --git a/Lib/test/test_importlib/namespace_pkgs/not_a_namespace_pkg/foo/one.py b/Lib/test/test_importlib/namespace_pkgs/not_a_namespace_pkg/foo/one.py
new file mode 100644
index 0000000000..d8f5c831f2
--- /dev/null
+++ b/Lib/test/test_importlib/namespace_pkgs/not_a_namespace_pkg/foo/one.py
@@ -0,0 +1 @@
+attr = 'portion1 foo one'
diff --git a/Lib/test/test_importlib/namespace_pkgs/portion1/foo/one.py b/Lib/test/test_importlib/namespace_pkgs/portion1/foo/one.py
new file mode 100644
index 0000000000..d8f5c831f2
--- /dev/null
+++ b/Lib/test/test_importlib/namespace_pkgs/portion1/foo/one.py
@@ -0,0 +1 @@
+attr = 'portion1 foo one'
diff --git a/Lib/test/test_importlib/namespace_pkgs/portion2/foo/two.py b/Lib/test/test_importlib/namespace_pkgs/portion2/foo/two.py
new file mode 100644
index 0000000000..d092e1e993
--- /dev/null
+++ b/Lib/test/test_importlib/namespace_pkgs/portion2/foo/two.py
@@ -0,0 +1 @@
+attr = 'portion2 foo two'
diff --git a/Lib/test/test_importlib/namespace_pkgs/project1/parent/child/one.py b/Lib/test/test_importlib/namespace_pkgs/project1/parent/child/one.py
new file mode 100644
index 0000000000..2776fcdfde
--- /dev/null
+++ b/Lib/test/test_importlib/namespace_pkgs/project1/parent/child/one.py
@@ -0,0 +1 @@
+attr = 'parent child one'
diff --git a/Lib/test/test_importlib/namespace_pkgs/project2/parent/child/two.py b/Lib/test/test_importlib/namespace_pkgs/project2/parent/child/two.py
new file mode 100644
index 0000000000..8b037bcb0e
--- /dev/null
+++ b/Lib/test/test_importlib/namespace_pkgs/project2/parent/child/two.py
@@ -0,0 +1 @@
+attr = 'parent child two'
diff --git a/Lib/test/test_importlib/namespace_pkgs/project3/parent/child/three.py b/Lib/test/test_importlib/namespace_pkgs/project3/parent/child/three.py
new file mode 100644
index 0000000000..f8abfe1c17
--- /dev/null
+++ b/Lib/test/test_importlib/namespace_pkgs/project3/parent/child/three.py
@@ -0,0 +1 @@
+attr = 'parent child three'
diff --git a/Lib/test/test_importlib/namespace_pkgs/top_level_portion1.zip b/Lib/test/test_importlib/namespace_pkgs/top_level_portion1.zip
new file mode 100644
index 0000000000..3b866c914a
--- /dev/null
+++ b/Lib/test/test_importlib/namespace_pkgs/top_level_portion1.zip
Binary files differ
diff --git a/Lib/test/test_importlib/source/__init__.py b/Lib/test/test_importlib/source/__init__.py
index 3ef97f3aa0..4b16ecc311 100644
--- a/Lib/test/test_importlib/source/__init__.py
+++ b/Lib/test/test_importlib/source/__init__.py
@@ -1,13 +1,5 @@
-from .. import test_suite
-import os.path
-import unittest
+import os
+from test.support import load_package_tests
-
-def test_suite():
- directory = os.path.dirname(__file__)
- return test.test_suite('importlib.test.source', directory)
-
-
-if __name__ == '__main__':
- from test.support import run_unittest
- run_unittest(test_suite())
+def load_tests(*args):
+ return load_package_tests(os.path.dirname(__file__), *args)
diff --git a/Lib/test/test_importlib/source/__main__.py b/Lib/test/test_importlib/source/__main__.py
new file mode 100644
index 0000000000..40a23a297e
--- /dev/null
+++ b/Lib/test/test_importlib/source/__main__.py
@@ -0,0 +1,4 @@
+from . import load_tests
+import unittest
+
+unittest.main()
diff --git a/Lib/test/test_importlib/source/test_abc_loader.py b/Lib/test/test_importlib/source/test_abc_loader.py
deleted file mode 100644
index 0d912b6469..0000000000
--- a/Lib/test/test_importlib/source/test_abc_loader.py
+++ /dev/null
@@ -1,906 +0,0 @@
-import importlib
-from importlib import abc
-
-from .. import abc as testing_abc
-from .. import util
-from . import util as source_util
-
-import imp
-import inspect
-import io
-import marshal
-import os
-import sys
-import types
-import unittest
-import warnings
-
-
-class SourceOnlyLoaderMock(abc.SourceLoader):
-
- # Globals that should be defined for all modules.
- source = (b"_ = '::'.join([__name__, __file__, __cached__, __package__, "
- b"repr(__loader__)])")
-
- def __init__(self, path):
- self.path = path
-
- def get_data(self, path):
- assert self.path == path
- return self.source
-
- def get_filename(self, fullname):
- return self.path
-
- def module_repr(self, module):
- return '<module>'
-
-
-class SourceLoaderMock(SourceOnlyLoaderMock):
-
- source_mtime = 1
-
- def __init__(self, path, magic=imp.get_magic()):
- super().__init__(path)
- self.bytecode_path = imp.cache_from_source(self.path)
- self.source_size = len(self.source)
- data = bytearray(magic)
- data.extend(importlib._w_long(self.source_mtime))
- data.extend(importlib._w_long(self.source_size))
- code_object = compile(self.source, self.path, 'exec',
- dont_inherit=True)
- data.extend(marshal.dumps(code_object))
- self.bytecode = bytes(data)
- self.written = {}
-
- def get_data(self, path):
- if path == self.path:
- return super().get_data(path)
- elif path == self.bytecode_path:
- return self.bytecode
- else:
- raise IOError
-
- def path_stats(self, path):
- assert path == self.path
- return {'mtime': self.source_mtime, 'size': self.source_size}
-
- def set_data(self, path, data):
- self.written[path] = bytes(data)
- return path == self.bytecode_path
-
-
-class PyLoaderMock(abc.PyLoader):
-
- # Globals that should be defined for all modules.
- source = (b"_ = '::'.join([__name__, __file__, __package__, "
- b"repr(__loader__)])")
-
- def __init__(self, data):
- """Take a dict of 'module_name: path' pairings.
-
- Paths should have no file extension, allowing packages to be denoted by
- ending in '__init__'.
-
- """
- self.module_paths = data
- self.path_to_module = {val:key for key,val in data.items()}
-
- def get_data(self, path):
- if path not in self.path_to_module:
- raise IOError
- return self.source
-
- def is_package(self, name):
- filename = os.path.basename(self.get_filename(name))
- return os.path.splitext(filename)[0] == '__init__'
-
- def source_path(self, name):
- try:
- return self.module_paths[name]
- except KeyError:
- raise ImportError
-
- def get_filename(self, name):
- """Silence deprecation warning."""
- with warnings.catch_warnings(record=True) as w:
- warnings.simplefilter("always")
- path = super().get_filename(name)
- assert len(w) == 1
- assert issubclass(w[0].category, DeprecationWarning)
- return path
-
- def module_repr(self):
- return '<module>'
-
-
-class PyLoaderCompatMock(PyLoaderMock):
-
- """Mock that matches what is suggested to have a loader that is compatible
- from Python 3.1 onwards."""
-
- def get_filename(self, fullname):
- try:
- return self.module_paths[fullname]
- except KeyError:
- raise ImportError
-
- def source_path(self, fullname):
- try:
- return self.get_filename(fullname)
- except ImportError:
- return None
-
-
-class PyPycLoaderMock(abc.PyPycLoader, PyLoaderMock):
-
- default_mtime = 1
-
- def __init__(self, source, bc={}):
- """Initialize mock.
-
- 'bc' is a dict keyed on a module's name. The value is dict with
- possible keys of 'path', 'mtime', 'magic', and 'bc'. Except for 'path',
- each of those keys control if any part of created bytecode is to
- deviate from default values.
-
- """
- super().__init__(source)
- self.module_bytecode = {}
- self.path_to_bytecode = {}
- self.bytecode_to_path = {}
- for name, data in bc.items():
- self.path_to_bytecode[data['path']] = name
- self.bytecode_to_path[name] = data['path']
- magic = data.get('magic', imp.get_magic())
- mtime = importlib._w_long(data.get('mtime', self.default_mtime))
- source_size = importlib._w_long(len(self.source) & 0xFFFFFFFF)
- if 'bc' in data:
- bc = data['bc']
- else:
- bc = self.compile_bc(name)
- self.module_bytecode[name] = magic + mtime + source_size + bc
-
- def compile_bc(self, name):
- source_path = self.module_paths.get(name, '<test>') or '<test>'
- code = compile(self.source, source_path, 'exec')
- return marshal.dumps(code)
-
- def source_mtime(self, name):
- if name in self.module_paths:
- return self.default_mtime
- elif name in self.module_bytecode:
- return None
- else:
- raise ImportError
-
- def bytecode_path(self, name):
- try:
- return self.bytecode_to_path[name]
- except KeyError:
- if name in self.module_paths:
- return None
- else:
- raise ImportError
-
- def write_bytecode(self, name, bytecode):
- self.module_bytecode[name] = bytecode
- return True
-
- def get_data(self, path):
- if path in self.path_to_module:
- return super().get_data(path)
- elif path in self.path_to_bytecode:
- name = self.path_to_bytecode[path]
- return self.module_bytecode[name]
- else:
- raise IOError
-
- def is_package(self, name):
- try:
- return super().is_package(name)
- except TypeError:
- return '__init__' in self.bytecode_to_path[name]
-
- def get_code(self, name):
- with warnings.catch_warnings(record=True) as w:
- warnings.simplefilter("always")
- code_object = super().get_code(name)
- assert len(w) == 1
- assert issubclass(w[0].category, DeprecationWarning)
- return code_object
-
-class PyLoaderTests(testing_abc.LoaderTests):
-
- """Tests for importlib.abc.PyLoader."""
-
- mocker = PyLoaderMock
-
- def eq_attrs(self, ob, **kwargs):
- for attr, val in kwargs.items():
- found = getattr(ob, attr)
- self.assertEqual(found, val,
- "{} attribute: {} != {}".format(attr, found, val))
-
- def test_module(self):
- name = '<module>'
- path = os.path.join('', 'path', 'to', 'module')
- mock = self.mocker({name: path})
- with util.uncache(name):
- module = mock.load_module(name)
- self.assertIn(name, sys.modules)
- self.eq_attrs(module, __name__=name, __file__=path, __package__='',
- __loader__=mock)
- self.assertTrue(not hasattr(module, '__path__'))
- return mock, name
-
- def test_package(self):
- name = '<pkg>'
- path = os.path.join('path', 'to', name, '__init__')
- mock = self.mocker({name: path})
- with util.uncache(name):
- module = mock.load_module(name)
- self.assertIn(name, sys.modules)
- self.eq_attrs(module, __name__=name, __file__=path,
- __path__=[os.path.dirname(path)], __package__=name,
- __loader__=mock)
- return mock, name
-
- def test_lacking_parent(self):
- name = 'pkg.mod'
- path = os.path.join('path', 'to', 'pkg', 'mod')
- mock = self.mocker({name: path})
- with util.uncache(name):
- module = mock.load_module(name)
- self.assertIn(name, sys.modules)
- self.eq_attrs(module, __name__=name, __file__=path, __package__='pkg',
- __loader__=mock)
- self.assertFalse(hasattr(module, '__path__'))
- return mock, name
-
- def test_module_reuse(self):
- name = 'mod'
- path = os.path.join('path', 'to', 'mod')
- module = imp.new_module(name)
- mock = self.mocker({name: path})
- with util.uncache(name):
- sys.modules[name] = module
- loaded_module = mock.load_module(name)
- self.assertIs(loaded_module, module)
- self.assertIs(sys.modules[name], module)
- return mock, name
-
- def test_state_after_failure(self):
- name = "mod"
- module = imp.new_module(name)
- module.blah = None
- mock = self.mocker({name: os.path.join('path', 'to', 'mod')})
- mock.source = b"1/0"
- with util.uncache(name):
- sys.modules[name] = module
- with self.assertRaises(ZeroDivisionError):
- mock.load_module(name)
- self.assertIs(sys.modules[name], module)
- self.assertTrue(hasattr(module, 'blah'))
- return mock
-
- def test_unloadable(self):
- name = "mod"
- mock = self.mocker({name: os.path.join('path', 'to', 'mod')})
- mock.source = b"1/0"
- with util.uncache(name):
- with self.assertRaises(ZeroDivisionError):
- mock.load_module(name)
- self.assertNotIn(name, sys.modules)
- return mock
-
-
-class PyLoaderCompatTests(PyLoaderTests):
-
- """Test that the suggested code to make a loader that is compatible from
- Python 3.1 forward works."""
-
- mocker = PyLoaderCompatMock
-
-
-class PyLoaderInterfaceTests(unittest.TestCase):
-
- """Tests for importlib.abc.PyLoader to make sure that when source_path()
- doesn't return a path everything works as expected."""
-
- def test_no_source_path(self):
- # No source path should lead to ImportError.
- name = 'mod'
- mock = PyLoaderMock({})
- with util.uncache(name), self.assertRaises(ImportError):
- mock.load_module(name)
-
- def test_source_path_is_None(self):
- name = 'mod'
- mock = PyLoaderMock({name: None})
- with util.uncache(name), self.assertRaises(ImportError):
- mock.load_module(name)
-
- def test_get_filename_with_source_path(self):
- # get_filename() should return what source_path() returns.
- name = 'mod'
- path = os.path.join('path', 'to', 'source')
- mock = PyLoaderMock({name: path})
- with util.uncache(name):
- self.assertEqual(mock.get_filename(name), path)
-
- def test_get_filename_no_source_path(self):
- # get_filename() should raise ImportError if source_path returns None.
- name = 'mod'
- mock = PyLoaderMock({name: None})
- with util.uncache(name), self.assertRaises(ImportError):
- mock.get_filename(name)
-
-
-class PyPycLoaderTests(PyLoaderTests):
-
- """Tests for importlib.abc.PyPycLoader."""
-
- mocker = PyPycLoaderMock
-
- @source_util.writes_bytecode_files
- def verify_bytecode(self, mock, name):
- assert name in mock.module_paths
- self.assertIn(name, mock.module_bytecode)
- magic = mock.module_bytecode[name][:4]
- self.assertEqual(magic, imp.get_magic())
- mtime = importlib._r_long(mock.module_bytecode[name][4:8])
- self.assertEqual(mtime, 1)
- source_size = mock.module_bytecode[name][8:12]
- self.assertEqual(len(mock.source) & 0xFFFFFFFF,
- importlib._r_long(source_size))
- bc = mock.module_bytecode[name][12:]
- self.assertEqual(bc, mock.compile_bc(name))
-
- def test_module(self):
- mock, name = super().test_module()
- self.verify_bytecode(mock, name)
-
- def test_package(self):
- mock, name = super().test_package()
- self.verify_bytecode(mock, name)
-
- def test_lacking_parent(self):
- mock, name = super().test_lacking_parent()
- self.verify_bytecode(mock, name)
-
- def test_module_reuse(self):
- mock, name = super().test_module_reuse()
- self.verify_bytecode(mock, name)
-
- def test_state_after_failure(self):
- super().test_state_after_failure()
-
- def test_unloadable(self):
- super().test_unloadable()
-
-
-class PyPycLoaderInterfaceTests(unittest.TestCase):
-
- """Test for the interface of importlib.abc.PyPycLoader."""
-
- def get_filename_check(self, src_path, bc_path, expect):
- name = 'mod'
- mock = PyPycLoaderMock({name: src_path}, {name: {'path': bc_path}})
- with util.uncache(name):
- assert mock.source_path(name) == src_path
- assert mock.bytecode_path(name) == bc_path
- self.assertEqual(mock.get_filename(name), expect)
-
- def test_filename_with_source_bc(self):
- # When source and bytecode paths present, return the source path.
- self.get_filename_check('source_path', 'bc_path', 'source_path')
-
- def test_filename_with_source_no_bc(self):
- # With source but no bc, return source path.
- self.get_filename_check('source_path', None, 'source_path')
-
- def test_filename_with_no_source_bc(self):
- # With not source but bc, return the bc path.
- self.get_filename_check(None, 'bc_path', 'bc_path')
-
- def test_filename_with_no_source_or_bc(self):
- # With no source or bc, raise ImportError.
- name = 'mod'
- mock = PyPycLoaderMock({name: None}, {name: {'path': None}})
- with util.uncache(name), self.assertRaises(ImportError):
- mock.get_filename(name)
-
-
-class SkipWritingBytecodeTests(unittest.TestCase):
-
- """Test that bytecode is properly handled based on
- sys.dont_write_bytecode."""
-
- @source_util.writes_bytecode_files
- def run_test(self, dont_write_bytecode):
- name = 'mod'
- mock = PyPycLoaderMock({name: os.path.join('path', 'to', 'mod')})
- sys.dont_write_bytecode = dont_write_bytecode
- with util.uncache(name):
- mock.load_module(name)
- self.assertIsNot(name in mock.module_bytecode, dont_write_bytecode)
-
- def test_no_bytecode_written(self):
- self.run_test(True)
-
- def test_bytecode_written(self):
- self.run_test(False)
-
-
-class RegeneratedBytecodeTests(unittest.TestCase):
-
- """Test that bytecode is regenerated as expected."""
-
- @source_util.writes_bytecode_files
- def test_different_magic(self):
- # A different magic number should lead to new bytecode.
- name = 'mod'
- bad_magic = b'\x00\x00\x00\x00'
- assert bad_magic != imp.get_magic()
- mock = PyPycLoaderMock({name: os.path.join('path', 'to', 'mod')},
- {name: {'path': os.path.join('path', 'to',
- 'mod.bytecode'),
- 'magic': bad_magic}})
- with util.uncache(name):
- mock.load_module(name)
- self.assertIn(name, mock.module_bytecode)
- magic = mock.module_bytecode[name][:4]
- self.assertEqual(magic, imp.get_magic())
-
- @source_util.writes_bytecode_files
- def test_old_mtime(self):
- # Bytecode with an older mtime should be regenerated.
- name = 'mod'
- old_mtime = PyPycLoaderMock.default_mtime - 1
- mock = PyPycLoaderMock({name: os.path.join('path', 'to', 'mod')},
- {name: {'path': 'path/to/mod.bytecode', 'mtime': old_mtime}})
- with util.uncache(name):
- mock.load_module(name)
- self.assertIn(name, mock.module_bytecode)
- mtime = importlib._r_long(mock.module_bytecode[name][4:8])
- self.assertEqual(mtime, PyPycLoaderMock.default_mtime)
-
-
-class BadBytecodeFailureTests(unittest.TestCase):
-
- """Test import failures when there is no source and parts of the bytecode
- is bad."""
-
- def test_bad_magic(self):
- # A bad magic number should lead to an ImportError.
- name = 'mod'
- bad_magic = b'\x00\x00\x00\x00'
- bc = {name:
- {'path': os.path.join('path', 'to', 'mod'),
- 'magic': bad_magic}}
- mock = PyPycLoaderMock({name: None}, bc)
- with util.uncache(name), self.assertRaises(ImportError) as cm:
- mock.load_module(name)
- self.assertEqual(cm.exception.name, name)
-
- def test_no_bytecode(self):
- # Missing code object bytecode should lead to an EOFError.
- name = 'mod'
- bc = {name: {'path': os.path.join('path', 'to', 'mod'), 'bc': b''}}
- mock = PyPycLoaderMock({name: None}, bc)
- with util.uncache(name), self.assertRaises(EOFError):
- mock.load_module(name)
-
- def test_bad_bytecode(self):
- # Malformed code object bytecode should lead to a ValueError.
- name = 'mod'
- bc = {name: {'path': os.path.join('path', 'to', 'mod'), 'bc': b'1234'}}
- mock = PyPycLoaderMock({name: None}, bc)
- with util.uncache(name), self.assertRaises(ValueError):
- mock.load_module(name)
-
-
-def raise_ImportError(*args, **kwargs):
- raise ImportError
-
-class MissingPathsTests(unittest.TestCase):
-
- """Test what happens when a source or bytecode path does not exist (either
- from *_path returning None or raising ImportError)."""
-
- def test_source_path_None(self):
- # Bytecode should be used when source_path returns None, along with
- # __file__ being set to the bytecode path.
- name = 'mod'
- bytecode_path = 'path/to/mod'
- mock = PyPycLoaderMock({name: None}, {name: {'path': bytecode_path}})
- with util.uncache(name):
- module = mock.load_module(name)
- self.assertEqual(module.__file__, bytecode_path)
-
- # Testing for bytecode_path returning None handled by all tests where no
- # bytecode initially exists.
-
- def test_all_paths_None(self):
- # If all *_path methods return None, raise ImportError.
- name = 'mod'
- mock = PyPycLoaderMock({name: None})
- with util.uncache(name), self.assertRaises(ImportError) as cm:
- mock.load_module(name)
- self.assertEqual(cm.exception.name, name)
-
- def test_source_path_ImportError(self):
- # An ImportError from source_path should trigger an ImportError.
- name = 'mod'
- mock = PyPycLoaderMock({}, {name: {'path': os.path.join('path', 'to',
- 'mod')}})
- with util.uncache(name), self.assertRaises(ImportError):
- mock.load_module(name)
-
- def test_bytecode_path_ImportError(self):
- # An ImportError from bytecode_path should trigger an ImportError.
- name = 'mod'
- mock = PyPycLoaderMock({name: os.path.join('path', 'to', 'mod')})
- bad_meth = types.MethodType(raise_ImportError, mock)
- mock.bytecode_path = bad_meth
- with util.uncache(name), self.assertRaises(ImportError) as cm:
- mock.load_module(name)
-
-
-class SourceLoaderTestHarness(unittest.TestCase):
-
- def setUp(self, *, is_package=True, **kwargs):
- self.package = 'pkg'
- if is_package:
- self.path = os.path.join(self.package, '__init__.py')
- self.name = self.package
- else:
- module_name = 'mod'
- self.path = os.path.join(self.package, '.'.join(['mod', 'py']))
- self.name = '.'.join([self.package, module_name])
- self.cached = imp.cache_from_source(self.path)
- self.loader = self.loader_mock(self.path, **kwargs)
-
- def verify_module(self, module):
- self.assertEqual(module.__name__, self.name)
- self.assertEqual(module.__file__, self.path)
- self.assertEqual(module.__cached__, self.cached)
- self.assertEqual(module.__package__, self.package)
- self.assertEqual(module.__loader__, self.loader)
- values = module._.split('::')
- self.assertEqual(values[0], self.name)
- self.assertEqual(values[1], self.path)
- self.assertEqual(values[2], self.cached)
- self.assertEqual(values[3], self.package)
- self.assertEqual(values[4], repr(self.loader))
-
- def verify_code(self, code_object):
- module = imp.new_module(self.name)
- module.__file__ = self.path
- module.__cached__ = self.cached
- module.__package__ = self.package
- module.__loader__ = self.loader
- module.__path__ = []
- exec(code_object, module.__dict__)
- self.verify_module(module)
-
-
-class SourceOnlyLoaderTests(SourceLoaderTestHarness):
-
- """Test importlib.abc.SourceLoader for source-only loading.
-
- Reload testing is subsumed by the tests for
- importlib.util.module_for_loader.
-
- """
-
- loader_mock = SourceOnlyLoaderMock
-
- def test_get_source(self):
- # Verify the source code is returned as a string.
- # If an IOError is raised by get_data then raise ImportError.
- expected_source = self.loader.source.decode('utf-8')
- self.assertEqual(self.loader.get_source(self.name), expected_source)
- def raise_IOError(path):
- raise IOError
- self.loader.get_data = raise_IOError
- with self.assertRaises(ImportError) as cm:
- self.loader.get_source(self.name)
- self.assertEqual(cm.exception.name, self.name)
-
- def test_is_package(self):
- # Properly detect when loading a package.
- self.setUp(is_package=False)
- self.assertFalse(self.loader.is_package(self.name))
- self.setUp(is_package=True)
- self.assertTrue(self.loader.is_package(self.name))
- self.assertFalse(self.loader.is_package(self.name + '.__init__'))
-
- def test_get_code(self):
- # Verify the code object is created.
- code_object = self.loader.get_code(self.name)
- self.verify_code(code_object)
-
- def test_load_module(self):
- # Loading a module should set __name__, __loader__, __package__,
- # __path__ (for packages), __file__, and __cached__.
- # The module should also be put into sys.modules.
- with util.uncache(self.name):
- module = self.loader.load_module(self.name)
- self.verify_module(module)
- self.assertEqual(module.__path__, [os.path.dirname(self.path)])
- self.assertIn(self.name, sys.modules)
-
- def test_package_settings(self):
- # __package__ needs to be set, while __path__ is set on if the module
- # is a package.
- # Testing the values for a package are covered by test_load_module.
- self.setUp(is_package=False)
- with util.uncache(self.name):
- module = self.loader.load_module(self.name)
- self.verify_module(module)
- self.assertTrue(not hasattr(module, '__path__'))
-
- def test_get_source_encoding(self):
- # Source is considered encoded in UTF-8 by default unless otherwise
- # specified by an encoding line.
- source = "_ = 'ΓΌ'"
- self.loader.source = source.encode('utf-8')
- returned_source = self.loader.get_source(self.name)
- self.assertEqual(returned_source, source)
- source = "# coding: latin-1\n_ = ΓΌ"
- self.loader.source = source.encode('latin-1')
- returned_source = self.loader.get_source(self.name)
- self.assertEqual(returned_source, source)
-
-
-@unittest.skipIf(sys.dont_write_bytecode, "sys.dont_write_bytecode is true")
-class SourceLoaderBytecodeTests(SourceLoaderTestHarness):
-
- """Test importlib.abc.SourceLoader's use of bytecode.
-
- Source-only testing handled by SourceOnlyLoaderTests.
-
- """
-
- loader_mock = SourceLoaderMock
-
- def verify_code(self, code_object, *, bytecode_written=False):
- super().verify_code(code_object)
- if bytecode_written:
- self.assertIn(self.cached, self.loader.written)
- data = bytearray(imp.get_magic())
- data.extend(importlib._w_long(self.loader.source_mtime))
- data.extend(importlib._w_long(self.loader.source_size))
- data.extend(marshal.dumps(code_object))
- self.assertEqual(self.loader.written[self.cached], bytes(data))
-
- def test_code_with_everything(self):
- # When everything should work.
- code_object = self.loader.get_code(self.name)
- self.verify_code(code_object)
-
- def test_no_bytecode(self):
- # If no bytecode exists then move on to the source.
- self.loader.bytecode_path = "<does not exist>"
- # Sanity check
- with self.assertRaises(IOError):
- bytecode_path = imp.cache_from_source(self.path)
- self.loader.get_data(bytecode_path)
- code_object = self.loader.get_code(self.name)
- self.verify_code(code_object, bytecode_written=True)
-
- def test_code_bad_timestamp(self):
- # Bytecode is only used when the timestamp matches the source EXACTLY.
- for source_mtime in (0, 2):
- assert source_mtime != self.loader.source_mtime
- original = self.loader.source_mtime
- self.loader.source_mtime = source_mtime
- # If bytecode is used then EOFError would be raised by marshal.
- self.loader.bytecode = self.loader.bytecode[8:]
- code_object = self.loader.get_code(self.name)
- self.verify_code(code_object, bytecode_written=True)
- self.loader.source_mtime = original
-
- def test_code_bad_magic(self):
- # Skip over bytecode with a bad magic number.
- self.setUp(magic=b'0000')
- # If bytecode is used then EOFError would be raised by marshal.
- self.loader.bytecode = self.loader.bytecode[8:]
- code_object = self.loader.get_code(self.name)
- self.verify_code(code_object, bytecode_written=True)
-
- def test_dont_write_bytecode(self):
- # Bytecode is not written if sys.dont_write_bytecode is true.
- # Can assume it is false already thanks to the skipIf class decorator.
- try:
- sys.dont_write_bytecode = True
- self.loader.bytecode_path = "<does not exist>"
- code_object = self.loader.get_code(self.name)
- self.assertNotIn(self.cached, self.loader.written)
- finally:
- sys.dont_write_bytecode = False
-
- def test_no_set_data(self):
- # If set_data is not defined, one can still read bytecode.
- self.setUp(magic=b'0000')
- original_set_data = self.loader.__class__.set_data
- try:
- del self.loader.__class__.set_data
- code_object = self.loader.get_code(self.name)
- self.verify_code(code_object)
- finally:
- self.loader.__class__.set_data = original_set_data
-
- def test_set_data_raises_exceptions(self):
- # Raising NotImplementedError or IOError is okay for set_data.
- def raise_exception(exc):
- def closure(*args, **kwargs):
- raise exc
- return closure
-
- self.setUp(magic=b'0000')
- self.loader.set_data = raise_exception(NotImplementedError)
- code_object = self.loader.get_code(self.name)
- self.verify_code(code_object)
-
-
-class SourceLoaderGetSourceTests(unittest.TestCase):
-
- """Tests for importlib.abc.SourceLoader.get_source()."""
-
- def test_default_encoding(self):
- # Should have no problems with UTF-8 text.
- name = 'mod'
- mock = SourceOnlyLoaderMock('mod.file')
- source = 'x = "ΓΌ"'
- mock.source = source.encode('utf-8')
- returned_source = mock.get_source(name)
- self.assertEqual(returned_source, source)
-
- def test_decoded_source(self):
- # Decoding should work.
- name = 'mod'
- mock = SourceOnlyLoaderMock("mod.file")
- source = "# coding: Latin-1\nx='ΓΌ'"
- assert source.encode('latin-1') != source.encode('utf-8')
- mock.source = source.encode('latin-1')
- returned_source = mock.get_source(name)
- self.assertEqual(returned_source, source)
-
- def test_universal_newlines(self):
- # PEP 302 says universal newlines should be used.
- name = 'mod'
- mock = SourceOnlyLoaderMock('mod.file')
- source = "x = 42\r\ny = -13\r\n"
- mock.source = source.encode('utf-8')
- expect = io.IncrementalNewlineDecoder(None, True).decode(source)
- self.assertEqual(mock.get_source(name), expect)
-
-
-class AbstractMethodImplTests(unittest.TestCase):
-
- """Test the concrete abstractmethod implementations."""
-
- class MetaPathFinder(abc.MetaPathFinder):
- def find_module(self, fullname, path):
- super().find_module(fullname, path)
-
- class PathEntryFinder(abc.PathEntryFinder):
- def find_module(self, _):
- super().find_module(_)
-
- def find_loader(self, _):
- super().find_loader(_)
-
- class Finder(abc.Finder):
- def find_module(self, fullname, path):
- super().find_module(fullname, path)
-
- class Loader(abc.Loader):
- def load_module(self, fullname):
- super().load_module(fullname)
- def module_repr(self, module):
- super().module_repr(module)
-
- class ResourceLoader(Loader, abc.ResourceLoader):
- def get_data(self, _):
- super().get_data(_)
-
- class InspectLoader(Loader, abc.InspectLoader):
- def is_package(self, _):
- super().is_package(_)
-
- def get_code(self, _):
- super().get_code(_)
-
- def get_source(self, _):
- super().get_source(_)
-
- class ExecutionLoader(InspectLoader, abc.ExecutionLoader):
- def get_filename(self, _):
- super().get_filename(_)
-
- class SourceLoader(ResourceLoader, ExecutionLoader, abc.SourceLoader):
- pass
-
- class PyLoader(ResourceLoader, InspectLoader, abc.PyLoader):
- def source_path(self, _):
- super().source_path(_)
-
- class PyPycLoader(PyLoader, abc.PyPycLoader):
- def bytecode_path(self, _):
- super().bytecode_path(_)
-
- def source_mtime(self, _):
- super().source_mtime(_)
-
- def write_bytecode(self, _, _2):
- super().write_bytecode(_, _2)
-
- def raises_NotImplementedError(self, ins, *args):
- for method_name in args:
- method = getattr(ins, method_name)
- arg_count = len(inspect.getfullargspec(method)[0]) - 1
- args = [''] * arg_count
- try:
- method(*args)
- except NotImplementedError:
- pass
- else:
- msg = "{}.{} did not raise NotImplementedError"
- self.fail(msg.format(ins.__class__.__name__, method_name))
-
- def test_Loader(self):
- self.raises_NotImplementedError(self.Loader(), 'load_module')
-
- # XXX misplaced; should be somewhere else
- def test_Finder(self):
- self.raises_NotImplementedError(self.Finder(), 'find_module')
-
- def test_ResourceLoader(self):
- self.raises_NotImplementedError(self.ResourceLoader(), 'load_module',
- 'get_data')
-
- def test_InspectLoader(self):
- self.raises_NotImplementedError(self.InspectLoader(), 'load_module',
- 'is_package', 'get_code', 'get_source')
-
- def test_ExecutionLoader(self):
- self.raises_NotImplementedError(self.ExecutionLoader(), 'load_module',
- 'is_package', 'get_code', 'get_source',
- 'get_filename')
-
- def test_SourceLoader(self):
- ins = self.SourceLoader()
- # Required abstractmethods.
- self.raises_NotImplementedError(ins, 'get_filename', 'get_data')
- # Optional abstractmethods.
- self.raises_NotImplementedError(ins,'path_stats', 'set_data')
-
- def test_PyLoader(self):
- self.raises_NotImplementedError(self.PyLoader(), 'source_path',
- 'get_data', 'is_package')
-
- def test_PyPycLoader(self):
- self.raises_NotImplementedError(self.PyPycLoader(), 'source_path',
- 'source_mtime', 'bytecode_path',
- 'write_bytecode')
-
-
-def test_main():
- from test.support import run_unittest
- run_unittest(PyLoaderTests, PyLoaderCompatTests,
- PyLoaderInterfaceTests,
- PyPycLoaderTests, PyPycLoaderInterfaceTests,
- SkipWritingBytecodeTests, RegeneratedBytecodeTests,
- BadBytecodeFailureTests, MissingPathsTests,
- SourceOnlyLoaderTests,
- SourceLoaderBytecodeTests,
- SourceLoaderGetSourceTests,
- AbstractMethodImplTests)
-
-
-if __name__ == '__main__':
- test_main()
diff --git a/Lib/test/test_importlib/source/test_case_sensitivity.py b/Lib/test/test_importlib/source/test_case_sensitivity.py
index 241173fb44..efd3146d90 100644
--- a/Lib/test/test_importlib/source/test_case_sensitivity.py
+++ b/Lib/test/test_importlib/source/test_case_sensitivity.py
@@ -1,9 +1,10 @@
"""Test case-sensitivity (PEP 235)."""
-from importlib import _bootstrap
-from importlib import machinery
from .. import util
from . import util as source_util
-import imp
+
+importlib = util.import_importlib('importlib')
+machinery = util.import_importlib('importlib.machinery')
+
import os
import sys
from test import support as test_support
@@ -11,7 +12,7 @@ import unittest
@util.case_insensitive_tests
-class CaseSensitivityTest(unittest.TestCase):
+class CaseSensitivityTest:
"""PEP 235 dictates that on case-preserving, case-insensitive file systems
that imports are case-sensitive unless the PYTHONCASEOK environment
@@ -20,13 +21,12 @@ class CaseSensitivityTest(unittest.TestCase):
name = 'MoDuLe'
assert name != name.lower()
- def find(self, path):
- finder = machinery.FileFinder(path,
- (machinery.SourceFileLoader,
- machinery.SOURCE_SUFFIXES),
- (machinery.SourcelessFileLoader,
- machinery.BYTECODE_SUFFIXES))
- return finder.find_module(self.name)
+ def finder(self, path):
+ return self.machinery.FileFinder(path,
+ (self.machinery.SourceFileLoader,
+ self.machinery.SOURCE_SUFFIXES),
+ (self.machinery.SourcelessFileLoader,
+ self.machinery.BYTECODE_SUFFIXES))
def sensitivity_test(self):
"""Look for a module with matching and non-matching sensitivity."""
@@ -36,35 +36,48 @@ class CaseSensitivityTest(unittest.TestCase):
with context as mapping:
sensitive_path = os.path.join(mapping['.root'], 'sensitive')
insensitive_path = os.path.join(mapping['.root'], 'insensitive')
- return self.find(sensitive_path), self.find(insensitive_path)
+ sensitive_finder = self.finder(sensitive_path)
+ insensitive_finder = self.finder(insensitive_path)
+ return self.find(sensitive_finder), self.find(insensitive_finder)
def test_sensitive(self):
with test_support.EnvironmentVarGuard() as env:
env.unset('PYTHONCASEOK')
- if b'PYTHONCASEOK' in _bootstrap._os.environ:
+ if b'PYTHONCASEOK' in self.importlib._bootstrap._os.environ:
self.skipTest('os.environ changes not reflected in '
'_os.environ')
sensitive, insensitive = self.sensitivity_test()
- self.assertTrue(hasattr(sensitive, 'load_module'))
+ self.assertIsNotNone(sensitive)
self.assertIn(self.name, sensitive.get_filename(self.name))
self.assertIsNone(insensitive)
def test_insensitive(self):
with test_support.EnvironmentVarGuard() as env:
env.set('PYTHONCASEOK', '1')
- if b'PYTHONCASEOK' not in _bootstrap._os.environ:
+ if b'PYTHONCASEOK' not in self.importlib._bootstrap._os.environ:
self.skipTest('os.environ changes not reflected in '
'_os.environ')
sensitive, insensitive = self.sensitivity_test()
- self.assertTrue(hasattr(sensitive, 'load_module'))
+ self.assertIsNotNone(sensitive)
self.assertIn(self.name, sensitive.get_filename(self.name))
- self.assertTrue(hasattr(insensitive, 'load_module'))
+ self.assertIsNotNone(insensitive)
self.assertIn(self.name, insensitive.get_filename(self.name))
+class CaseSensitivityTestPEP302(CaseSensitivityTest):
+ def find(self, finder):
+ return finder.find_module(self.name)
+
+Frozen_CaseSensitivityTestPEP302, Source_CaseSensitivityTestPEP302 = util.test_both(
+ CaseSensitivityTestPEP302, importlib=importlib, machinery=machinery)
+
+class CaseSensitivityTestPEP451(CaseSensitivityTest):
+ def find(self, finder):
+ found = finder.find_spec(self.name)
+ return found.loader if found is not None else found
-def test_main():
- test_support.run_unittest(CaseSensitivityTest)
+Frozen_CaseSensitivityTestPEP451, Source_CaseSensitivityTestPEP451 = util.test_both(
+ CaseSensitivityTestPEP451, importlib=importlib, machinery=machinery)
if __name__ == '__main__':
- test_main()
+ unittest.main()
diff --git a/Lib/test/test_importlib/source/test_file_loader.py b/Lib/test/test_importlib/source/test_file_loader.py
index d711cb3e79..2d415f985d 100644
--- a/Lib/test/test_importlib/source/test_file_loader.py
+++ b/Lib/test/test_importlib/source/test_file_loader.py
@@ -1,52 +1,52 @@
-from importlib import machinery
-import importlib
-import importlib.abc
from .. import abc
from .. import util
from . import util as source_util
+importlib = util.import_importlib('importlib')
+importlib_abc = util.import_importlib('importlib.abc')
+machinery = util.import_importlib('importlib.machinery')
+importlib_util = util.import_importlib('importlib.util')
+
import errno
-import imp
import marshal
import os
import py_compile
import shutil
import stat
import sys
+import types
import unittest
+import warnings
-from test.support import make_legacy_pyc
+from test.support import make_legacy_pyc, unload
-class SimpleTest(unittest.TestCase):
+class SimpleTest(abc.LoaderTests):
"""Should have no issue importing a source module [basic]. And if there is
a syntax error, it should raise a SyntaxError [syntax error].
"""
- def test_load_module_API(self):
- # If fullname is not specified that assume self.name is desired.
- class TesterMixin(importlib.abc.Loader):
- def load_module(self, fullname): return fullname
- def module_repr(self, module): return '<module>'
+ def setUp(self):
+ self.name = 'spam'
+ self.filepath = os.path.join('ham', self.name + '.py')
+ self.loader = self.machinery.SourceFileLoader(self.name, self.filepath)
- class Tester(importlib.abc.FileLoader, TesterMixin):
- def get_code(self, _): pass
- def get_source(self, _): pass
- def is_package(self, _): pass
+ def test_load_module_API(self):
+ class Tester(self.abc.FileLoader):
+ def get_source(self, _): return 'attr = 42'
+ def is_package(self, _): return False
- name = 'mod_name'
- loader = Tester(name, 'some_path')
- self.assertEqual(name, loader.load_module())
- self.assertEqual(name, loader.load_module(None))
- self.assertEqual(name, loader.load_module(name))
- with self.assertRaises(ImportError):
- loader.load_module(loader.name + 'XXX')
+ loader = Tester('blah', 'blah.py')
+ self.addCleanup(unload, 'blah')
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ module = loader.load_module() # Should not raise an exception.
def test_get_filename_API(self):
# If fullname is not set then assume self.path is desired.
- class Tester(importlib.abc.FileLoader):
+ class Tester(self.abc.FileLoader):
def get_code(self, _): pass
def get_source(self, _): pass
def is_package(self, _): pass
@@ -61,11 +61,21 @@ class SimpleTest(unittest.TestCase):
with self.assertRaises(ImportError):
loader.get_filename(name + 'XXX')
+ def test_equality(self):
+ other = self.machinery.SourceFileLoader(self.name, self.filepath)
+ self.assertEqual(self.loader, other)
+
+ def test_inequality(self):
+ other = self.machinery.SourceFileLoader('_' + self.name, self.filepath)
+ self.assertNotEqual(self.loader, other)
+
# [basic]
def test_module(self):
with source_util.create_modules('_temp') as mapping:
- loader = machinery.SourceFileLoader('_temp', mapping['_temp'])
- module = loader.load_module('_temp')
+ loader = self.machinery.SourceFileLoader('_temp', mapping['_temp'])
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ module = loader.load_module('_temp')
self.assertIn('_temp', sys.modules)
check = {'__name__': '_temp', '__file__': mapping['_temp'],
'__package__': ''}
@@ -74,9 +84,11 @@ class SimpleTest(unittest.TestCase):
def test_package(self):
with source_util.create_modules('_pkg.__init__') as mapping:
- loader = machinery.SourceFileLoader('_pkg',
+ loader = self.machinery.SourceFileLoader('_pkg',
mapping['_pkg.__init__'])
- module = loader.load_module('_pkg')
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ module = loader.load_module('_pkg')
self.assertIn('_pkg', sys.modules)
check = {'__name__': '_pkg', '__file__': mapping['_pkg.__init__'],
'__path__': [os.path.dirname(mapping['_pkg.__init__'])],
@@ -87,9 +99,11 @@ class SimpleTest(unittest.TestCase):
def test_lacking_parent(self):
with source_util.create_modules('_pkg.__init__', '_pkg.mod')as mapping:
- loader = machinery.SourceFileLoader('_pkg.mod',
+ loader = self.machinery.SourceFileLoader('_pkg.mod',
mapping['_pkg.mod'])
- module = loader.load_module('_pkg.mod')
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ module = loader.load_module('_pkg.mod')
self.assertIn('_pkg.mod', sys.modules)
check = {'__name__': '_pkg.mod', '__file__': mapping['_pkg.mod'],
'__package__': '_pkg'}
@@ -102,13 +116,17 @@ class SimpleTest(unittest.TestCase):
def test_module_reuse(self):
with source_util.create_modules('_temp') as mapping:
- loader = machinery.SourceFileLoader('_temp', mapping['_temp'])
- module = loader.load_module('_temp')
+ loader = self.machinery.SourceFileLoader('_temp', mapping['_temp'])
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ module = loader.load_module('_temp')
module_id = id(module)
module_dict_id = id(module.__dict__)
with open(mapping['_temp'], 'w') as file:
file.write("testing_var = 42\n")
- module = loader.load_module('_temp')
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ module = loader.load_module('_temp')
self.assertIn('testing_var', module.__dict__,
"'testing_var' not in "
"{0}".format(list(module.__dict__.keys())))
@@ -122,14 +140,20 @@ class SimpleTest(unittest.TestCase):
value = '<test>'
name = '_temp'
with source_util.create_modules(name) as mapping:
- orig_module = imp.new_module(name)
+ orig_module = types.ModuleType(name)
for attr in attributes:
setattr(orig_module, attr, value)
with open(mapping[name], 'w') as file:
file.write('+++ bad syntax +++')
- loader = machinery.SourceFileLoader('_temp', mapping['_temp'])
+ loader = self.machinery.SourceFileLoader('_temp', mapping['_temp'])
+ with self.assertRaises(SyntaxError):
+ loader.exec_module(orig_module)
+ for attr in attributes:
+ self.assertEqual(getattr(orig_module, attr), value)
with self.assertRaises(SyntaxError):
- loader.load_module(name)
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ loader.load_module(name)
for attr in attributes:
self.assertEqual(getattr(orig_module, attr), value)
@@ -138,9 +162,11 @@ class SimpleTest(unittest.TestCase):
with source_util.create_modules('_temp') as mapping:
with open(mapping['_temp'], 'w') as file:
file.write('=')
- loader = machinery.SourceFileLoader('_temp', mapping['_temp'])
+ loader = self.machinery.SourceFileLoader('_temp', mapping['_temp'])
with self.assertRaises(SyntaxError):
- loader.load_module('_temp')
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ loader.load_module('_temp')
self.assertNotIn('_temp', sys.modules)
def test_file_from_empty_string_dir(self):
@@ -151,14 +177,16 @@ class SimpleTest(unittest.TestCase):
file.write("# test file for importlib")
try:
with util.uncache('_temp'):
- loader = machinery.SourceFileLoader('_temp', file_path)
- mod = loader.load_module('_temp')
+ loader = self.machinery.SourceFileLoader('_temp', file_path)
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ mod = loader.load_module('_temp')
self.assertEqual(file_path, mod.__file__)
- self.assertEqual(imp.cache_from_source(file_path),
+ self.assertEqual(self.util.cache_from_source(file_path),
mod.__cached__)
finally:
os.unlink(file_path)
- pycache = os.path.dirname(imp.cache_from_source(file_path))
+ pycache = os.path.dirname(self.util.cache_from_source(file_path))
if os.path.exists(pycache):
shutil.rmtree(pycache)
@@ -168,7 +196,7 @@ class SimpleTest(unittest.TestCase):
# truncated rather than raise an OverflowError.
with source_util.create_modules('_temp') as mapping:
source = mapping['_temp']
- compiled = imp.cache_from_source(source)
+ compiled = self.util.cache_from_source(source)
with open(source, 'w') as f:
f.write("x = 5")
try:
@@ -179,20 +207,48 @@ class SimpleTest(unittest.TestCase):
if e.errno != getattr(errno, 'EOVERFLOW', None):
raise
self.skipTest("cannot set modification time to large integer ({})".format(e))
- loader = machinery.SourceFileLoader('_temp', mapping['_temp'])
- mod = loader.load_module('_temp')
+ loader = self.machinery.SourceFileLoader('_temp', mapping['_temp'])
+ # PEP 451
+ module = types.ModuleType('_temp')
+ module.__spec__ = self.util.spec_from_loader('_temp', loader)
+ loader.exec_module(module)
+ self.assertEqual(module.x, 5)
+ self.assertTrue(os.path.exists(compiled))
+ os.unlink(compiled)
+ # PEP 302
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ mod = loader.load_module('_temp') # XXX
# Sanity checks.
self.assertEqual(mod.__cached__, compiled)
self.assertEqual(mod.x, 5)
# The pyc file was created.
- os.stat(compiled)
+ self.assertTrue(os.path.exists(compiled))
+
+ def test_unloadable(self):
+ loader = self.machinery.SourceFileLoader('good name', {})
+ module = types.ModuleType('bad name')
+ module.__spec__ = self.machinery.ModuleSpec('bad name', loader)
+ with self.assertRaises(ImportError):
+ loader.exec_module(module)
+ with self.assertRaises(ImportError):
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ loader.load_module('bad name')
+
+Frozen_SimpleTest, Source_SimpleTest = util.test_both(
+ SimpleTest, importlib=importlib, machinery=machinery, abc=importlib_abc,
+ util=importlib_util)
-class BadBytecodeTest(unittest.TestCase):
+class BadBytecodeTest:
def import_(self, file, module_name):
loader = self.loader(module_name, file)
- module = loader.load_module(module_name)
+ 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)
def manipulate_bytecode(self, name, mapping, manipulator, *,
@@ -205,7 +261,7 @@ class BadBytecodeTest(unittest.TestCase):
pass
py_compile.compile(mapping[name])
if not del_source:
- bytecode_path = imp.cache_from_source(mapping[name])
+ bytecode_path = self.util.cache_from_source(mapping[name])
else:
os.unlink(mapping[name])
bytecode_path = make_legacy_pyc(mapping[name])
@@ -291,10 +347,29 @@ class BadBytecodeTest(unittest.TestCase):
lambda bc: b'\x00\x00\x00\x00' + bc[4:])
test('_temp', mapping, bc_path)
+class BadBytecodeTestPEP451(BadBytecodeTest):
+
+ def import_(self, file, module_name):
+ loader = self.loader(module_name, file)
+ module = types.ModuleType(module_name)
+ module.__spec__ = self.util.spec_from_loader(module_name, loader)
+ loader.exec_module(module)
+
+class BadBytecodeTestPEP302(BadBytecodeTest):
+
+ def import_(self, file, module_name):
+ loader = self.loader(module_name, file)
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ module = loader.load_module(module_name)
+ self.assertIn(module_name, sys.modules)
-class SourceLoaderBadBytecodeTest(BadBytecodeTest):
- loader = machinery.SourceFileLoader
+class SourceLoaderBadBytecodeTest:
+
+ @classmethod
+ def setUpClass(cls):
+ cls.loader = cls.machinery.SourceFileLoader
@source_util.writes_bytecode_files
def test_empty_file(self):
@@ -333,7 +408,8 @@ class SourceLoaderBadBytecodeTest(BadBytecodeTest):
def test(name, mapping, bytecode_path):
self.import_(mapping[name], name)
with open(bytecode_path, 'rb') as bytecode_file:
- self.assertEqual(bytecode_file.read(4), imp.get_magic())
+ self.assertEqual(bytecode_file.read(4),
+ self.util.MAGIC_NUMBER)
self._test_bad_magic(test)
@@ -383,13 +459,13 @@ class SourceLoaderBadBytecodeTest(BadBytecodeTest):
zeros = b'\x00\x00\x00\x00'
with source_util.create_modules('_temp') as mapping:
py_compile.compile(mapping['_temp'])
- bytecode_path = imp.cache_from_source(mapping['_temp'])
+ bytecode_path = self.util.cache_from_source(mapping['_temp'])
with open(bytecode_path, 'r+b') as bytecode_file:
bytecode_file.seek(4)
bytecode_file.write(zeros)
self.import_(mapping['_temp'], '_temp')
source_mtime = os.path.getmtime(mapping['_temp'])
- source_timestamp = importlib._w_long(source_mtime)
+ source_timestamp = self.importlib._w_long(source_mtime)
with open(bytecode_path, 'rb') as bytecode_file:
bytecode_file.seek(4)
self.assertEqual(bytecode_file.read(4), source_timestamp)
@@ -401,7 +477,7 @@ class SourceLoaderBadBytecodeTest(BadBytecodeTest):
with source_util.create_modules('_temp') as mapping:
# Create bytecode that will need to be re-created.
py_compile.compile(mapping['_temp'])
- bytecode_path = imp.cache_from_source(mapping['_temp'])
+ bytecode_path = self.util.cache_from_source(mapping['_temp'])
with open(bytecode_path, 'r+b') as bytecode_file:
bytecode_file.seek(0)
bytecode_file.write(b'\x00\x00\x00\x00')
@@ -409,16 +485,34 @@ class SourceLoaderBadBytecodeTest(BadBytecodeTest):
os.chmod(bytecode_path,
stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH)
try:
- # Should not raise IOError!
+ # Should not raise OSError!
self.import_(mapping['_temp'], '_temp')
finally:
# Make writable for eventual clean-up.
os.chmod(bytecode_path, stat.S_IWUSR)
+class SourceLoaderBadBytecodeTestPEP451(
+ SourceLoaderBadBytecodeTest, BadBytecodeTestPEP451):
+ pass
+
+Frozen_SourceBadBytecodePEP451, Source_SourceBadBytecodePEP451 = util.test_both(
+ SourceLoaderBadBytecodeTestPEP451, importlib=importlib, machinery=machinery,
+ abc=importlib_abc, util=importlib_util)
+
+class SourceLoaderBadBytecodeTestPEP302(
+ SourceLoaderBadBytecodeTest, BadBytecodeTestPEP302):
+ pass
+
+Frozen_SourceBadBytecodePEP302, Source_SourceBadBytecodePEP302 = util.test_both(
+ SourceLoaderBadBytecodeTestPEP302, importlib=importlib, machinery=machinery,
+ abc=importlib_abc, util=importlib_util)
-class SourcelessLoaderBadBytecodeTest(BadBytecodeTest):
- loader = machinery.SourcelessFileLoader
+class SourcelessLoaderBadBytecodeTest:
+
+ @classmethod
+ def setUpClass(cls):
+ cls.loader = cls.machinery.SourcelessFileLoader
def test_empty_file(self):
def test(name, mapping, bytecode_path):
@@ -473,14 +567,22 @@ class SourcelessLoaderBadBytecodeTest(BadBytecodeTest):
def test_non_code_marshal(self):
self._test_non_code_marshal(del_source=True)
+class SourcelessLoaderBadBytecodeTestPEP451(SourcelessLoaderBadBytecodeTest,
+ BadBytecodeTestPEP451):
+ pass
+
+Frozen_SourcelessBadBytecodePEP451, Source_SourcelessBadBytecodePEP451 = util.test_both(
+ SourcelessLoaderBadBytecodeTestPEP451, importlib=importlib,
+ machinery=machinery, abc=importlib_abc, util=importlib_util)
+
+class SourcelessLoaderBadBytecodeTestPEP302(SourcelessLoaderBadBytecodeTest,
+ BadBytecodeTestPEP302):
+ pass
-def test_main():
- from test.support import run_unittest
- run_unittest(SimpleTest,
- SourceLoaderBadBytecodeTest,
- SourcelessLoaderBadBytecodeTest
- )
+Frozen_SourcelessBadBytecodePEP302, Source_SourcelessBadBytecodePEP302 = util.test_both(
+ SourcelessLoaderBadBytecodeTestPEP302, importlib=importlib,
+ machinery=machinery, abc=importlib_abc, util=importlib_util)
if __name__ == '__main__':
- test_main()
+ unittest.main()
diff --git a/Lib/test/test_importlib/source/test_finder.py b/Lib/test/test_importlib/source/test_finder.py
index 8e4986835d..473297bdc8 100644
--- a/Lib/test/test_importlib/source/test_finder.py
+++ b/Lib/test/test_importlib/source/test_finder.py
@@ -1,9 +1,10 @@
from .. import abc
+from .. import util
from . import util as source_util
-from importlib import machinery
+machinery = util.import_importlib('importlib.machinery')
+
import errno
-import imp
import os
import py_compile
import stat
@@ -39,14 +40,15 @@ class FinderTests(abc.FinderTests):
"""
def get_finder(self, root):
- loader_details = [(machinery.SourceFileLoader,
- machinery.SOURCE_SUFFIXES),
- (machinery.SourcelessFileLoader,
- machinery.BYTECODE_SUFFIXES)]
- return machinery.FileFinder(root, *loader_details)
+ loader_details = [(self.machinery.SourceFileLoader,
+ self.machinery.SOURCE_SUFFIXES),
+ (self.machinery.SourcelessFileLoader,
+ self.machinery.BYTECODE_SUFFIXES)]
+ return self.machinery.FileFinder(root, *loader_details)
def import_(self, root, module):
- return self.get_finder(root).find_module(module)
+ finder = self.get_finder(root)
+ return self._find(finder, module, loader_only=True)
def run_test(self, test, create=None, *, compile_=None, unlink=None):
"""Test the finding of 'test' with the creation of modules listed in
@@ -124,20 +126,20 @@ class FinderTests(abc.FinderTests):
def test_empty_string_for_dir(self):
# The empty string from sys.path means to search in the cwd.
- finder = machinery.FileFinder('', (machinery.SourceFileLoader,
- machinery.SOURCE_SUFFIXES))
+ finder = self.machinery.FileFinder('', (self.machinery.SourceFileLoader,
+ self.machinery.SOURCE_SUFFIXES))
with open('mod.py', 'w') as file:
file.write("# test file for importlib")
try:
- loader = finder.find_module('mod')
+ loader = self._find(finder, 'mod', loader_only=True)
self.assertTrue(hasattr(loader, 'load_module'))
finally:
os.unlink('mod.py')
def test_invalidate_caches(self):
# invalidate_caches() should reset the mtime.
- finder = machinery.FileFinder('', (machinery.SourceFileLoader,
- machinery.SOURCE_SUFFIXES))
+ finder = self.machinery.FileFinder('', (self.machinery.SourceFileLoader,
+ self.machinery.SOURCE_SUFFIXES))
finder._path_mtime = 42
finder.invalidate_caches()
self.assertEqual(finder._path_mtime, -1)
@@ -147,8 +149,10 @@ class FinderTests(abc.FinderTests):
mod = 'mod'
with source_util.create_modules(mod) as mapping:
finder = self.get_finder(mapping['.root'])
- self.assertIsNotNone(finder.find_module(mod))
- self.assertIsNone(finder.find_module(mod))
+ found = self._find(finder, 'mod', loader_only=True)
+ self.assertIsNotNone(found)
+ found = self._find(finder, 'mod', loader_only=True)
+ self.assertIsNone(found)
@unittest.skipUnless(sys.platform != 'win32',
'os.chmod() does not support the needed arguments under Windows')
@@ -172,20 +176,57 @@ class FinderTests(abc.FinderTests):
self.addCleanup(cleanup, tempdir)
os.chmod(tempdir.name, stat.S_IWUSR | stat.S_IXUSR)
finder = self.get_finder(tempdir.name)
- self.assertEqual((None, []), finder.find_loader('doesnotexist'))
+ found = self._find(finder, 'doesnotexist')
+ self.assertEqual(found, self.NOT_FOUND)
def test_ignore_file(self):
# If a directory got changed to a file from underneath us, then don't
# worry about looking for submodules.
with tempfile.NamedTemporaryFile() as file_obj:
finder = self.get_finder(file_obj.name)
- self.assertEqual((None, []), finder.find_loader('doesnotexist'))
+ found = self._find(finder, 'doesnotexist')
+ self.assertEqual(found, self.NOT_FOUND)
+
+
+class FinderTestsPEP451(FinderTests):
+
+ NOT_FOUND = None
+
+ def _find(self, finder, name, loader_only=False):
+ spec = finder.find_spec(name)
+ return spec.loader if spec is not None else spec
+
+Frozen_FinderTestsPEP451, Source_FinderTestsPEP451 = util.test_both(
+ FinderTestsPEP451, machinery=machinery)
+
+
+class FinderTestsPEP420(FinderTests):
+
+ NOT_FOUND = (None, [])
+
+ def _find(self, finder, name, loader_only=False):
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore", DeprecationWarning)
+ loader_portions = finder.find_loader(name)
+ return loader_portions[0] if loader_only else loader_portions
+
+Frozen_FinderTestsPEP420, Source_FinderTestsPEP420 = util.test_both(
+ FinderTestsPEP420, machinery=machinery)
+
+
+class FinderTestsPEP302(FinderTests):
+
+ NOT_FOUND = None
+
+ def _find(self, finder, name, loader_only=False):
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore", DeprecationWarning)
+ return finder.find_module(name)
+Frozen_FinderTestsPEP302, Source_FinderTestsPEP302 = util.test_both(
+ FinderTestsPEP302, machinery=machinery)
-def test_main():
- from test.support import run_unittest
- run_unittest(FinderTests)
if __name__ == '__main__':
- test_main()
+ unittest.main()
diff --git a/Lib/test/test_importlib/source/test_path_hook.py b/Lib/test/test_importlib/source/test_path_hook.py
index 6a78792f07..92da77265b 100644
--- a/Lib/test/test_importlib/source/test_path_hook.py
+++ b/Lib/test/test_importlib/source/test_path_hook.py
@@ -1,17 +1,18 @@
+from .. import util
from . import util as source_util
-from importlib import machinery
-import imp
+machinery = util.import_importlib('importlib.machinery')
+
import unittest
-class PathHookTest(unittest.TestCase):
+class PathHookTest:
"""Test the path hook for source."""
def path_hook(self):
- return machinery.FileFinder.path_hook((machinery.SourceFileLoader,
- machinery.SOURCE_SUFFIXES))
+ return self.machinery.FileFinder.path_hook((self.machinery.SourceFileLoader,
+ self.machinery.SOURCE_SUFFIXES))
def test_success(self):
with source_util.create_modules('dummy') as mapping:
@@ -22,11 +23,8 @@ class PathHookTest(unittest.TestCase):
# The empty string represents the cwd.
self.assertTrue(hasattr(self.path_hook()(''), 'find_module'))
-
-def test_main():
- from test.support import run_unittest
- run_unittest(PathHookTest)
+Frozen_PathHookTest, Source_PathHooktest = util.test_both(PathHookTest, machinery=machinery)
if __name__ == '__main__':
- test_main()
+ unittest.main()
diff --git a/Lib/test/test_importlib/source/test_source_encoding.py b/Lib/test/test_importlib/source/test_source_encoding.py
index ba02b44274..c62dfa108d 100644
--- a/Lib/test/test_importlib/source/test_source_encoding.py
+++ b/Lib/test/test_importlib/source/test_source_encoding.py
@@ -1,19 +1,24 @@
+from .. import util
from . import util as source_util
-from importlib import _bootstrap
+machinery = util.import_importlib('importlib.machinery')
+
import codecs
+import importlib.util
import re
import sys
+import types
# Because sys.path gets essentially blanked, need to have unicodedata already
# imported for the parser to use.
import unicodedata
import unittest
+import warnings
CODING_RE = re.compile(r'^[ \t\f]*#.*coding[:=][ \t]*([-\w.]+)', re.ASCII)
-class EncodingTest(unittest.TestCase):
+class EncodingTest:
"""PEP 3120 makes UTF-8 the default encoding for source code
[default encoding].
@@ -35,9 +40,9 @@ class EncodingTest(unittest.TestCase):
with source_util.create_modules(self.module_name) as mapping:
with open(mapping[self.module_name], 'wb') as file:
file.write(source)
- loader = _bootstrap.SourceFileLoader(self.module_name,
+ loader = self.machinery.SourceFileLoader(self.module_name,
mapping[self.module_name])
- return loader.load_module(self.module_name)
+ return self.load(loader)
def create_source(self, encoding):
encoding_line = "# coding={0}".format(encoding)
@@ -84,8 +89,29 @@ class EncodingTest(unittest.TestCase):
with self.assertRaises(SyntaxError):
self.run_test(source)
+class EncodingTestPEP451(EncodingTest):
+
+ def load(self, loader):
+ module = types.ModuleType(self.module_name)
+ module.__spec__ = importlib.util.spec_from_loader(self.module_name, loader)
+ loader.exec_module(module)
+ return module
+
+Frozen_EncodingTestPEP451, Source_EncodingTestPEP451 = util.test_both(
+ EncodingTestPEP451, machinery=machinery)
+
+class EncodingTestPEP302(EncodingTest):
+
+ def load(self, loader):
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ return loader.load_module(self.module_name)
+
+Frozen_EncodingTestPEP302, Source_EncodingTestPEP302 = util.test_both(
+ EncodingTestPEP302, machinery=machinery)
-class LineEndingTest(unittest.TestCase):
+
+class LineEndingTest:
r"""Source written with the three types of line endings (\n, \r\n, \r)
need to be readable [cr][crlf][lf]."""
@@ -97,9 +123,9 @@ class LineEndingTest(unittest.TestCase):
with source_util.create_modules(module_name) as mapping:
with open(mapping[module_name], 'wb') as file:
file.write(source)
- loader = _bootstrap.SourceFileLoader(module_name,
- mapping[module_name])
- return loader.load_module(module_name)
+ loader = self.machinery.SourceFileLoader(module_name,
+ mapping[module_name])
+ return self.load(loader, module_name)
# [cr]
def test_cr(self):
@@ -113,11 +139,27 @@ class LineEndingTest(unittest.TestCase):
def test_lf(self):
self.run_test(b'\n')
+class LineEndingTestPEP451(LineEndingTest):
+
+ def load(self, loader, module_name):
+ module = types.ModuleType(module_name)
+ module.__spec__ = importlib.util.spec_from_loader(module_name, loader)
+ loader.exec_module(module)
+ return module
+
+Frozen_LineEndingTestPEP451, Source_LineEndingTestPEP451 = util.test_both(
+ LineEndingTestPEP451, machinery=machinery)
+
+class LineEndingTestPEP302(LineEndingTest):
+
+ def load(self, loader, module_name):
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ return loader.load_module(module_name)
-def test_main():
- from test.support import run_unittest
- run_unittest(EncodingTest, LineEndingTest)
+Frozen_LineEndingTestPEP302, Source_LineEndingTestPEP302 = util.test_both(
+ LineEndingTestPEP302, machinery=machinery)
if __name__ == '__main__':
- test_main()
+ unittest.main()
diff --git a/Lib/test/test_importlib/source/util.py b/Lib/test/test_importlib/source/util.py
index ae65663a67..63cd25adc4 100644
--- a/Lib/test/test_importlib/source/util.py
+++ b/Lib/test/test_importlib/source/util.py
@@ -2,7 +2,6 @@ from .. import util
import contextlib
import errno
import functools
-import imp
import os
import os.path
import sys
diff --git a/Lib/test/test_importlib/test_abc.py b/Lib/test/test_importlib/test_abc.py
index c620c3771b..a1f8e76302 100644
--- a/Lib/test/test_importlib/test_abc.py
+++ b/Lib/test/test_importlib/test_abc.py
@@ -1,9 +1,23 @@
-from importlib import abc
-from importlib import machinery
+import contextlib
import inspect
+import io
+import marshal
+import os
+import sys
+from test import support
+import types
import unittest
+from unittest import mock
+import warnings
+from . import util
+frozen_init, source_init = util.import_importlib('importlib')
+frozen_abc, source_abc = util.import_importlib('importlib.abc')
+machinery = util.import_importlib('importlib.machinery')
+frozen_util, source_util = util.import_importlib('importlib.util')
+
+##### Inheritance ##############################################################
class InheritanceTests:
"""Test that the specified class is a subclass/superclass of the expected
@@ -14,8 +28,19 @@ class InheritanceTests:
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
+ self.superclasses = [getattr(self.abc, class_name)
+ for class_name in self.superclass_names]
+ if hasattr(self, 'subclass_names'):
+ # Because test.support.import_fresh_module() creates a new
+ # importlib._bootstrap per module, inheritance checks fail when
+ # checking across module boundaries (i.e. the _bootstrap in abc is
+ # not the same as the one in machinery). That means stealing one of
+ # the modules from the other to make sure the same instance is used.
+ self.subclasses = [getattr(self.abc.machinery, class_name)
+ for class_name in self.subclass_names]
assert self.subclasses or self.superclasses, self.__class__
- self.__test = getattr(abc, self.__class__.__name__)
+ testing = self.__class__.__name__.partition('_')[2]
+ self.__test = getattr(self.abc, testing)
def test_subclasses(self):
# Test that the expected subclasses inherit.
@@ -29,75 +54,898 @@ class InheritanceTests:
self.assertTrue(issubclass(self.__test, superclass),
"{0} is not a superclass of {1}".format(superclass, self.__test))
+def create_inheritance_tests(base_class):
+ def set_frozen(ns):
+ ns['abc'] = frozen_abc
+ def set_source(ns):
+ ns['abc'] = source_abc
-class MetaPathFinder(InheritanceTests, unittest.TestCase):
+ classes = []
+ for prefix, ns_set in [('Frozen', set_frozen), ('Source', set_source)]:
+ classes.append(types.new_class('_'.join([prefix, base_class.__name__]),
+ (base_class, unittest.TestCase),
+ exec_body=ns_set))
+ return classes
- superclasses = [abc.Finder]
- subclasses = [machinery.BuiltinImporter, machinery.FrozenImporter,
- machinery.PathFinder, machinery.WindowsRegistryFinder]
+class MetaPathFinder(InheritanceTests):
+ superclass_names = ['Finder']
+ subclass_names = ['BuiltinImporter', 'FrozenImporter', 'PathFinder',
+ 'WindowsRegistryFinder']
-class PathEntryFinder(InheritanceTests, unittest.TestCase):
+tests = create_inheritance_tests(MetaPathFinder)
+Frozen_MetaPathFinderInheritanceTests, Source_MetaPathFinderInheritanceTests = tests
- superclasses = [abc.Finder]
- subclasses = [machinery.FileFinder]
+class PathEntryFinder(InheritanceTests):
+ superclass_names = ['Finder']
+ subclass_names = ['FileFinder']
-class Loader(InheritanceTests, unittest.TestCase):
+tests = create_inheritance_tests(PathEntryFinder)
+Frozen_PathEntryFinderInheritanceTests, Source_PathEntryFinderInheritanceTests = tests
- subclasses = [abc.PyLoader]
+class ResourceLoader(InheritanceTests):
+ superclass_names = ['Loader']
-class ResourceLoader(InheritanceTests, unittest.TestCase):
+tests = create_inheritance_tests(ResourceLoader)
+Frozen_ResourceLoaderInheritanceTests, Source_ResourceLoaderInheritanceTests = tests
- superclasses = [abc.Loader]
+class InspectLoader(InheritanceTests):
+ superclass_names = ['Loader']
+ subclass_names = ['BuiltinImporter', 'FrozenImporter', 'ExtensionFileLoader']
-class InspectLoader(InheritanceTests, unittest.TestCase):
+tests = create_inheritance_tests(InspectLoader)
+Frozen_InspectLoaderInheritanceTests, Source_InspectLoaderInheritanceTests = tests
- superclasses = [abc.Loader]
- subclasses = [abc.PyLoader, machinery.BuiltinImporter,
- machinery.FrozenImporter, machinery.ExtensionFileLoader]
+class ExecutionLoader(InheritanceTests):
+ superclass_names = ['InspectLoader']
+ subclass_names = ['ExtensionFileLoader']
-class ExecutionLoader(InheritanceTests, unittest.TestCase):
+tests = create_inheritance_tests(ExecutionLoader)
+Frozen_ExecutionLoaderInheritanceTests, Source_ExecutionLoaderInheritanceTests = tests
- superclasses = [abc.InspectLoader]
- subclasses = [abc.PyLoader]
+class FileLoader(InheritanceTests):
+ superclass_names = ['ResourceLoader', 'ExecutionLoader']
+ subclass_names = ['SourceFileLoader', 'SourcelessFileLoader']
-class FileLoader(InheritanceTests, unittest.TestCase):
+tests = create_inheritance_tests(FileLoader)
+Frozen_FileLoaderInheritanceTests, Source_FileLoaderInheritanceTests = tests
- superclasses = [abc.ResourceLoader, abc.ExecutionLoader]
- subclasses = [machinery.SourceFileLoader, machinery.SourcelessFileLoader]
+class SourceLoader(InheritanceTests):
+ superclass_names = ['ResourceLoader', 'ExecutionLoader']
+ subclass_names = ['SourceFileLoader']
-class SourceLoader(InheritanceTests, unittest.TestCase):
+tests = create_inheritance_tests(SourceLoader)
+Frozen_SourceLoaderInheritanceTests, Source_SourceLoaderInheritanceTests = tests
- superclasses = [abc.ResourceLoader, abc.ExecutionLoader]
- subclasses = [machinery.SourceFileLoader]
+##### Default return values ####################################################
+def make_abc_subclasses(base_class):
+ classes = []
+ for kind, abc in [('Frozen', frozen_abc), ('Source', source_abc)]:
+ name = '_'.join([kind, base_class.__name__])
+ base_classes = base_class, getattr(abc, base_class.__name__)
+ classes.append(types.new_class(name, base_classes))
+ return classes
+def make_return_value_tests(base_class, test_class):
+ frozen_class, source_class = make_abc_subclasses(base_class)
+ tests = []
+ for prefix, class_in_test in [('Frozen', frozen_class), ('Source', source_class)]:
+ def set_ns(ns):
+ ns['ins'] = class_in_test()
+ tests.append(types.new_class('_'.join([prefix, test_class.__name__]),
+ (test_class, unittest.TestCase),
+ exec_body=set_ns))
+ return tests
-class PyLoader(InheritanceTests, unittest.TestCase):
- superclasses = [abc.Loader, abc.ResourceLoader, abc.ExecutionLoader]
+class MetaPathFinder:
+ def find_module(self, fullname, path):
+ return super().find_module(fullname, path)
-class PyPycLoader(InheritanceTests, unittest.TestCase):
+Frozen_MPF, Source_MPF = make_abc_subclasses(MetaPathFinder)
- superclasses = [abc.PyLoader]
+class MetaPathFinderDefaultsTests:
-def test_main():
- from test.support import run_unittest
- classes = []
- for class_ in globals().values():
- if (inspect.isclass(class_) and
- issubclass(class_, unittest.TestCase) and
- issubclass(class_, InheritanceTests)):
- classes.append(class_)
- run_unittest(*classes)
+ def test_find_module(self):
+ # Default should return None.
+ self.assertIsNone(self.ins.find_module('something', None))
+
+ def test_invalidate_caches(self):
+ # Calling the method is a no-op.
+ self.ins.invalidate_caches()
+
+
+tests = make_return_value_tests(MetaPathFinder, MetaPathFinderDefaultsTests)
+Frozen_MPFDefaultTests, Source_MPFDefaultTests = tests
+
+
+class PathEntryFinder:
+
+ def find_loader(self, fullname):
+ return super().find_loader(fullname)
+
+Frozen_PEF, Source_PEF = make_abc_subclasses(PathEntryFinder)
+
+
+class PathEntryFinderDefaultsTests:
+
+ def test_find_loader(self):
+ self.assertEqual((None, []), self.ins.find_loader('something'))
+
+ def find_module(self):
+ self.assertEqual(None, self.ins.find_module('something'))
+
+ def test_invalidate_caches(self):
+ # Should be a no-op.
+ self.ins.invalidate_caches()
+
+
+tests = make_return_value_tests(PathEntryFinder, PathEntryFinderDefaultsTests)
+Frozen_PEFDefaultTests, Source_PEFDefaultTests = tests
+
+
+class Loader:
+
+ def load_module(self, fullname):
+ return super().load_module(fullname)
+
+
+Frozen_L, Source_L = make_abc_subclasses(Loader)
+
+
+class LoaderDefaultsTests:
+
+ def test_load_module(self):
+ with self.assertRaises(ImportError):
+ self.ins.load_module('something')
+
+ def test_module_repr(self):
+ mod = types.ModuleType('blah')
+ with self.assertRaises(NotImplementedError):
+ self.ins.module_repr(mod)
+ original_repr = repr(mod)
+ mod.__loader__ = self.ins
+ # Should still return a proper repr.
+ self.assertTrue(repr(mod))
+
+
+tests = make_return_value_tests(Loader, LoaderDefaultsTests)
+Frozen_LDefaultTests, SourceLDefaultTests = tests
+
+
+class ResourceLoader(Loader):
+
+ def get_data(self, path):
+ return super().get_data(path)
+
+
+Frozen_RL, Source_RL = make_abc_subclasses(ResourceLoader)
+
+
+class ResourceLoaderDefaultsTests:
+
+ def test_get_data(self):
+ with self.assertRaises(IOError):
+ self.ins.get_data('/some/path')
+
+
+tests = make_return_value_tests(ResourceLoader, ResourceLoaderDefaultsTests)
+Frozen_RLDefaultTests, Source_RLDefaultTests = tests
+
+
+class InspectLoader(Loader):
+
+ def is_package(self, fullname):
+ return super().is_package(fullname)
+
+ def get_source(self, fullname):
+ return super().get_source(fullname)
+
+
+Frozen_IL, Source_IL = make_abc_subclasses(InspectLoader)
+
+
+class InspectLoaderDefaultsTests:
+
+ def test_is_package(self):
+ with self.assertRaises(ImportError):
+ self.ins.is_package('blah')
+
+ def test_get_source(self):
+ with self.assertRaises(ImportError):
+ self.ins.get_source('blah')
+
+
+tests = make_return_value_tests(InspectLoader, InspectLoaderDefaultsTests)
+Frozen_ILDefaultTests, Source_ILDefaultTests = tests
+
+
+class ExecutionLoader(InspectLoader):
+
+ def get_filename(self, fullname):
+ return super().get_filename(fullname)
+
+Frozen_EL, Source_EL = make_abc_subclasses(ExecutionLoader)
+
+
+class ExecutionLoaderDefaultsTests:
+
+ def test_get_filename(self):
+ with self.assertRaises(ImportError):
+ self.ins.get_filename('blah')
+
+
+tests = make_return_value_tests(ExecutionLoader, InspectLoaderDefaultsTests)
+Frozen_ELDefaultTests, Source_ELDefaultsTests = tests
+
+##### MetaPathFinder concrete methods ##########################################
+
+class MetaPathFinderFindModuleTests:
+
+ @classmethod
+ def finder(cls, spec):
+ class MetaPathSpecFinder(cls.abc.MetaPathFinder):
+
+ def find_spec(self, fullname, path, target=None):
+ self.called_for = fullname, path
+ return spec
+
+ return MetaPathSpecFinder()
+
+ def test_no_spec(self):
+ finder = self.finder(None)
+ path = ['a', 'b', 'c']
+ name = 'blah'
+ found = finder.find_module(name, path)
+ self.assertIsNone(found)
+ self.assertEqual(name, finder.called_for[0])
+ self.assertEqual(path, finder.called_for[1])
+
+ def test_spec(self):
+ loader = object()
+ spec = self.util.spec_from_loader('blah', loader)
+ finder = self.finder(spec)
+ found = finder.find_module('blah', None)
+ self.assertIs(found, spec.loader)
+
+
+Frozen_MPFFindModuleTests, Source_MPFFindModuleTests = util.test_both(
+ MetaPathFinderFindModuleTests,
+ abc=(frozen_abc, source_abc),
+ util=(frozen_util, source_util))
+
+##### PathEntryFinder concrete methods #########################################
+
+class PathEntryFinderFindLoaderTests:
+
+ @classmethod
+ def finder(cls, spec):
+ class PathEntrySpecFinder(cls.abc.PathEntryFinder):
+
+ def find_spec(self, fullname, target=None):
+ self.called_for = fullname
+ return spec
+
+ return PathEntrySpecFinder()
+
+ def test_no_spec(self):
+ finder = self.finder(None)
+ name = 'blah'
+ found = finder.find_loader(name)
+ self.assertIsNone(found[0])
+ self.assertEqual([], found[1])
+ self.assertEqual(name, finder.called_for)
+
+ def test_spec_with_loader(self):
+ loader = object()
+ spec = self.util.spec_from_loader('blah', loader)
+ finder = self.finder(spec)
+ found = finder.find_loader('blah')
+ self.assertIs(found[0], spec.loader)
+
+ def test_spec_with_portions(self):
+ spec = self.machinery.ModuleSpec('blah', None)
+ paths = ['a', 'b', 'c']
+ spec.submodule_search_locations = paths
+ finder = self.finder(spec)
+ found = finder.find_loader('blah')
+ self.assertIsNone(found[0])
+ self.assertEqual(paths, found[1])
+
+
+Frozen_PEFFindLoaderTests, Source_PEFFindLoaderTests = util.test_both(
+ PathEntryFinderFindLoaderTests,
+ abc=(frozen_abc, source_abc),
+ machinery=machinery,
+ util=(frozen_util, source_util))
+
+
+##### Loader concrete methods ##################################################
+class LoaderLoadModuleTests:
+
+ def loader(self):
+ class SpecLoader(self.abc.Loader):
+ found = None
+ def exec_module(self, module):
+ self.found = module
+
+ def is_package(self, fullname):
+ """Force some non-default module state to be set."""
+ return True
+
+ return SpecLoader()
+
+ def test_fresh(self):
+ loader = self.loader()
+ name = 'blah'
+ with util.uncache(name):
+ loader.load_module(name)
+ module = loader.found
+ self.assertIs(sys.modules[name], module)
+ self.assertEqual(loader, module.__loader__)
+ self.assertEqual(loader, module.__spec__.loader)
+ self.assertEqual(name, module.__name__)
+ self.assertEqual(name, module.__spec__.name)
+ self.assertIsNotNone(module.__path__)
+ self.assertIsNotNone(module.__path__,
+ module.__spec__.submodule_search_locations)
+
+ def test_reload(self):
+ name = 'blah'
+ loader = self.loader()
+ module = types.ModuleType(name)
+ module.__spec__ = self.util.spec_from_loader(name, loader)
+ module.__loader__ = loader
+ with util.uncache(name):
+ sys.modules[name] = module
+ loader.load_module(name)
+ found = loader.found
+ self.assertIs(found, sys.modules[name])
+ self.assertIs(module, sys.modules[name])
+
+
+Frozen_LoaderLoadModuleTests, Source_LoaderLoadModuleTests = util.test_both(
+ LoaderLoadModuleTests,
+ abc=(frozen_abc, source_abc),
+ util=(frozen_util, source_util))
+
+
+##### InspectLoader concrete methods ###########################################
+class InspectLoaderSourceToCodeTests:
+
+ def source_to_module(self, data, path=None):
+ """Help with source_to_code() tests."""
+ module = types.ModuleType('blah')
+ loader = self.InspectLoaderSubclass()
+ if path is None:
+ code = loader.source_to_code(data)
+ else:
+ code = loader.source_to_code(data, path)
+ exec(code, module.__dict__)
+ return module
+
+ def test_source_to_code_source(self):
+ # Since compile() can handle strings, so should source_to_code().
+ source = 'attr = 42'
+ module = self.source_to_module(source)
+ self.assertTrue(hasattr(module, 'attr'))
+ self.assertEqual(module.attr, 42)
+
+ def test_source_to_code_bytes(self):
+ # Since compile() can handle bytes, so should source_to_code().
+ source = b'attr = 42'
+ module = self.source_to_module(source)
+ self.assertTrue(hasattr(module, 'attr'))
+ self.assertEqual(module.attr, 42)
+
+ def test_source_to_code_path(self):
+ # Specifying a path should set it for the code object.
+ path = 'path/to/somewhere'
+ loader = self.InspectLoaderSubclass()
+ code = loader.source_to_code('', path)
+ self.assertEqual(code.co_filename, path)
+
+ def test_source_to_code_no_path(self):
+ # Not setting a path should still work and be set to <string> since that
+ # is a pre-existing practice as a default to compile().
+ loader = self.InspectLoaderSubclass()
+ code = loader.source_to_code('')
+ self.assertEqual(code.co_filename, '<string>')
+
+
+class Frozen_ILSourceToCodeTests(InspectLoaderSourceToCodeTests, unittest.TestCase):
+ InspectLoaderSubclass = Frozen_IL
+
+class Source_ILSourceToCodeTests(InspectLoaderSourceToCodeTests, unittest.TestCase):
+ InspectLoaderSubclass = Source_IL
+
+
+class InspectLoaderGetCodeTests:
+
+ def test_get_code(self):
+ # Test success.
+ module = types.ModuleType('blah')
+ with mock.patch.object(self.InspectLoaderSubclass, 'get_source') as mocked:
+ mocked.return_value = 'attr = 42'
+ loader = self.InspectLoaderSubclass()
+ code = loader.get_code('blah')
+ exec(code, module.__dict__)
+ self.assertEqual(module.attr, 42)
+
+ def test_get_code_source_is_None(self):
+ # If get_source() is None then this should be None.
+ with mock.patch.object(self.InspectLoaderSubclass, 'get_source') as mocked:
+ mocked.return_value = None
+ loader = self.InspectLoaderSubclass()
+ code = loader.get_code('blah')
+ self.assertIsNone(code)
+
+ def test_get_code_source_not_found(self):
+ # If there is no source then there is no code object.
+ loader = self.InspectLoaderSubclass()
+ with self.assertRaises(ImportError):
+ loader.get_code('blah')
+
+
+class Frozen_ILGetCodeTests(InspectLoaderGetCodeTests, unittest.TestCase):
+ InspectLoaderSubclass = Frozen_IL
+
+class Source_ILGetCodeTests(InspectLoaderGetCodeTests, unittest.TestCase):
+ InspectLoaderSubclass = Source_IL
+
+
+class InspectLoaderLoadModuleTests:
+
+ """Test InspectLoader.load_module()."""
+
+ module_name = 'blah'
+
+ def setUp(self):
+ support.unload(self.module_name)
+ self.addCleanup(support.unload, self.module_name)
+
+ def mock_get_code(self):
+ return mock.patch.object(self.InspectLoaderSubclass, 'get_code')
+
+ def test_get_code_ImportError(self):
+ # If get_code() raises ImportError, it should propagate.
+ with self.mock_get_code() as mocked_get_code:
+ 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)
+
+ def test_get_code_None(self):
+ # If get_code() returns None, raise ImportError.
+ with self.mock_get_code() as mocked_get_code:
+ mocked_get_code.return_value = None
+ with self.assertRaises(ImportError):
+ loader = self.InspectLoaderSubclass()
+ loader.load_module(self.module_name)
+
+ def test_module_returned(self):
+ # The loaded module should be returned.
+ code = compile('attr = 42', '<string>', 'exec')
+ 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)
+ self.assertEqual(module, sys.modules[self.module_name])
+
+
+class Frozen_ILLoadModuleTests(InspectLoaderLoadModuleTests, unittest.TestCase):
+ InspectLoaderSubclass = Frozen_IL
+
+class Source_ILLoadModuleTests(InspectLoaderLoadModuleTests, unittest.TestCase):
+ InspectLoaderSubclass = Source_IL
+
+
+##### ExecutionLoader concrete methods #########################################
+class ExecutionLoaderGetCodeTests:
+
+ def mock_methods(self, *, get_source=False, get_filename=False):
+ source_mock_context, filename_mock_context = None, None
+ if get_source:
+ source_mock_context = mock.patch.object(self.ExecutionLoaderSubclass,
+ 'get_source')
+ if get_filename:
+ filename_mock_context = mock.patch.object(self.ExecutionLoaderSubclass,
+ 'get_filename')
+ return source_mock_context, filename_mock_context
+
+ def test_get_code(self):
+ path = 'blah.py'
+ source_mock_context, filename_mock_context = self.mock_methods(
+ get_source=True, get_filename=True)
+ with source_mock_context as source_mock, filename_mock_context as name_mock:
+ source_mock.return_value = 'attr = 42'
+ name_mock.return_value = path
+ loader = self.ExecutionLoaderSubclass()
+ code = loader.get_code('blah')
+ self.assertEqual(code.co_filename, path)
+ module = types.ModuleType('blah')
+ exec(code, module.__dict__)
+ self.assertEqual(module.attr, 42)
+
+ def test_get_code_source_is_None(self):
+ # If get_source() is None then this should be None.
+ source_mock_context, _ = self.mock_methods(get_source=True)
+ with source_mock_context as mocked:
+ mocked.return_value = None
+ loader = self.ExecutionLoaderSubclass()
+ code = loader.get_code('blah')
+ self.assertIsNone(code)
+
+ def test_get_code_source_not_found(self):
+ # If there is no source then there is no code object.
+ loader = self.ExecutionLoaderSubclass()
+ with self.assertRaises(ImportError):
+ loader.get_code('blah')
+
+ def test_get_code_no_path(self):
+ # If get_filename() raises ImportError then simply skip setting the path
+ # on the code object.
+ source_mock_context, filename_mock_context = self.mock_methods(
+ get_source=True, get_filename=True)
+ with source_mock_context as source_mock, filename_mock_context as name_mock:
+ source_mock.return_value = 'attr = 42'
+ name_mock.side_effect = ImportError
+ loader = self.ExecutionLoaderSubclass()
+ code = loader.get_code('blah')
+ self.assertEqual(code.co_filename, '<string>')
+ module = types.ModuleType('blah')
+ exec(code, module.__dict__)
+ self.assertEqual(module.attr, 42)
+
+
+class Frozen_ELGetCodeTests(ExecutionLoaderGetCodeTests, unittest.TestCase):
+ ExecutionLoaderSubclass = Frozen_EL
+
+class Source_ELGetCodeTests(ExecutionLoaderGetCodeTests, unittest.TestCase):
+ ExecutionLoaderSubclass = Source_EL
+
+
+##### SourceLoader concrete methods ############################################
+class SourceLoader:
+
+ # Globals that should be defined for all modules.
+ source = (b"_ = '::'.join([__name__, __file__, __cached__, __package__, "
+ b"repr(__loader__)])")
+
+ def __init__(self, path):
+ self.path = path
+
+ def get_data(self, path):
+ if path != self.path:
+ raise IOError
+ return self.source
+
+ def get_filename(self, fullname):
+ return self.path
+
+ def module_repr(self, module):
+ return '<module>'
+
+
+Frozen_SourceOnlyL, Source_SourceOnlyL = make_abc_subclasses(SourceLoader)
+
+
+class SourceLoader(SourceLoader):
+
+ source_mtime = 1
+
+ def __init__(self, path, magic=None):
+ super().__init__(path)
+ self.bytecode_path = self.util.cache_from_source(self.path)
+ self.source_size = len(self.source)
+ if magic is None:
+ magic = self.util.MAGIC_NUMBER
+ data = bytearray(magic)
+ data.extend(self.init._w_long(self.source_mtime))
+ data.extend(self.init._w_long(self.source_size))
+ code_object = compile(self.source, self.path, 'exec',
+ dont_inherit=True)
+ data.extend(marshal.dumps(code_object))
+ self.bytecode = bytes(data)
+ self.written = {}
+
+ def get_data(self, path):
+ if path == self.path:
+ return super().get_data(path)
+ elif path == self.bytecode_path:
+ return self.bytecode
+ else:
+ raise OSError
+
+ def path_stats(self, path):
+ if path != self.path:
+ raise IOError
+ return {'mtime': self.source_mtime, 'size': self.source_size}
+
+ def set_data(self, path, data):
+ self.written[path] = bytes(data)
+ return path == self.bytecode_path
+
+
+Frozen_SL, Source_SL = make_abc_subclasses(SourceLoader)
+Frozen_SL.util = frozen_util
+Source_SL.util = source_util
+Frozen_SL.init = frozen_init
+Source_SL.init = source_init
+
+
+class SourceLoaderTestHarness:
+
+ def setUp(self, *, is_package=True, **kwargs):
+ self.package = 'pkg'
+ if is_package:
+ self.path = os.path.join(self.package, '__init__.py')
+ self.name = self.package
+ else:
+ module_name = 'mod'
+ self.path = os.path.join(self.package, '.'.join(['mod', 'py']))
+ self.name = '.'.join([self.package, module_name])
+ self.cached = self.util.cache_from_source(self.path)
+ self.loader = self.loader_mock(self.path, **kwargs)
+
+ def verify_module(self, module):
+ self.assertEqual(module.__name__, self.name)
+ self.assertEqual(module.__file__, self.path)
+ self.assertEqual(module.__cached__, self.cached)
+ self.assertEqual(module.__package__, self.package)
+ self.assertEqual(module.__loader__, self.loader)
+ values = module._.split('::')
+ self.assertEqual(values[0], self.name)
+ self.assertEqual(values[1], self.path)
+ self.assertEqual(values[2], self.cached)
+ self.assertEqual(values[3], self.package)
+ self.assertEqual(values[4], repr(self.loader))
+
+ def verify_code(self, code_object):
+ module = types.ModuleType(self.name)
+ module.__file__ = self.path
+ module.__cached__ = self.cached
+ module.__package__ = self.package
+ module.__loader__ = self.loader
+ module.__path__ = []
+ exec(code_object, module.__dict__)
+ self.verify_module(module)
+
+
+class SourceOnlyLoaderTests(SourceLoaderTestHarness):
+
+ """Test importlib.abc.SourceLoader for source-only loading.
+
+ Reload testing is subsumed by the tests for
+ importlib.util.module_for_loader.
+
+ """
+
+ def test_get_source(self):
+ # Verify the source code is returned as a string.
+ # If an OSError is raised by get_data then raise ImportError.
+ expected_source = self.loader.source.decode('utf-8')
+ self.assertEqual(self.loader.get_source(self.name), expected_source)
+ def raise_OSError(path):
+ raise OSError
+ self.loader.get_data = raise_OSError
+ with self.assertRaises(ImportError) as cm:
+ self.loader.get_source(self.name)
+ self.assertEqual(cm.exception.name, self.name)
+
+ def test_is_package(self):
+ # Properly detect when loading a package.
+ self.setUp(is_package=False)
+ self.assertFalse(self.loader.is_package(self.name))
+ self.setUp(is_package=True)
+ self.assertTrue(self.loader.is_package(self.name))
+ self.assertFalse(self.loader.is_package(self.name + '.__init__'))
+
+ def test_get_code(self):
+ # Verify the code object is created.
+ code_object = self.loader.get_code(self.name)
+ self.verify_code(code_object)
+
+ def test_source_to_code(self):
+ # Verify the compiled code object.
+ code = self.loader.source_to_code(self.loader.source, self.path)
+ self.verify_code(code)
+
+ def test_load_module(self):
+ # Loading a module should set __name__, __loader__, __package__,
+ # __path__ (for packages), __file__, and __cached__.
+ # The module should also be put into sys.modules.
+ with util.uncache(self.name):
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ module = self.loader.load_module(self.name)
+ self.verify_module(module)
+ self.assertEqual(module.__path__, [os.path.dirname(self.path)])
+ self.assertIn(self.name, sys.modules)
+
+ def test_package_settings(self):
+ # __package__ needs to be set, while __path__ is set on if the module
+ # is a package.
+ # Testing the values for a package are covered by test_load_module.
+ self.setUp(is_package=False)
+ with util.uncache(self.name):
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ module = self.loader.load_module(self.name)
+ self.verify_module(module)
+ self.assertFalse(hasattr(module, '__path__'))
+
+ def test_get_source_encoding(self):
+ # Source is considered encoded in UTF-8 by default unless otherwise
+ # specified by an encoding line.
+ source = "_ = 'ΓΌ'"
+ self.loader.source = source.encode('utf-8')
+ returned_source = self.loader.get_source(self.name)
+ self.assertEqual(returned_source, source)
+ source = "# coding: latin-1\n_ = ΓΌ"
+ self.loader.source = source.encode('latin-1')
+ returned_source = self.loader.get_source(self.name)
+ self.assertEqual(returned_source, source)
+
+
+class Frozen_SourceOnlyLTests(SourceOnlyLoaderTests, unittest.TestCase):
+ loader_mock = Frozen_SourceOnlyL
+ util = frozen_util
+
+class Source_SourceOnlyLTests(SourceOnlyLoaderTests, unittest.TestCase):
+ loader_mock = Source_SourceOnlyL
+ util = source_util
+
+
+@unittest.skipIf(sys.dont_write_bytecode, "sys.dont_write_bytecode is true")
+class SourceLoaderBytecodeTests(SourceLoaderTestHarness):
+
+ """Test importlib.abc.SourceLoader's use of bytecode.
+
+ Source-only testing handled by SourceOnlyLoaderTests.
+
+ """
+
+ def verify_code(self, code_object, *, bytecode_written=False):
+ super().verify_code(code_object)
+ if bytecode_written:
+ self.assertIn(self.cached, self.loader.written)
+ data = bytearray(self.util.MAGIC_NUMBER)
+ data.extend(self.init._w_long(self.loader.source_mtime))
+ data.extend(self.init._w_long(self.loader.source_size))
+ data.extend(marshal.dumps(code_object))
+ self.assertEqual(self.loader.written[self.cached], bytes(data))
+
+ def test_code_with_everything(self):
+ # When everything should work.
+ code_object = self.loader.get_code(self.name)
+ self.verify_code(code_object)
+
+ def test_no_bytecode(self):
+ # If no bytecode exists then move on to the source.
+ self.loader.bytecode_path = "<does not exist>"
+ # Sanity check
+ with self.assertRaises(OSError):
+ bytecode_path = self.util.cache_from_source(self.path)
+ self.loader.get_data(bytecode_path)
+ code_object = self.loader.get_code(self.name)
+ self.verify_code(code_object, bytecode_written=True)
+
+ def test_code_bad_timestamp(self):
+ # Bytecode is only used when the timestamp matches the source EXACTLY.
+ for source_mtime in (0, 2):
+ assert source_mtime != self.loader.source_mtime
+ original = self.loader.source_mtime
+ self.loader.source_mtime = source_mtime
+ # If bytecode is used then EOFError would be raised by marshal.
+ self.loader.bytecode = self.loader.bytecode[8:]
+ code_object = self.loader.get_code(self.name)
+ self.verify_code(code_object, bytecode_written=True)
+ self.loader.source_mtime = original
+
+ def test_code_bad_magic(self):
+ # Skip over bytecode with a bad magic number.
+ self.setUp(magic=b'0000')
+ # If bytecode is used then EOFError would be raised by marshal.
+ self.loader.bytecode = self.loader.bytecode[8:]
+ code_object = self.loader.get_code(self.name)
+ self.verify_code(code_object, bytecode_written=True)
+
+ def test_dont_write_bytecode(self):
+ # Bytecode is not written if sys.dont_write_bytecode is true.
+ # Can assume it is false already thanks to the skipIf class decorator.
+ try:
+ sys.dont_write_bytecode = True
+ self.loader.bytecode_path = "<does not exist>"
+ code_object = self.loader.get_code(self.name)
+ self.assertNotIn(self.cached, self.loader.written)
+ finally:
+ sys.dont_write_bytecode = False
+
+ def test_no_set_data(self):
+ # If set_data is not defined, one can still read bytecode.
+ self.setUp(magic=b'0000')
+ original_set_data = self.loader.__class__.mro()[1].set_data
+ try:
+ del self.loader.__class__.mro()[1].set_data
+ code_object = self.loader.get_code(self.name)
+ self.verify_code(code_object)
+ finally:
+ self.loader.__class__.mro()[1].set_data = original_set_data
+
+ def test_set_data_raises_exceptions(self):
+ # Raising NotImplementedError or OSError is okay for set_data.
+ def raise_exception(exc):
+ def closure(*args, **kwargs):
+ raise exc
+ return closure
+
+ self.setUp(magic=b'0000')
+ self.loader.set_data = raise_exception(NotImplementedError)
+ code_object = self.loader.get_code(self.name)
+ self.verify_code(code_object)
+
+
+class Frozen_SLBytecodeTests(SourceLoaderBytecodeTests, unittest.TestCase):
+ loader_mock = Frozen_SL
+ init = frozen_init
+ util = frozen_util
+
+class SourceSLBytecodeTests(SourceLoaderBytecodeTests, unittest.TestCase):
+ loader_mock = Source_SL
+ init = source_init
+ util = source_util
+
+
+class SourceLoaderGetSourceTests:
+
+ """Tests for importlib.abc.SourceLoader.get_source()."""
+
+ def test_default_encoding(self):
+ # Should have no problems with UTF-8 text.
+ name = 'mod'
+ mock = self.SourceOnlyLoaderMock('mod.file')
+ source = 'x = "ΓΌ"'
+ mock.source = source.encode('utf-8')
+ returned_source = mock.get_source(name)
+ self.assertEqual(returned_source, source)
+
+ def test_decoded_source(self):
+ # Decoding should work.
+ name = 'mod'
+ mock = self.SourceOnlyLoaderMock("mod.file")
+ source = "# coding: Latin-1\nx='ΓΌ'"
+ assert source.encode('latin-1') != source.encode('utf-8')
+ mock.source = source.encode('latin-1')
+ returned_source = mock.get_source(name)
+ self.assertEqual(returned_source, source)
+
+ def test_universal_newlines(self):
+ # PEP 302 says universal newlines should be used.
+ name = 'mod'
+ mock = self.SourceOnlyLoaderMock('mod.file')
+ source = "x = 42\r\ny = -13\r\n"
+ mock.source = source.encode('utf-8')
+ expect = io.IncrementalNewlineDecoder(None, True).decode(source)
+ self.assertEqual(mock.get_source(name), expect)
+
+
+class Frozen_SourceOnlyLGetSourceTests(SourceLoaderGetSourceTests, unittest.TestCase):
+ SourceOnlyLoaderMock = Frozen_SourceOnlyL
+
+class Source_SourceOnlyLGetSourceTests(SourceLoaderGetSourceTests, unittest.TestCase):
+ SourceOnlyLoaderMock = Source_SourceOnlyL
if __name__ == '__main__':
- test_main()
+ unittest.main()
diff --git a/Lib/test/test_importlib/test_api.py b/Lib/test/test_importlib/test_api.py
index b1a58944f3..2a2d42bbfe 100644
--- a/Lib/test/test_importlib/test_api.py
+++ b/Lib/test/test_importlib/test_api.py
@@ -1,14 +1,18 @@
from . import util
-import imp
-import importlib
-from importlib import machinery
+
+frozen_init, source_init = util.import_importlib('importlib')
+frozen_util, source_util = util.import_importlib('importlib.util')
+frozen_machinery, source_machinery = util.import_importlib('importlib.machinery')
+
+import os.path
import sys
from test import support
import types
import unittest
+import warnings
-class ImportModuleTests(unittest.TestCase):
+class ImportModuleTests:
"""Test importlib.import_module."""
@@ -16,7 +20,7 @@ class ImportModuleTests(unittest.TestCase):
# Test importing a top-level module.
with util.mock_modules('top_level') as mock:
with util.import_state(meta_path=[mock]):
- module = importlib.import_module('top_level')
+ module = self.init.import_module('top_level')
self.assertEqual(module.__name__, 'top_level')
def test_absolute_package_import(self):
@@ -26,7 +30,7 @@ class ImportModuleTests(unittest.TestCase):
name = '{0}.mod'.format(pkg_name)
with util.mock_modules(pkg_long_name, name) as mock:
with util.import_state(meta_path=[mock]):
- module = importlib.import_module(name)
+ module = self.init.import_module(name)
self.assertEqual(module.__name__, name)
def test_shallow_relative_package_import(self):
@@ -38,17 +42,17 @@ class ImportModuleTests(unittest.TestCase):
relative_name = '.{0}'.format(module_name)
with util.mock_modules(pkg_long_name, absolute_name) as mock:
with util.import_state(meta_path=[mock]):
- importlib.import_module(pkg_name)
- module = importlib.import_module(relative_name, pkg_name)
+ self.init.import_module(pkg_name)
+ module = self.init.import_module(relative_name, pkg_name)
self.assertEqual(module.__name__, absolute_name)
def test_deep_relative_package_import(self):
modules = ['a.__init__', 'a.b.__init__', 'a.c']
with util.mock_modules(*modules) as mock:
with util.import_state(meta_path=[mock]):
- importlib.import_module('a')
- importlib.import_module('a.b')
- module = importlib.import_module('..c', 'a.b')
+ self.init.import_module('a')
+ self.init.import_module('a.b')
+ module = self.init.import_module('..c', 'a.b')
self.assertEqual(module.__name__, 'a.c')
def test_absolute_import_with_package(self):
@@ -59,15 +63,15 @@ class ImportModuleTests(unittest.TestCase):
name = '{0}.mod'.format(pkg_name)
with util.mock_modules(pkg_long_name, name) as mock:
with util.import_state(meta_path=[mock]):
- importlib.import_module(pkg_name)
- module = importlib.import_module(name, pkg_name)
+ self.init.import_module(pkg_name)
+ module = self.init.import_module(name, pkg_name)
self.assertEqual(module.__name__, name)
def test_relative_import_wo_package(self):
# Relative imports cannot happen without the 'package' argument being
# set.
with self.assertRaises(TypeError):
- importlib.import_module('.support')
+ self.init.import_module('.support')
def test_loaded_once(self):
@@ -76,7 +80,7 @@ class ImportModuleTests(unittest.TestCase):
# module currently being imported.
b_load_count = 0
def load_a():
- importlib.import_module('a.b')
+ self.init.import_module('a.b')
def load_b():
nonlocal b_load_count
b_load_count += 1
@@ -84,11 +88,17 @@ class ImportModuleTests(unittest.TestCase):
modules = ['a.__init__', 'a.b']
with util.mock_modules(*modules, module_code=code) as mock:
with util.import_state(meta_path=[mock]):
- importlib.import_module('a.b')
+ self.init.import_module('a.b')
self.assertEqual(b_load_count, 1)
+class Frozen_ImportModuleTests(ImportModuleTests, unittest.TestCase):
+ init = frozen_init
+
+class Source_ImportModuleTests(ImportModuleTests, unittest.TestCase):
+ init = source_init
-class FindLoaderTests(unittest.TestCase):
+
+class FindLoaderTests:
class FakeMetaFinder:
@staticmethod
@@ -98,29 +108,51 @@ class FindLoaderTests(unittest.TestCase):
# If a module with __loader__ is in sys.modules, then return it.
name = 'some_mod'
with util.uncache(name):
- module = imp.new_module(name)
+ module = types.ModuleType(name)
loader = 'a loader!'
module.__loader__ = loader
sys.modules[name] = module
- found = importlib.find_loader(name)
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ found = self.init.find_loader(name)
self.assertEqual(loader, found)
def test_sys_modules_loader_is_None(self):
# If sys.modules[name].__loader__ is None, raise ValueError.
name = 'some_mod'
with util.uncache(name):
- module = imp.new_module(name)
+ module = types.ModuleType(name)
module.__loader__ = None
sys.modules[name] = module
with self.assertRaises(ValueError):
- importlib.find_loader(name)
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ self.init.find_loader(name)
+
+ def test_sys_modules_loader_is_not_set(self):
+ # Should raise ValueError
+ # Issue #17099
+ name = 'some_mod'
+ with util.uncache(name):
+ module = types.ModuleType(name)
+ try:
+ del module.__loader__
+ except AttributeError:
+ pass
+ sys.modules[name] = module
+ with self.assertRaises(ValueError):
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ self.init.find_loader(name)
def test_success(self):
# Return the loader found on sys.meta_path.
name = 'some_mod'
with util.uncache(name):
with util.import_state(meta_path=[self.FakeMetaFinder]):
- self.assertEqual((name, None), importlib.find_loader(name))
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ self.assertEqual((name, None), self.init.find_loader(name))
def test_success_path(self):
# Searching on a path should work.
@@ -128,15 +160,201 @@ class FindLoaderTests(unittest.TestCase):
path = 'path to some place'
with util.uncache(name):
with util.import_state(meta_path=[self.FakeMetaFinder]):
- self.assertEqual((name, path),
- importlib.find_loader(name, path))
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ self.assertEqual((name, path),
+ self.init.find_loader(name, path))
def test_nothing(self):
# None is returned upon failure to find a loader.
- self.assertIsNone(importlib.find_loader('nevergoingtofindthismodule'))
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ self.assertIsNone(self.init.find_loader('nevergoingtofindthismodule'))
+
+class Frozen_FindLoaderTests(FindLoaderTests, unittest.TestCase):
+ init = frozen_init
+
+class Source_FindLoaderTests(FindLoaderTests, unittest.TestCase):
+ init = source_init
-class InvalidateCacheTests(unittest.TestCase):
+class ReloadTests:
+
+ """Test module reloading for builtin and extension modules."""
+
+ def test_reload_modules(self):
+ for mod in ('tokenize', 'time', 'marshal'):
+ with self.subTest(module=mod):
+ with support.CleanImport(mod):
+ module = self.init.import_module(mod)
+ self.init.reload(module)
+
+ def test_module_replaced(self):
+ def code():
+ import sys
+ module = type(sys)('top_level')
+ module.spam = 3
+ sys.modules['top_level'] = module
+ mock = util.mock_modules('top_level',
+ module_code={'top_level': code})
+ with mock:
+ with util.import_state(meta_path=[mock]):
+ module = self.init.import_module('top_level')
+ reloaded = self.init.reload(module)
+ actual = sys.modules['top_level']
+ self.assertEqual(actual.spam, 3)
+ self.assertEqual(reloaded.spam, 3)
+
+ def test_reload_missing_loader(self):
+ with support.CleanImport('types'):
+ import types
+ loader = types.__loader__
+ del types.__loader__
+ reloaded = self.init.reload(types)
+
+ self.assertIs(reloaded, types)
+ self.assertIs(sys.modules['types'], types)
+ self.assertEqual(reloaded.__loader__.path, loader.path)
+
+ def test_reload_loader_replaced(self):
+ with support.CleanImport('types'):
+ import types
+ types.__loader__ = None
+ self.init.invalidate_caches()
+ reloaded = self.init.reload(types)
+
+ self.assertIsNot(reloaded.__loader__, None)
+ self.assertIs(reloaded, types)
+ self.assertIs(sys.modules['types'], types)
+
+ def test_reload_location_changed(self):
+ name = 'spam'
+ with support.temp_cwd(None) as cwd:
+ with util.uncache('spam'):
+ with support.DirsOnSysPath(cwd):
+ # Start as a plain module.
+ self.init.invalidate_caches()
+ path = os.path.join(cwd, name + '.py')
+ cached = self.util.cache_from_source(path)
+ expected = {'__name__': name,
+ '__package__': '',
+ '__file__': path,
+ '__cached__': cached,
+ '__doc__': None,
+ }
+ support.create_empty_file(path)
+ module = self.init.import_module(name)
+ ns = vars(module).copy()
+ loader = ns.pop('__loader__')
+ spec = ns.pop('__spec__')
+ ns.pop('__builtins__', None) # An implementation detail.
+ self.assertEqual(spec.name, name)
+ self.assertEqual(spec.loader, loader)
+ self.assertEqual(loader.path, path)
+ self.assertEqual(ns, expected)
+
+ # Change to a package.
+ self.init.invalidate_caches()
+ init_path = os.path.join(cwd, name, '__init__.py')
+ cached = self.util.cache_from_source(init_path)
+ expected = {'__name__': name,
+ '__package__': name,
+ '__file__': init_path,
+ '__cached__': cached,
+ '__path__': [os.path.dirname(init_path)],
+ '__doc__': None,
+ }
+ os.mkdir(name)
+ os.rename(path, init_path)
+ reloaded = self.init.reload(module)
+ ns = vars(reloaded).copy()
+ loader = ns.pop('__loader__')
+ spec = ns.pop('__spec__')
+ ns.pop('__builtins__', None) # An implementation detail.
+ self.assertEqual(spec.name, name)
+ self.assertEqual(spec.loader, loader)
+ self.assertIs(reloaded, module)
+ self.assertEqual(loader.path, init_path)
+ self.maxDiff = None
+ self.assertEqual(ns, expected)
+
+ def test_reload_namespace_changed(self):
+ name = 'spam'
+ with support.temp_cwd(None) as cwd:
+ with util.uncache('spam'):
+ with support.DirsOnSysPath(cwd):
+ # Start as a namespace package.
+ self.init.invalidate_caches()
+ bad_path = os.path.join(cwd, name, '__init.py')
+ cached = self.util.cache_from_source(bad_path)
+ expected = {'__name__': name,
+ '__package__': name,
+ '__doc__': None,
+ }
+ os.mkdir(name)
+ with open(bad_path, 'w') as init_file:
+ init_file.write('eggs = None')
+ module = self.init.import_module(name)
+ ns = vars(module).copy()
+ loader = ns.pop('__loader__')
+ path = ns.pop('__path__')
+ spec = ns.pop('__spec__')
+ ns.pop('__builtins__', None) # An implementation detail.
+ self.assertEqual(spec.name, name)
+ self.assertIs(spec.loader, None)
+ self.assertIsNot(loader, None)
+ self.assertEqual(set(path),
+ set([os.path.dirname(bad_path)]))
+ with self.assertRaises(AttributeError):
+ # a NamespaceLoader
+ loader.path
+ self.assertEqual(ns, expected)
+
+ # Change to a regular package.
+ self.init.invalidate_caches()
+ init_path = os.path.join(cwd, name, '__init__.py')
+ cached = self.util.cache_from_source(init_path)
+ expected = {'__name__': name,
+ '__package__': name,
+ '__file__': init_path,
+ '__cached__': cached,
+ '__path__': [os.path.dirname(init_path)],
+ '__doc__': None,
+ 'eggs': None,
+ }
+ os.rename(bad_path, init_path)
+ reloaded = self.init.reload(module)
+ ns = vars(reloaded).copy()
+ loader = ns.pop('__loader__')
+ spec = ns.pop('__spec__')
+ ns.pop('__builtins__', None) # An implementation detail.
+ self.assertEqual(spec.name, name)
+ self.assertEqual(spec.loader, loader)
+ self.assertIs(reloaded, module)
+ self.assertEqual(loader.path, init_path)
+ self.assertEqual(ns, expected)
+
+ def test_reload_submodule(self):
+ # See #19851.
+ name = 'spam'
+ subname = 'ham'
+ with util.temp_module(name, pkg=True) as pkg_dir:
+ fullname, _ = util.submodule(name, subname, pkg_dir)
+ ham = self.init.import_module(fullname)
+ reloaded = self.init.reload(ham)
+ self.assertIs(reloaded, ham)
+
+
+class Frozen_ReloadTests(ReloadTests, unittest.TestCase):
+ init = frozen_init
+ util = frozen_util
+
+class Source_ReloadTests(ReloadTests, unittest.TestCase):
+ init = source_init
+ util = source_util
+
+
+class InvalidateCacheTests:
def test_method_called(self):
# If defined the method should be called.
@@ -155,48 +373,65 @@ class InvalidateCacheTests(unittest.TestCase):
self.addCleanup(lambda: sys.path_importer_cache.__delitem__(key))
sys.path_importer_cache[key] = path_ins
self.addCleanup(lambda: sys.meta_path.remove(meta_ins))
- importlib.invalidate_caches()
+ self.init.invalidate_caches()
self.assertTrue(meta_ins.called)
self.assertTrue(path_ins.called)
def test_method_lacking(self):
# There should be no issues if the method is not defined.
key = 'gobbledeegook'
- sys.path_importer_cache[key] = imp.NullImporter('abc')
+ sys.path_importer_cache[key] = None
self.addCleanup(lambda: sys.path_importer_cache.__delitem__(key))
- importlib.invalidate_caches() # Shouldn't trigger an exception.
+ self.init.invalidate_caches() # Shouldn't trigger an exception.
+
+class Frozen_InvalidateCacheTests(InvalidateCacheTests, unittest.TestCase):
+ init = frozen_init
+
+class Source_InvalidateCacheTests(InvalidateCacheTests, unittest.TestCase):
+ init = source_init
class FrozenImportlibTests(unittest.TestCase):
def test_no_frozen_importlib(self):
# Should be able to import w/o _frozen_importlib being defined.
- module = support.import_fresh_module('importlib', blocked=['_frozen_importlib'])
- self.assertFalse(isinstance(module.__loader__,
- machinery.FrozenImporter))
+ # Can't do an isinstance() check since separate copies of importlib
+ # may have been used for import, so just check the name is not for the
+ # frozen loader.
+ self.assertNotEqual(source_init.__loader__.__class__.__name__,
+ 'FrozenImporter')
-class StartupTests(unittest.TestCase):
+class StartupTests:
def test_everyone_has___loader__(self):
# Issue #17098: all modules should have __loader__ defined.
for name, module in sys.modules.items():
if isinstance(module, types.ModuleType):
- if name in sys.builtin_module_names:
- self.assertEqual(importlib.machinery.BuiltinImporter,
- module.__loader__)
- elif imp.is_frozen(name):
- self.assertEqual(importlib.machinery.FrozenImporter,
- module.__loader__)
-
-def test_main():
- from test.support import run_unittest
- run_unittest(ImportModuleTests,
- FindLoaderTests,
- InvalidateCacheTests,
- FrozenImportlibTests,
- StartupTests)
+ with self.subTest(name=name):
+ self.assertTrue(hasattr(module, '__loader__'),
+ '{!r} lacks a __loader__ attribute'.format(name))
+ if self.machinery.BuiltinImporter.find_module(name):
+ self.assertIsNot(module.__loader__, None)
+ elif self.machinery.FrozenImporter.find_module(name):
+ self.assertIsNot(module.__loader__, None)
+
+ def test_everyone_has___spec__(self):
+ for name, module in sys.modules.items():
+ if isinstance(module, types.ModuleType):
+ with self.subTest(name=name):
+ self.assertTrue(hasattr(module, '__spec__'))
+ if self.machinery.BuiltinImporter.find_module(name):
+ self.assertIsNot(module.__spec__, None)
+ elif self.machinery.FrozenImporter.find_module(name):
+ self.assertIsNot(module.__spec__, None)
+
+class Frozen_StartupTests(StartupTests, unittest.TestCase):
+ machinery = frozen_machinery
+
+class Source_StartupTests(StartupTests, unittest.TestCase):
+ machinery = source_machinery
if __name__ == '__main__':
- test_main()
+ unittest.main()
diff --git a/Lib/test/test_importlib/test_locks.py b/Lib/test/test_importlib/test_locks.py
index c373b11256..dc97ba1567 100644
--- a/Lib/test/test_importlib/test_locks.py
+++ b/Lib/test/test_importlib/test_locks.py
@@ -1,4 +1,8 @@
-from importlib import _bootstrap
+from . import util
+frozen_init, source_init = util.import_importlib('importlib')
+frozen_bootstrap = frozen_init._bootstrap
+source_bootstrap = source_init._bootstrap
+
import sys
import time
import unittest
@@ -13,14 +17,9 @@ except ImportError:
else:
from test import lock_tests
-
-LockType = _bootstrap._ModuleLock
-DeadlockError = _bootstrap._DeadlockError
-
-
if threading is not None:
- class ModuleLockAsRLockTests(lock_tests.RLockTests):
- locktype = staticmethod(lambda: LockType("some_lock"))
+ class ModuleLockAsRLockTests:
+ locktype = classmethod(lambda cls: cls.LockType("some_lock"))
# _is_owned() unsupported
test__is_owned = None
@@ -34,13 +33,21 @@ if threading is not None:
# _release_save() unsupported
test_release_save_unacquired = None
+ class Frozen_ModuleLockAsRLockTests(ModuleLockAsRLockTests, lock_tests.RLockTests):
+ LockType = frozen_bootstrap._ModuleLock
+
+ class Source_ModuleLockAsRLockTests(ModuleLockAsRLockTests, lock_tests.RLockTests):
+ LockType = source_bootstrap._ModuleLock
+
else:
- class ModuleLockAsRLockTests(unittest.TestCase):
+ class Frozen_ModuleLockAsRLockTests(unittest.TestCase):
pass
+ class Source_ModuleLockAsRLockTests(unittest.TestCase):
+ pass
-@unittest.skipUnless(threading, "threads needed for this test")
-class DeadlockAvoidanceTests(unittest.TestCase):
+
+class DeadlockAvoidanceTests:
def setUp(self):
try:
@@ -55,7 +62,7 @@ class DeadlockAvoidanceTests(unittest.TestCase):
def run_deadlock_avoidance_test(self, create_deadlock):
NLOCKS = 10
- locks = [LockType(str(i)) for i in range(NLOCKS)]
+ locks = [self.LockType(str(i)) for i in range(NLOCKS)]
pairs = [(locks[i], locks[(i+1)%NLOCKS]) for i in range(NLOCKS)]
if create_deadlock:
NTHREADS = NLOCKS
@@ -67,7 +74,7 @@ class DeadlockAvoidanceTests(unittest.TestCase):
"""Try to acquire the lock. Return True on success, False on deadlock."""
try:
lock.acquire()
- except DeadlockError:
+ except self.DeadlockError:
return False
else:
return True
@@ -99,30 +106,50 @@ class DeadlockAvoidanceTests(unittest.TestCase):
self.assertEqual(results.count((True, False)), 0)
self.assertEqual(results.count((True, True)), len(results))
+@unittest.skipUnless(threading, "threads needed for this test")
+class Frozen_DeadlockAvoidanceTests(DeadlockAvoidanceTests, unittest.TestCase):
+ LockType = frozen_bootstrap._ModuleLock
+ DeadlockError = frozen_bootstrap._DeadlockError
+
+@unittest.skipUnless(threading, "threads needed for this test")
+class Source_DeadlockAvoidanceTests(DeadlockAvoidanceTests, unittest.TestCase):
+ LockType = source_bootstrap._ModuleLock
+ DeadlockError = source_bootstrap._DeadlockError
-class LifetimeTests(unittest.TestCase):
+
+class LifetimeTests:
def test_lock_lifetime(self):
name = "xyzzy"
- self.assertNotIn(name, _bootstrap._module_locks)
- lock = _bootstrap._get_module_lock(name)
- self.assertIn(name, _bootstrap._module_locks)
+ self.assertNotIn(name, self.bootstrap._module_locks)
+ lock = self.bootstrap._get_module_lock(name)
+ self.assertIn(name, self.bootstrap._module_locks)
wr = weakref.ref(lock)
del lock
support.gc_collect()
- self.assertNotIn(name, _bootstrap._module_locks)
+ self.assertNotIn(name, self.bootstrap._module_locks)
self.assertIsNone(wr())
def test_all_locks(self):
support.gc_collect()
- self.assertEqual(0, len(_bootstrap._module_locks), _bootstrap._module_locks)
+ self.assertEqual(0, len(self.bootstrap._module_locks),
+ self.bootstrap._module_locks)
+
+class Frozen_LifetimeTests(LifetimeTests, unittest.TestCase):
+ bootstrap = frozen_bootstrap
+
+class Source_LifetimeTests(LifetimeTests, unittest.TestCase):
+ bootstrap = source_bootstrap
@support.reap_threads
def test_main():
- support.run_unittest(ModuleLockAsRLockTests,
- DeadlockAvoidanceTests,
- LifetimeTests)
+ support.run_unittest(Frozen_ModuleLockAsRLockTests,
+ Source_ModuleLockAsRLockTests,
+ Frozen_DeadlockAvoidanceTests,
+ Source_DeadlockAvoidanceTests,
+ Frozen_LifetimeTests,
+ Source_LifetimeTests)
if __name__ == '__main__':
diff --git a/Lib/test/test_importlib/test_namespace_pkgs.py b/Lib/test/test_importlib/test_namespace_pkgs.py
new file mode 100644
index 0000000000..6639612631
--- /dev/null
+++ b/Lib/test/test_importlib/test_namespace_pkgs.py
@@ -0,0 +1,293 @@
+import contextlib
+import importlib.abc
+import importlib.machinery
+import os
+import sys
+import types
+import unittest
+
+from test.test_importlib import util
+from test.support import run_unittest
+
+# needed tests:
+#
+# need to test when nested, so that the top-level path isn't sys.path
+# need to test dynamic path detection, both at top-level and nested
+# with dynamic path, check when a loader is returned on path reload (that is,
+# trying to switch from a namespace package to a regular package)
+
+
+@contextlib.contextmanager
+def sys_modules_context():
+ """
+ Make sure sys.modules is the same object and has the same content
+ when exiting the context as when entering.
+
+ Similar to importlib.test.util.uncache, but doesn't require explicit
+ names.
+ """
+ sys_modules_saved = sys.modules
+ sys_modules_copy = sys.modules.copy()
+ try:
+ yield
+ finally:
+ sys.modules = sys_modules_saved
+ sys.modules.clear()
+ sys.modules.update(sys_modules_copy)
+
+
+@contextlib.contextmanager
+def namespace_tree_context(**kwargs):
+ """
+ Save import state and sys.modules cache and restore it on exit.
+ Typical usage:
+
+ >>> with namespace_tree_context(path=['/tmp/xxyy/portion1',
+ ... '/tmp/xxyy/portion2']):
+ ... pass
+ """
+ # use default meta_path and path_hooks unless specified otherwise
+ kwargs.setdefault('meta_path', sys.meta_path)
+ kwargs.setdefault('path_hooks', sys.path_hooks)
+ import_context = util.import_state(**kwargs)
+ with import_context, sys_modules_context():
+ yield
+
+class NamespacePackageTest(unittest.TestCase):
+ """
+ Subclasses should define self.root and self.paths (under that root)
+ to be added to sys.path.
+ """
+ root = os.path.join(os.path.dirname(__file__), 'namespace_pkgs')
+
+ def setUp(self):
+ self.resolved_paths = [
+ os.path.join(self.root, path) for path in self.paths
+ ]
+ self.ctx = namespace_tree_context(path=self.resolved_paths)
+ self.ctx.__enter__()
+
+ def tearDown(self):
+ # TODO: will we ever want to pass exc_info to __exit__?
+ self.ctx.__exit__(None, None, None)
+
+class SingleNamespacePackage(NamespacePackageTest):
+ paths = ['portion1']
+
+ def test_simple_package(self):
+ import foo.one
+ self.assertEqual(foo.one.attr, 'portion1 foo one')
+
+ def test_cant_import_other(self):
+ with self.assertRaises(ImportError):
+ import foo.two
+
+ def test_module_repr(self):
+ import foo.one
+ self.assertEqual(repr(foo), "<module 'foo' (namespace)>")
+
+
+class DynamicPatheNamespacePackage(NamespacePackageTest):
+ paths = ['portion1']
+
+ def test_dynamic_path(self):
+ # Make sure only 'foo.one' can be imported
+ import foo.one
+ self.assertEqual(foo.one.attr, 'portion1 foo one')
+
+ with self.assertRaises(ImportError):
+ import foo.two
+
+ # Now modify sys.path
+ sys.path.append(os.path.join(self.root, 'portion2'))
+
+ # And make sure foo.two is now importable
+ import foo.two
+ self.assertEqual(foo.two.attr, 'portion2 foo two')
+
+
+class CombinedNamespacePackages(NamespacePackageTest):
+ paths = ['both_portions']
+
+ def test_imports(self):
+ import foo.one
+ import foo.two
+ self.assertEqual(foo.one.attr, 'both_portions foo one')
+ self.assertEqual(foo.two.attr, 'both_portions foo two')
+
+
+class SeparatedNamespacePackages(NamespacePackageTest):
+ paths = ['portion1', 'portion2']
+
+ def test_imports(self):
+ import foo.one
+ import foo.two
+ self.assertEqual(foo.one.attr, 'portion1 foo one')
+ self.assertEqual(foo.two.attr, 'portion2 foo two')
+
+
+class SeparatedOverlappingNamespacePackages(NamespacePackageTest):
+ paths = ['portion1', 'both_portions']
+
+ def test_first_path_wins(self):
+ import foo.one
+ import foo.two
+ self.assertEqual(foo.one.attr, 'portion1 foo one')
+ self.assertEqual(foo.two.attr, 'both_portions foo two')
+
+ def test_first_path_wins_again(self):
+ sys.path.reverse()
+ import foo.one
+ import foo.two
+ self.assertEqual(foo.one.attr, 'both_portions foo one')
+ self.assertEqual(foo.two.attr, 'both_portions foo two')
+
+ def test_first_path_wins_importing_second_first(self):
+ import foo.two
+ import foo.one
+ self.assertEqual(foo.one.attr, 'portion1 foo one')
+ self.assertEqual(foo.two.attr, 'both_portions foo two')
+
+
+class SingleZipNamespacePackage(NamespacePackageTest):
+ paths = ['top_level_portion1.zip']
+
+ def test_simple_package(self):
+ import foo.one
+ self.assertEqual(foo.one.attr, 'portion1 foo one')
+
+ def test_cant_import_other(self):
+ with self.assertRaises(ImportError):
+ import foo.two
+
+
+class SeparatedZipNamespacePackages(NamespacePackageTest):
+ paths = ['top_level_portion1.zip', 'portion2']
+
+ def test_imports(self):
+ import foo.one
+ import foo.two
+ self.assertEqual(foo.one.attr, 'portion1 foo one')
+ self.assertEqual(foo.two.attr, 'portion2 foo two')
+ self.assertIn('top_level_portion1.zip', foo.one.__file__)
+ self.assertNotIn('.zip', foo.two.__file__)
+
+
+class SingleNestedZipNamespacePackage(NamespacePackageTest):
+ paths = ['nested_portion1.zip/nested_portion1']
+
+ def test_simple_package(self):
+ import foo.one
+ self.assertEqual(foo.one.attr, 'portion1 foo one')
+
+ def test_cant_import_other(self):
+ with self.assertRaises(ImportError):
+ import foo.two
+
+
+class SeparatedNestedZipNamespacePackages(NamespacePackageTest):
+ paths = ['nested_portion1.zip/nested_portion1', 'portion2']
+
+ def test_imports(self):
+ import foo.one
+ import foo.two
+ self.assertEqual(foo.one.attr, 'portion1 foo one')
+ self.assertEqual(foo.two.attr, 'portion2 foo two')
+ fn = os.path.join('nested_portion1.zip', 'nested_portion1')
+ self.assertIn(fn, foo.one.__file__)
+ self.assertNotIn('.zip', foo.two.__file__)
+
+
+class LegacySupport(NamespacePackageTest):
+ paths = ['not_a_namespace_pkg', 'portion1', 'portion2', 'both_portions']
+
+ def test_non_namespace_package_takes_precedence(self):
+ import foo.one
+ with self.assertRaises(ImportError):
+ import foo.two
+ self.assertIn('__init__', foo.__file__)
+ self.assertNotIn('namespace', str(foo.__loader__).lower())
+
+
+class DynamicPathCalculation(NamespacePackageTest):
+ paths = ['project1', 'project2']
+
+ def test_project3_fails(self):
+ import parent.child.one
+ self.assertEqual(len(parent.__path__), 2)
+ self.assertEqual(len(parent.child.__path__), 2)
+ import parent.child.two
+ self.assertEqual(len(parent.__path__), 2)
+ self.assertEqual(len(parent.child.__path__), 2)
+
+ self.assertEqual(parent.child.one.attr, 'parent child one')
+ self.assertEqual(parent.child.two.attr, 'parent child two')
+
+ with self.assertRaises(ImportError):
+ import parent.child.three
+
+ self.assertEqual(len(parent.__path__), 2)
+ self.assertEqual(len(parent.child.__path__), 2)
+
+ def test_project3_succeeds(self):
+ import parent.child.one
+ self.assertEqual(len(parent.__path__), 2)
+ self.assertEqual(len(parent.child.__path__), 2)
+ import parent.child.two
+ self.assertEqual(len(parent.__path__), 2)
+ self.assertEqual(len(parent.child.__path__), 2)
+
+ self.assertEqual(parent.child.one.attr, 'parent child one')
+ self.assertEqual(parent.child.two.attr, 'parent child two')
+
+ with self.assertRaises(ImportError):
+ import parent.child.three
+
+ # now add project3
+ sys.path.append(os.path.join(self.root, 'project3'))
+ import parent.child.three
+
+ # the paths dynamically get longer, to include the new directories
+ self.assertEqual(len(parent.__path__), 3)
+ self.assertEqual(len(parent.child.__path__), 3)
+
+ self.assertEqual(parent.child.three.attr, 'parent child three')
+
+
+class ZipWithMissingDirectory(NamespacePackageTest):
+ paths = ['missing_directory.zip']
+
+ @unittest.expectedFailure
+ def test_missing_directory(self):
+ # This will fail because missing_directory.zip contains:
+ # Length Date Time Name
+ # --------- ---------- ----- ----
+ # 29 2012-05-03 18:13 foo/one.py
+ # 0 2012-05-03 20:57 bar/
+ # 38 2012-05-03 20:57 bar/two.py
+ # --------- -------
+ # 67 3 files
+
+ # Because there is no 'foo/', the zipimporter currently doesn't
+ # know that foo is a namespace package
+
+ import foo.one
+
+ def test_present_directory(self):
+ # This succeeds because there is a "bar/" in the zip file
+ import bar.two
+ self.assertEqual(bar.two.attr, 'missing_directory foo two')
+
+
+class ModuleAndNamespacePackageInSameDir(NamespacePackageTest):
+ paths = ['module_and_namespace_package']
+
+ def test_module_before_namespace_package(self):
+ # Make sure we find the module in preference to the
+ # namespace package.
+ import a_test
+ self.assertEqual(a_test.attr, 'in module')
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/Lib/test/test_importlib/test_spec.py b/Lib/test/test_importlib/test_spec.py
new file mode 100644
index 0000000000..71541f692e
--- /dev/null
+++ b/Lib/test/test_importlib/test_spec.py
@@ -0,0 +1,957 @@
+from . import util
+
+frozen_init, source_init = util.import_importlib('importlib')
+frozen_bootstrap = frozen_init._bootstrap
+source_bootstrap = source_init._bootstrap
+frozen_machinery, source_machinery = util.import_importlib('importlib.machinery')
+frozen_util, source_util = util.import_importlib('importlib.util')
+
+import os.path
+from test.support import CleanImport
+import unittest
+import sys
+import warnings
+
+
+
+class TestLoader:
+
+ def __init__(self, path=None, is_package=None):
+ self.path = path
+ self.package = is_package
+
+ def __repr__(self):
+ return '<TestLoader object>'
+
+ def __getattr__(self, name):
+ if name == 'get_filename' and self.path is not None:
+ return self._get_filename
+ if name == 'is_package':
+ return self._is_package
+ raise AttributeError(name)
+
+ def _get_filename(self, name):
+ return self.path
+
+ def _is_package(self, name):
+ return self.package
+
+
+class NewLoader(TestLoader):
+
+ EGGS = 1
+
+ def exec_module(self, module):
+ module.eggs = self.EGGS
+
+
+class LegacyLoader(TestLoader):
+
+ HAM = -1
+
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore", DeprecationWarning)
+
+ @frozen_util.module_for_loader
+ def load_module(self, module):
+ module.ham = self.HAM
+ return module
+
+
+class ModuleSpecTests:
+
+ def setUp(self):
+ self.name = 'spam'
+ self.path = 'spam.py'
+ self.cached = self.util.cache_from_source(self.path)
+ self.loader = TestLoader()
+ self.spec = self.machinery.ModuleSpec(self.name, self.loader)
+ self.loc_spec = self.machinery.ModuleSpec(self.name, self.loader,
+ origin=self.path)
+ self.loc_spec._set_fileattr = True
+
+ def test_default(self):
+ spec = self.machinery.ModuleSpec(self.name, self.loader)
+
+ self.assertEqual(spec.name, self.name)
+ self.assertEqual(spec.loader, self.loader)
+ self.assertIs(spec.origin, None)
+ self.assertIs(spec.loader_state, None)
+ self.assertIs(spec.submodule_search_locations, None)
+ self.assertIs(spec.cached, None)
+ self.assertFalse(spec.has_location)
+
+ def test_default_no_loader(self):
+ spec = self.machinery.ModuleSpec(self.name, None)
+
+ self.assertEqual(spec.name, self.name)
+ self.assertIs(spec.loader, None)
+ self.assertIs(spec.origin, None)
+ self.assertIs(spec.loader_state, None)
+ self.assertIs(spec.submodule_search_locations, None)
+ self.assertIs(spec.cached, None)
+ self.assertFalse(spec.has_location)
+
+ def test_default_is_package_false(self):
+ spec = self.machinery.ModuleSpec(self.name, self.loader,
+ is_package=False)
+
+ self.assertEqual(spec.name, self.name)
+ self.assertEqual(spec.loader, self.loader)
+ self.assertIs(spec.origin, None)
+ self.assertIs(spec.loader_state, None)
+ self.assertIs(spec.submodule_search_locations, None)
+ self.assertIs(spec.cached, None)
+ self.assertFalse(spec.has_location)
+
+ def test_default_is_package_true(self):
+ spec = self.machinery.ModuleSpec(self.name, self.loader,
+ is_package=True)
+
+ self.assertEqual(spec.name, self.name)
+ self.assertEqual(spec.loader, self.loader)
+ self.assertIs(spec.origin, None)
+ self.assertIs(spec.loader_state, None)
+ self.assertEqual(spec.submodule_search_locations, [])
+ self.assertIs(spec.cached, None)
+ self.assertFalse(spec.has_location)
+
+ def test_has_location_setter(self):
+ spec = self.machinery.ModuleSpec(self.name, self.loader,
+ origin='somewhere')
+ self.assertFalse(spec.has_location)
+ spec.has_location = True
+ self.assertTrue(spec.has_location)
+
+ def test_equality(self):
+ other = type(sys.implementation)(name=self.name,
+ loader=self.loader,
+ origin=None,
+ submodule_search_locations=None,
+ has_location=False,
+ cached=None,
+ )
+
+ self.assertTrue(self.spec == other)
+
+ def test_equality_location(self):
+ other = type(sys.implementation)(name=self.name,
+ loader=self.loader,
+ origin=self.path,
+ submodule_search_locations=None,
+ has_location=True,
+ cached=self.cached,
+ )
+
+ self.assertEqual(self.loc_spec, other)
+
+ def test_inequality(self):
+ other = type(sys.implementation)(name='ham',
+ loader=self.loader,
+ origin=None,
+ submodule_search_locations=None,
+ has_location=False,
+ cached=None,
+ )
+
+ self.assertNotEqual(self.spec, other)
+
+ def test_inequality_incomplete(self):
+ other = type(sys.implementation)(name=self.name,
+ loader=self.loader,
+ )
+
+ self.assertNotEqual(self.spec, other)
+
+ def test_package(self):
+ spec = self.machinery.ModuleSpec('spam.eggs', self.loader)
+
+ self.assertEqual(spec.parent, 'spam')
+
+ def test_package_is_package(self):
+ spec = self.machinery.ModuleSpec('spam.eggs', self.loader,
+ is_package=True)
+
+ self.assertEqual(spec.parent, 'spam.eggs')
+
+ # cached
+
+ def test_cached_set(self):
+ before = self.spec.cached
+ self.spec.cached = 'there'
+ after = self.spec.cached
+
+ self.assertIs(before, None)
+ self.assertEqual(after, 'there')
+
+ def test_cached_no_origin(self):
+ spec = self.machinery.ModuleSpec(self.name, self.loader)
+
+ self.assertIs(spec.cached, None)
+
+ def test_cached_with_origin_not_location(self):
+ spec = self.machinery.ModuleSpec(self.name, self.loader,
+ origin=self.path)
+
+ self.assertIs(spec.cached, None)
+
+ def test_cached_source(self):
+ expected = self.util.cache_from_source(self.path)
+
+ self.assertEqual(self.loc_spec.cached, expected)
+
+ def test_cached_source_unknown_suffix(self):
+ self.loc_spec.origin = 'spam.spamspamspam'
+
+ self.assertIs(self.loc_spec.cached, None)
+
+ def test_cached_source_missing_cache_tag(self):
+ original = sys.implementation.cache_tag
+ sys.implementation.cache_tag = None
+ try:
+ cached = self.loc_spec.cached
+ finally:
+ sys.implementation.cache_tag = original
+
+ self.assertIs(cached, None)
+
+ def test_cached_sourceless(self):
+ self.loc_spec.origin = 'spam.pyc'
+
+ self.assertEqual(self.loc_spec.cached, 'spam.pyc')
+
+
+class Frozen_ModuleSpecTests(ModuleSpecTests, unittest.TestCase):
+ util = frozen_util
+ machinery = frozen_machinery
+
+
+class Source_ModuleSpecTests(ModuleSpecTests, unittest.TestCase):
+ util = source_util
+ machinery = source_machinery
+
+
+class ModuleSpecMethodsTests:
+
+ def setUp(self):
+ self.name = 'spam'
+ self.path = 'spam.py'
+ self.cached = self.util.cache_from_source(self.path)
+ self.loader = TestLoader()
+ self.spec = self.machinery.ModuleSpec(self.name, self.loader)
+ self.loc_spec = self.machinery.ModuleSpec(self.name, self.loader,
+ origin=self.path)
+ self.loc_spec._set_fileattr = True
+
+ # init_module_attrs
+
+ def test_init_module_attrs(self):
+ module = type(sys)(self.name)
+ spec = self.machinery.ModuleSpec(self.name, self.loader)
+ self.bootstrap._SpecMethods(spec).init_module_attrs(module)
+
+ self.assertEqual(module.__name__, spec.name)
+ self.assertIs(module.__loader__, spec.loader)
+ self.assertEqual(module.__package__, spec.parent)
+ self.assertIs(module.__spec__, spec)
+ self.assertFalse(hasattr(module, '__path__'))
+ self.assertFalse(hasattr(module, '__file__'))
+ self.assertFalse(hasattr(module, '__cached__'))
+
+ def test_init_module_attrs_package(self):
+ module = type(sys)(self.name)
+ spec = self.machinery.ModuleSpec(self.name, self.loader)
+ spec.submodule_search_locations = ['spam', 'ham']
+ self.bootstrap._SpecMethods(spec).init_module_attrs(module)
+
+ self.assertEqual(module.__name__, spec.name)
+ self.assertIs(module.__loader__, spec.loader)
+ self.assertEqual(module.__package__, spec.parent)
+ self.assertIs(module.__spec__, spec)
+ self.assertIs(module.__path__, spec.submodule_search_locations)
+ self.assertFalse(hasattr(module, '__file__'))
+ self.assertFalse(hasattr(module, '__cached__'))
+
+ def test_init_module_attrs_location(self):
+ module = type(sys)(self.name)
+ spec = self.loc_spec
+ self.bootstrap._SpecMethods(spec).init_module_attrs(module)
+
+ self.assertEqual(module.__name__, spec.name)
+ self.assertIs(module.__loader__, spec.loader)
+ self.assertEqual(module.__package__, spec.parent)
+ self.assertIs(module.__spec__, spec)
+ self.assertFalse(hasattr(module, '__path__'))
+ self.assertEqual(module.__file__, spec.origin)
+ self.assertEqual(module.__cached__,
+ self.util.cache_from_source(spec.origin))
+
+ def test_init_module_attrs_different_name(self):
+ module = type(sys)('eggs')
+ spec = self.machinery.ModuleSpec(self.name, self.loader)
+ self.bootstrap._SpecMethods(spec).init_module_attrs(module)
+
+ self.assertEqual(module.__name__, spec.name)
+
+ def test_init_module_attrs_different_spec(self):
+ module = type(sys)(self.name)
+ module.__spec__ = self.machinery.ModuleSpec('eggs', object())
+ spec = self.machinery.ModuleSpec(self.name, self.loader)
+ self.bootstrap._SpecMethods(spec).init_module_attrs(module)
+
+ self.assertEqual(module.__name__, spec.name)
+ self.assertIs(module.__loader__, spec.loader)
+ self.assertEqual(module.__package__, spec.parent)
+ self.assertIs(module.__spec__, spec)
+
+ def test_init_module_attrs_already_set(self):
+ module = type(sys)('ham.eggs')
+ module.__loader__ = object()
+ module.__package__ = 'ham'
+ module.__path__ = ['eggs']
+ module.__file__ = 'ham/eggs/__init__.py'
+ module.__cached__ = self.util.cache_from_source(module.__file__)
+ original = vars(module).copy()
+ spec = self.loc_spec
+ spec.submodule_search_locations = ['']
+ self.bootstrap._SpecMethods(spec).init_module_attrs(module)
+
+ self.assertIs(module.__loader__, original['__loader__'])
+ self.assertEqual(module.__package__, original['__package__'])
+ self.assertIs(module.__path__, original['__path__'])
+ self.assertEqual(module.__file__, original['__file__'])
+ self.assertEqual(module.__cached__, original['__cached__'])
+
+ def test_init_module_attrs_immutable(self):
+ module = object()
+ spec = self.loc_spec
+ spec.submodule_search_locations = ['']
+ self.bootstrap._SpecMethods(spec).init_module_attrs(module)
+
+ self.assertFalse(hasattr(module, '__name__'))
+ self.assertFalse(hasattr(module, '__loader__'))
+ self.assertFalse(hasattr(module, '__package__'))
+ self.assertFalse(hasattr(module, '__spec__'))
+ self.assertFalse(hasattr(module, '__path__'))
+ self.assertFalse(hasattr(module, '__file__'))
+ self.assertFalse(hasattr(module, '__cached__'))
+
+ # create()
+
+ def test_create(self):
+ created = self.bootstrap._SpecMethods(self.spec).create()
+
+ self.assertEqual(created.__name__, self.spec.name)
+ self.assertIs(created.__loader__, self.spec.loader)
+ self.assertEqual(created.__package__, self.spec.parent)
+ self.assertIs(created.__spec__, self.spec)
+ self.assertFalse(hasattr(created, '__path__'))
+ self.assertFalse(hasattr(created, '__file__'))
+ self.assertFalse(hasattr(created, '__cached__'))
+
+ def test_create_from_loader(self):
+ module = type(sys.implementation)()
+ class CreatingLoader(TestLoader):
+ def create_module(self, spec):
+ return module
+ self.spec.loader = CreatingLoader()
+ created = self.bootstrap._SpecMethods(self.spec).create()
+
+ self.assertIs(created, module)
+ self.assertEqual(created.__name__, self.spec.name)
+ self.assertIs(created.__loader__, self.spec.loader)
+ self.assertEqual(created.__package__, self.spec.parent)
+ self.assertIs(created.__spec__, self.spec)
+ self.assertFalse(hasattr(created, '__path__'))
+ self.assertFalse(hasattr(created, '__file__'))
+ self.assertFalse(hasattr(created, '__cached__'))
+
+ def test_create_from_loader_not_handled(self):
+ class CreatingLoader(TestLoader):
+ def create_module(self, spec):
+ return None
+ self.spec.loader = CreatingLoader()
+ created = self.bootstrap._SpecMethods(self.spec).create()
+
+ self.assertEqual(created.__name__, self.spec.name)
+ self.assertIs(created.__loader__, self.spec.loader)
+ self.assertEqual(created.__package__, self.spec.parent)
+ self.assertIs(created.__spec__, self.spec)
+ self.assertFalse(hasattr(created, '__path__'))
+ self.assertFalse(hasattr(created, '__file__'))
+ self.assertFalse(hasattr(created, '__cached__'))
+
+ # exec()
+
+ def test_exec(self):
+ self.spec.loader = NewLoader()
+ module = self.bootstrap._SpecMethods(self.spec).create()
+ sys.modules[self.name] = module
+ self.assertFalse(hasattr(module, 'eggs'))
+ self.bootstrap._SpecMethods(self.spec).exec(module)
+
+ self.assertEqual(module.eggs, 1)
+
+ # load()
+
+ def test_load(self):
+ self.spec.loader = NewLoader()
+ with CleanImport(self.spec.name):
+ loaded = self.bootstrap._SpecMethods(self.spec).load()
+ installed = sys.modules[self.spec.name]
+
+ self.assertEqual(loaded.eggs, 1)
+ self.assertIs(loaded, installed)
+
+ def test_load_replaced(self):
+ replacement = object()
+ class ReplacingLoader(TestLoader):
+ def exec_module(self, module):
+ sys.modules[module.__name__] = replacement
+ self.spec.loader = ReplacingLoader()
+ with CleanImport(self.spec.name):
+ loaded = self.bootstrap._SpecMethods(self.spec).load()
+ installed = sys.modules[self.spec.name]
+
+ self.assertIs(loaded, replacement)
+ self.assertIs(installed, replacement)
+
+ def test_load_failed(self):
+ class FailedLoader(TestLoader):
+ def exec_module(self, module):
+ raise RuntimeError
+ self.spec.loader = FailedLoader()
+ with CleanImport(self.spec.name):
+ with self.assertRaises(RuntimeError):
+ loaded = self.bootstrap._SpecMethods(self.spec).load()
+ self.assertNotIn(self.spec.name, sys.modules)
+
+ def test_load_failed_removed(self):
+ class FailedLoader(TestLoader):
+ def exec_module(self, module):
+ del sys.modules[module.__name__]
+ raise RuntimeError
+ self.spec.loader = FailedLoader()
+ with CleanImport(self.spec.name):
+ with self.assertRaises(RuntimeError):
+ loaded = self.bootstrap._SpecMethods(self.spec).load()
+ self.assertNotIn(self.spec.name, sys.modules)
+
+ def test_load_legacy(self):
+ self.spec.loader = LegacyLoader()
+ with CleanImport(self.spec.name):
+ loaded = self.bootstrap._SpecMethods(self.spec).load()
+
+ self.assertEqual(loaded.ham, -1)
+
+ def test_load_legacy_attributes(self):
+ self.spec.loader = LegacyLoader()
+ with CleanImport(self.spec.name):
+ loaded = self.bootstrap._SpecMethods(self.spec).load()
+
+ self.assertIs(loaded.__loader__, self.spec.loader)
+ self.assertEqual(loaded.__package__, self.spec.parent)
+ self.assertIs(loaded.__spec__, self.spec)
+
+ def test_load_legacy_attributes_immutable(self):
+ module = object()
+ class ImmutableLoader(TestLoader):
+ def load_module(self, name):
+ sys.modules[name] = module
+ return module
+ self.spec.loader = ImmutableLoader()
+ with CleanImport(self.spec.name):
+ loaded = self.bootstrap._SpecMethods(self.spec).load()
+
+ self.assertIs(sys.modules[self.spec.name], module)
+
+ # reload()
+
+ def test_reload(self):
+ self.spec.loader = NewLoader()
+ with CleanImport(self.spec.name):
+ loaded = self.bootstrap._SpecMethods(self.spec).load()
+ reloaded = self.bootstrap._SpecMethods(self.spec).exec(loaded)
+ installed = sys.modules[self.spec.name]
+
+ self.assertEqual(loaded.eggs, 1)
+ self.assertIs(reloaded, loaded)
+ self.assertIs(installed, loaded)
+
+ def test_reload_modified(self):
+ self.spec.loader = NewLoader()
+ with CleanImport(self.spec.name):
+ loaded = self.bootstrap._SpecMethods(self.spec).load()
+ loaded.eggs = 2
+ reloaded = self.bootstrap._SpecMethods(self.spec).exec(loaded)
+
+ self.assertEqual(loaded.eggs, 1)
+ self.assertIs(reloaded, loaded)
+
+ def test_reload_extra_attributes(self):
+ self.spec.loader = NewLoader()
+ with CleanImport(self.spec.name):
+ loaded = self.bootstrap._SpecMethods(self.spec).load()
+ loaded.available = False
+ reloaded = self.bootstrap._SpecMethods(self.spec).exec(loaded)
+
+ self.assertFalse(loaded.available)
+ self.assertIs(reloaded, loaded)
+
+ def test_reload_init_module_attrs(self):
+ self.spec.loader = NewLoader()
+ with CleanImport(self.spec.name):
+ loaded = self.bootstrap._SpecMethods(self.spec).load()
+ loaded.__name__ = 'ham'
+ del loaded.__loader__
+ del loaded.__package__
+ del loaded.__spec__
+ self.bootstrap._SpecMethods(self.spec).exec(loaded)
+
+ self.assertEqual(loaded.__name__, self.spec.name)
+ self.assertIs(loaded.__loader__, self.spec.loader)
+ self.assertEqual(loaded.__package__, self.spec.parent)
+ self.assertIs(loaded.__spec__, self.spec)
+ self.assertFalse(hasattr(loaded, '__path__'))
+ self.assertFalse(hasattr(loaded, '__file__'))
+ self.assertFalse(hasattr(loaded, '__cached__'))
+
+ def test_reload_legacy(self):
+ self.spec.loader = LegacyLoader()
+ with CleanImport(self.spec.name):
+ loaded = self.bootstrap._SpecMethods(self.spec).load()
+ reloaded = self.bootstrap._SpecMethods(self.spec).exec(loaded)
+ installed = sys.modules[self.spec.name]
+
+ self.assertEqual(loaded.ham, -1)
+ self.assertIs(reloaded, loaded)
+ self.assertIs(installed, loaded)
+
+
+class Frozen_ModuleSpecMethodsTests(ModuleSpecMethodsTests, unittest.TestCase):
+ bootstrap = frozen_bootstrap
+ machinery = frozen_machinery
+ util = frozen_util
+
+
+class Source_ModuleSpecMethodsTests(ModuleSpecMethodsTests, unittest.TestCase):
+ bootstrap = source_bootstrap
+ machinery = source_machinery
+ util = source_util
+
+
+class ModuleReprTests:
+
+ def setUp(self):
+ self.module = type(os)('spam')
+ self.spec = self.machinery.ModuleSpec('spam', TestLoader())
+
+ def test_module___loader___module_repr(self):
+ class Loader:
+ def module_repr(self, module):
+ return '<delicious {}>'.format(module.__name__)
+ self.module.__loader__ = Loader()
+ modrepr = self.bootstrap._module_repr(self.module)
+
+ self.assertEqual(modrepr, '<delicious spam>')
+
+ def test_module___loader___module_repr_bad(self):
+ class Loader(TestLoader):
+ def module_repr(self, module):
+ raise Exception
+ self.module.__loader__ = Loader()
+ modrepr = self.bootstrap._module_repr(self.module)
+
+ self.assertEqual(modrepr,
+ '<module {!r} (<TestLoader object>)>'.format('spam'))
+
+ def test_module___spec__(self):
+ origin = 'in a hole, in the ground'
+ self.spec.origin = origin
+ self.module.__spec__ = self.spec
+ modrepr = self.bootstrap._module_repr(self.module)
+
+ self.assertEqual(modrepr, '<module {!r} ({})>'.format('spam', origin))
+
+ def test_module___spec___location(self):
+ location = 'in_a_galaxy_far_far_away.py'
+ self.spec.origin = location
+ self.spec._set_fileattr = True
+ self.module.__spec__ = self.spec
+ modrepr = self.bootstrap._module_repr(self.module)
+
+ self.assertEqual(modrepr,
+ '<module {!r} from {!r}>'.format('spam', location))
+
+ def test_module___spec___no_origin(self):
+ self.spec.loader = TestLoader()
+ self.module.__spec__ = self.spec
+ modrepr = self.bootstrap._module_repr(self.module)
+
+ self.assertEqual(modrepr,
+ '<module {!r} (<TestLoader object>)>'.format('spam'))
+
+ def test_module___spec___no_origin_no_loader(self):
+ self.spec.loader = None
+ self.module.__spec__ = self.spec
+ modrepr = self.bootstrap._module_repr(self.module)
+
+ self.assertEqual(modrepr, '<module {!r}>'.format('spam'))
+
+ def test_module_no_name(self):
+ del self.module.__name__
+ modrepr = self.bootstrap._module_repr(self.module)
+
+ self.assertEqual(modrepr, '<module {!r}>'.format('?'))
+
+ def test_module_with_file(self):
+ filename = 'e/i/e/i/o/spam.py'
+ self.module.__file__ = filename
+ modrepr = self.bootstrap._module_repr(self.module)
+
+ self.assertEqual(modrepr,
+ '<module {!r} from {!r}>'.format('spam', filename))
+
+ def test_module_no_file(self):
+ self.module.__loader__ = TestLoader()
+ modrepr = self.bootstrap._module_repr(self.module)
+
+ self.assertEqual(modrepr,
+ '<module {!r} (<TestLoader object>)>'.format('spam'))
+
+ def test_module_no_file_no_loader(self):
+ modrepr = self.bootstrap._module_repr(self.module)
+
+ self.assertEqual(modrepr, '<module {!r}>'.format('spam'))
+
+
+class Frozen_ModuleReprTests(ModuleReprTests, unittest.TestCase):
+ bootstrap = frozen_bootstrap
+ machinery = frozen_machinery
+ util = frozen_util
+
+
+class Source_ModuleReprTests(ModuleReprTests, unittest.TestCase):
+ bootstrap = source_bootstrap
+ machinery = source_machinery
+ util = source_util
+
+
+class FactoryTests:
+
+ def setUp(self):
+ self.name = 'spam'
+ self.path = 'spam.py'
+ self.cached = self.util.cache_from_source(self.path)
+ self.loader = TestLoader()
+ self.fileloader = TestLoader(self.path)
+ self.pkgloader = TestLoader(self.path, True)
+
+ # spec_from_loader()
+
+ def test_spec_from_loader_default(self):
+ spec = self.util.spec_from_loader(self.name, self.loader)
+
+ self.assertEqual(spec.name, self.name)
+ self.assertEqual(spec.loader, self.loader)
+ self.assertIs(spec.origin, None)
+ self.assertIs(spec.loader_state, None)
+ self.assertIs(spec.submodule_search_locations, None)
+ self.assertIs(spec.cached, None)
+ self.assertFalse(spec.has_location)
+
+ def test_spec_from_loader_default_with_bad_is_package(self):
+ class Loader:
+ def is_package(self, name):
+ raise ImportError
+ loader = Loader()
+ spec = self.util.spec_from_loader(self.name, loader)
+
+ self.assertEqual(spec.name, self.name)
+ self.assertEqual(spec.loader, loader)
+ self.assertIs(spec.origin, None)
+ self.assertIs(spec.loader_state, None)
+ self.assertIs(spec.submodule_search_locations, None)
+ self.assertIs(spec.cached, None)
+ self.assertFalse(spec.has_location)
+
+ def test_spec_from_loader_origin(self):
+ origin = 'somewhere over the rainbow'
+ spec = self.util.spec_from_loader(self.name, self.loader,
+ origin=origin)
+
+ self.assertEqual(spec.name, self.name)
+ self.assertEqual(spec.loader, self.loader)
+ self.assertIs(spec.origin, origin)
+ self.assertIs(spec.loader_state, None)
+ self.assertIs(spec.submodule_search_locations, None)
+ self.assertIs(spec.cached, None)
+ self.assertFalse(spec.has_location)
+
+ def test_spec_from_loader_is_package_false(self):
+ spec = self.util.spec_from_loader(self.name, self.loader,
+ is_package=False)
+
+ self.assertEqual(spec.name, self.name)
+ self.assertEqual(spec.loader, self.loader)
+ self.assertIs(spec.origin, None)
+ self.assertIs(spec.loader_state, None)
+ self.assertIs(spec.submodule_search_locations, None)
+ self.assertIs(spec.cached, None)
+ self.assertFalse(spec.has_location)
+
+ def test_spec_from_loader_is_package_true(self):
+ spec = self.util.spec_from_loader(self.name, self.loader,
+ is_package=True)
+
+ self.assertEqual(spec.name, self.name)
+ self.assertEqual(spec.loader, self.loader)
+ self.assertIs(spec.origin, None)
+ self.assertIs(spec.loader_state, None)
+ self.assertEqual(spec.submodule_search_locations, [])
+ self.assertIs(spec.cached, None)
+ self.assertFalse(spec.has_location)
+
+ def test_spec_from_loader_origin_and_is_package(self):
+ origin = 'where the streets have no name'
+ spec = self.util.spec_from_loader(self.name, self.loader,
+ origin=origin, is_package=True)
+
+ self.assertEqual(spec.name, self.name)
+ self.assertEqual(spec.loader, self.loader)
+ self.assertIs(spec.origin, origin)
+ self.assertIs(spec.loader_state, None)
+ self.assertEqual(spec.submodule_search_locations, [])
+ self.assertIs(spec.cached, None)
+ self.assertFalse(spec.has_location)
+
+ def test_spec_from_loader_is_package_with_loader_false(self):
+ loader = TestLoader(is_package=False)
+ spec = self.util.spec_from_loader(self.name, loader)
+
+ self.assertEqual(spec.name, self.name)
+ self.assertEqual(spec.loader, loader)
+ self.assertIs(spec.origin, None)
+ self.assertIs(spec.loader_state, None)
+ self.assertIs(spec.submodule_search_locations, None)
+ self.assertIs(spec.cached, None)
+ self.assertFalse(spec.has_location)
+
+ def test_spec_from_loader_is_package_with_loader_true(self):
+ loader = TestLoader(is_package=True)
+ spec = self.util.spec_from_loader(self.name, loader)
+
+ self.assertEqual(spec.name, self.name)
+ self.assertEqual(spec.loader, loader)
+ self.assertIs(spec.origin, None)
+ self.assertIs(spec.loader_state, None)
+ self.assertEqual(spec.submodule_search_locations, [])
+ self.assertIs(spec.cached, None)
+ self.assertFalse(spec.has_location)
+
+ def test_spec_from_loader_default_with_file_loader(self):
+ spec = self.util.spec_from_loader(self.name, self.fileloader)
+
+ self.assertEqual(spec.name, self.name)
+ self.assertEqual(spec.loader, self.fileloader)
+ self.assertEqual(spec.origin, self.path)
+ self.assertIs(spec.loader_state, None)
+ self.assertIs(spec.submodule_search_locations, None)
+ self.assertEqual(spec.cached, self.cached)
+ self.assertTrue(spec.has_location)
+
+ def test_spec_from_loader_is_package_false_with_fileloader(self):
+ spec = self.util.spec_from_loader(self.name, self.fileloader,
+ is_package=False)
+
+ self.assertEqual(spec.name, self.name)
+ self.assertEqual(spec.loader, self.fileloader)
+ self.assertEqual(spec.origin, self.path)
+ self.assertIs(spec.loader_state, None)
+ self.assertIs(spec.submodule_search_locations, None)
+ self.assertEqual(spec.cached, self.cached)
+ self.assertTrue(spec.has_location)
+
+ def test_spec_from_loader_is_package_true_with_fileloader(self):
+ spec = self.util.spec_from_loader(self.name, self.fileloader,
+ is_package=True)
+
+ self.assertEqual(spec.name, self.name)
+ self.assertEqual(spec.loader, self.fileloader)
+ self.assertEqual(spec.origin, self.path)
+ self.assertIs(spec.loader_state, None)
+ self.assertEqual(spec.submodule_search_locations, [''])
+ self.assertEqual(spec.cached, self.cached)
+ self.assertTrue(spec.has_location)
+
+ # spec_from_file_location()
+
+ def test_spec_from_file_location_default(self):
+ if self.machinery is source_machinery:
+ raise unittest.SkipTest('not sure why this is breaking...')
+ spec = self.util.spec_from_file_location(self.name, self.path)
+
+ self.assertEqual(spec.name, self.name)
+ self.assertIsInstance(spec.loader,
+ self.machinery.SourceFileLoader)
+ self.assertEqual(spec.loader.name, self.name)
+ self.assertEqual(spec.loader.path, self.path)
+ self.assertEqual(spec.origin, self.path)
+ self.assertIs(spec.loader_state, None)
+ self.assertIs(spec.submodule_search_locations, None)
+ self.assertEqual(spec.cached, self.cached)
+ self.assertTrue(spec.has_location)
+
+ def test_spec_from_file_location_default_without_location(self):
+ spec = self.util.spec_from_file_location(self.name)
+
+ self.assertIs(spec, None)
+
+ def test_spec_from_file_location_default_bad_suffix(self):
+ spec = self.util.spec_from_file_location(self.name, 'spam.eggs')
+
+ self.assertIs(spec, None)
+
+ def test_spec_from_file_location_loader_no_location(self):
+ spec = self.util.spec_from_file_location(self.name,
+ loader=self.fileloader)
+
+ self.assertEqual(spec.name, self.name)
+ self.assertEqual(spec.loader, self.fileloader)
+ self.assertEqual(spec.origin, self.path)
+ self.assertIs(spec.loader_state, None)
+ self.assertIs(spec.submodule_search_locations, None)
+ self.assertEqual(spec.cached, self.cached)
+ self.assertTrue(spec.has_location)
+
+ def test_spec_from_file_location_loader_no_location_no_get_filename(self):
+ spec = self.util.spec_from_file_location(self.name,
+ loader=self.loader)
+
+ self.assertEqual(spec.name, self.name)
+ self.assertEqual(spec.loader, self.loader)
+ self.assertEqual(spec.origin, '<unknown>')
+ self.assertIs(spec.loader_state, None)
+ self.assertIs(spec.submodule_search_locations, None)
+ self.assertIs(spec.cached, None)
+ self.assertTrue(spec.has_location)
+
+ def test_spec_from_file_location_loader_no_location_bad_get_filename(self):
+ class Loader:
+ def get_filename(self, name):
+ raise ImportError
+ loader = Loader()
+ spec = self.util.spec_from_file_location(self.name, loader=loader)
+
+ self.assertEqual(spec.name, self.name)
+ self.assertEqual(spec.loader, loader)
+ self.assertEqual(spec.origin, '<unknown>')
+ self.assertIs(spec.loader_state, None)
+ self.assertIs(spec.submodule_search_locations, None)
+ self.assertIs(spec.cached, None)
+ self.assertTrue(spec.has_location)
+
+ def test_spec_from_file_location_smsl_none(self):
+ spec = self.util.spec_from_file_location(self.name, self.path,
+ loader=self.fileloader,
+ submodule_search_locations=None)
+
+ self.assertEqual(spec.name, self.name)
+ self.assertEqual(spec.loader, self.fileloader)
+ self.assertEqual(spec.origin, self.path)
+ self.assertIs(spec.loader_state, None)
+ self.assertIs(spec.submodule_search_locations, None)
+ self.assertEqual(spec.cached, self.cached)
+ self.assertTrue(spec.has_location)
+
+ def test_spec_from_file_location_smsl_empty(self):
+ spec = self.util.spec_from_file_location(self.name, self.path,
+ loader=self.fileloader,
+ submodule_search_locations=[])
+
+ self.assertEqual(spec.name, self.name)
+ self.assertEqual(spec.loader, self.fileloader)
+ self.assertEqual(spec.origin, self.path)
+ self.assertIs(spec.loader_state, None)
+ self.assertEqual(spec.submodule_search_locations, [''])
+ self.assertEqual(spec.cached, self.cached)
+ self.assertTrue(spec.has_location)
+
+ def test_spec_from_file_location_smsl_not_empty(self):
+ spec = self.util.spec_from_file_location(self.name, self.path,
+ loader=self.fileloader,
+ submodule_search_locations=['eggs'])
+
+ self.assertEqual(spec.name, self.name)
+ self.assertEqual(spec.loader, self.fileloader)
+ self.assertEqual(spec.origin, self.path)
+ self.assertIs(spec.loader_state, None)
+ self.assertEqual(spec.submodule_search_locations, ['eggs'])
+ self.assertEqual(spec.cached, self.cached)
+ self.assertTrue(spec.has_location)
+
+ def test_spec_from_file_location_smsl_default(self):
+ spec = self.util.spec_from_file_location(self.name, self.path,
+ loader=self.pkgloader)
+
+ self.assertEqual(spec.name, self.name)
+ self.assertEqual(spec.loader, self.pkgloader)
+ self.assertEqual(spec.origin, self.path)
+ self.assertIs(spec.loader_state, None)
+ self.assertEqual(spec.submodule_search_locations, [''])
+ self.assertEqual(spec.cached, self.cached)
+ self.assertTrue(spec.has_location)
+
+ def test_spec_from_file_location_smsl_default_not_package(self):
+ class Loader:
+ def is_package(self, name):
+ return False
+ loader = Loader()
+ spec = self.util.spec_from_file_location(self.name, self.path,
+ loader=loader)
+
+ self.assertEqual(spec.name, self.name)
+ self.assertEqual(spec.loader, loader)
+ self.assertEqual(spec.origin, self.path)
+ self.assertIs(spec.loader_state, None)
+ self.assertIs(spec.submodule_search_locations, None)
+ self.assertEqual(spec.cached, self.cached)
+ self.assertTrue(spec.has_location)
+
+ def test_spec_from_file_location_smsl_default_no_is_package(self):
+ spec = self.util.spec_from_file_location(self.name, self.path,
+ loader=self.fileloader)
+
+ self.assertEqual(spec.name, self.name)
+ self.assertEqual(spec.loader, self.fileloader)
+ self.assertEqual(spec.origin, self.path)
+ self.assertIs(spec.loader_state, None)
+ self.assertIs(spec.submodule_search_locations, None)
+ self.assertEqual(spec.cached, self.cached)
+ self.assertTrue(spec.has_location)
+
+ def test_spec_from_file_location_smsl_default_bad_is_package(self):
+ class Loader:
+ def is_package(self, name):
+ raise ImportError
+ loader = Loader()
+ spec = self.util.spec_from_file_location(self.name, self.path,
+ loader=loader)
+
+ self.assertEqual(spec.name, self.name)
+ self.assertEqual(spec.loader, loader)
+ self.assertEqual(spec.origin, self.path)
+ self.assertIs(spec.loader_state, None)
+ self.assertIs(spec.submodule_search_locations, None)
+ self.assertEqual(spec.cached, self.cached)
+ self.assertTrue(spec.has_location)
+
+
+class Frozen_FactoryTests(FactoryTests, unittest.TestCase):
+ util = frozen_util
+ machinery = frozen_machinery
+
+
+class Source_FactoryTests(FactoryTests, unittest.TestCase):
+ util = source_util
+ machinery = source_machinery
diff --git a/Lib/test/test_importlib/test_util.py b/Lib/test/test_importlib/test_util.py
index efc8977fb4..b2823c6a78 100644
--- a/Lib/test/test_importlib/test_util.py
+++ b/Lib/test/test_importlib/test_util.py
@@ -1,23 +1,66 @@
from importlib import util
from . import util as test_util
-import imp
+frozen_init, source_init = test_util.import_importlib('importlib')
+frozen_machinery, source_machinery = test_util.import_importlib('importlib.machinery')
+frozen_util, source_util = test_util.import_importlib('importlib.util')
+
+import os
import sys
+from test import support
import types
import unittest
+import warnings
+
+
+class DecodeSourceBytesTests:
+
+ source = "string ='ΓΌ'"
+
+ def test_ut8_default(self):
+ source_bytes = self.source.encode('utf-8')
+ self.assertEqual(self.util.decode_source(source_bytes), self.source)
+
+ def test_specified_encoding(self):
+ source = '# coding=latin-1\n' + self.source
+ source_bytes = source.encode('latin-1')
+ assert source_bytes != source.encode('utf-8')
+ self.assertEqual(self.util.decode_source(source_bytes), source)
+ def test_universal_newlines(self):
+ source = '\r\n'.join([self.source, self.source])
+ source_bytes = source.encode('utf-8')
+ self.assertEqual(self.util.decode_source(source_bytes),
+ '\n'.join([self.source, self.source]))
-class ModuleForLoaderTests(unittest.TestCase):
+Frozen_DecodeSourceBytesTests, Source_DecodeSourceBytesTests = test_util.test_both(
+ DecodeSourceBytesTests, util=[frozen_util, source_util])
+
+
+class ModuleForLoaderTests:
"""Tests for importlib.util.module_for_loader."""
+ @classmethod
+ def module_for_loader(cls, func):
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ return cls.util.module_for_loader(func)
+
+ def test_warning(self):
+ # Should raise a PendingDeprecationWarning when used.
+ with warnings.catch_warnings():
+ warnings.simplefilter('error', DeprecationWarning)
+ with self.assertRaises(DeprecationWarning):
+ func = self.util.module_for_loader(lambda x: x)
+
def return_module(self, name):
- fxn = util.module_for_loader(lambda self, module: module)
+ fxn = self.module_for_loader(lambda self, module: module)
return fxn(self, name)
def raise_exception(self, name):
def to_wrap(self, module):
raise ImportError
- fxn = util.module_for_loader(to_wrap)
+ fxn = self.module_for_loader(to_wrap)
try:
fxn(self, name)
except ImportError:
@@ -35,12 +78,23 @@ class ModuleForLoaderTests(unittest.TestCase):
def test_reload(self):
# Test that a module is reused if already in sys.modules.
+ class FakeLoader:
+ def is_package(self, name):
+ return True
+ @self.module_for_loader
+ def load_module(self, module):
+ return module
name = 'a.b.c'
- module = imp.new_module('a.b.c')
+ module = types.ModuleType('a.b.c')
+ module.__loader__ = 42
+ module.__package__ = 42
with test_util.uncache(name):
sys.modules[name] = module
- returned_module = self.return_module(name)
+ loader = FakeLoader()
+ returned_module = loader.load_module(name)
self.assertIs(returned_module, sys.modules[name])
+ self.assertEqual(module.__loader__, loader)
+ self.assertEqual(module.__package__, name)
def test_new_module_failure(self):
# Test that a module is removed from sys.modules if added but an
@@ -53,7 +107,7 @@ class ModuleForLoaderTests(unittest.TestCase):
def test_reload_failure(self):
# Test that a failure on reload leaves the module in-place.
name = 'a.b.c'
- module = imp.new_module(name)
+ module = types.ModuleType(name)
with test_util.uncache(name):
sys.modules[name] = module
self.raise_exception(name)
@@ -61,7 +115,7 @@ class ModuleForLoaderTests(unittest.TestCase):
def test_decorator_attrs(self):
def fxn(self, module): pass
- wrapped = util.module_for_loader(fxn)
+ wrapped = self.module_for_loader(fxn)
self.assertEqual(wrapped.__name__, fxn.__name__)
self.assertEqual(wrapped.__qualname__, fxn.__qualname__)
@@ -87,7 +141,7 @@ class ModuleForLoaderTests(unittest.TestCase):
self._pkg = is_package
def is_package(self, name):
return self._pkg
- @util.module_for_loader
+ @self.module_for_loader
def load_module(self, module):
return module
@@ -107,8 +161,11 @@ class ModuleForLoaderTests(unittest.TestCase):
self.assertIs(module.__loader__, loader)
self.assertEqual(module.__package__, name)
+Frozen_ModuleForLoaderTests, Source_ModuleForLoaderTests = test_util.test_both(
+ ModuleForLoaderTests, util=[frozen_util, source_util])
+
-class SetPackageTests(unittest.TestCase):
+class SetPackageTests:
"""Tests for importlib.util.set_package."""
@@ -116,34 +173,36 @@ class SetPackageTests(unittest.TestCase):
"""Verify the module has the expected value for __package__ after
passing through set_package."""
fxn = lambda: module
- wrapped = util.set_package(fxn)
- wrapped()
+ wrapped = self.util.set_package(fxn)
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ wrapped()
self.assertTrue(hasattr(module, '__package__'))
self.assertEqual(expect, module.__package__)
def test_top_level(self):
# __package__ should be set to the empty string if a top-level module.
# Implicitly tests when package is set to None.
- module = imp.new_module('module')
+ module = types.ModuleType('module')
module.__package__ = None
self.verify(module, '')
def test_package(self):
# Test setting __package__ for a package.
- module = imp.new_module('pkg')
+ module = types.ModuleType('pkg')
module.__path__ = ['<path>']
module.__package__ = None
self.verify(module, 'pkg')
def test_submodule(self):
# Test __package__ for a module in a package.
- module = imp.new_module('pkg.mod')
+ module = types.ModuleType('pkg.mod')
module.__package__ = None
self.verify(module, 'pkg')
def test_setting_if_missing(self):
# __package__ should be set if it is missing.
- module = imp.new_module('mod')
+ module = types.ModuleType('mod')
if hasattr(module, '__package__'):
delattr(module, '__package__')
self.verify(module, '')
@@ -151,58 +210,383 @@ class SetPackageTests(unittest.TestCase):
def test_leaving_alone(self):
# If __package__ is set and not None then leave it alone.
for value in (True, False):
- module = imp.new_module('mod')
+ module = types.ModuleType('mod')
module.__package__ = value
self.verify(module, value)
def test_decorator_attrs(self):
def fxn(module): pass
- wrapped = util.set_package(fxn)
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ wrapped = self.util.set_package(fxn)
self.assertEqual(wrapped.__name__, fxn.__name__)
self.assertEqual(wrapped.__qualname__, fxn.__qualname__)
+Frozen_SetPackageTests, Source_SetPackageTests = test_util.test_both(
+ SetPackageTests, util=[frozen_util, source_util])
-class ResolveNameTests(unittest.TestCase):
+
+class SetLoaderTests:
+
+ """Tests importlib.util.set_loader()."""
+
+ class DummyLoader:
+ @util.set_loader
+ def load_module(self, module):
+ return self.module
+
+ def test_no_attribute(self):
+ loader = self.DummyLoader()
+ loader.module = types.ModuleType('blah')
+ try:
+ del loader.module.__loader__
+ except AttributeError:
+ pass
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ self.assertEqual(loader, loader.load_module('blah').__loader__)
+
+ def test_attribute_is_None(self):
+ loader = self.DummyLoader()
+ loader.module = types.ModuleType('blah')
+ loader.module.__loader__ = None
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ self.assertEqual(loader, loader.load_module('blah').__loader__)
+
+ def test_not_reset(self):
+ loader = self.DummyLoader()
+ loader.module = types.ModuleType('blah')
+ loader.module.__loader__ = 42
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ self.assertEqual(42, loader.load_module('blah').__loader__)
+
+class Frozen_SetLoaderTests(SetLoaderTests, unittest.TestCase):
+ class DummyLoader:
+ @frozen_util.set_loader
+ def load_module(self, module):
+ return self.module
+
+class Source_SetLoaderTests(SetLoaderTests, unittest.TestCase):
+ class DummyLoader:
+ @source_util.set_loader
+ def load_module(self, module):
+ return self.module
+
+
+class ResolveNameTests:
"""Tests importlib.util.resolve_name()."""
def test_absolute(self):
# bacon
- self.assertEqual('bacon', util.resolve_name('bacon', None))
+ self.assertEqual('bacon', self.util.resolve_name('bacon', None))
def test_aboslute_within_package(self):
# bacon in spam
- self.assertEqual('bacon', util.resolve_name('bacon', 'spam'))
+ self.assertEqual('bacon', self.util.resolve_name('bacon', 'spam'))
def test_no_package(self):
# .bacon in ''
with self.assertRaises(ValueError):
- util.resolve_name('.bacon', '')
+ self.util.resolve_name('.bacon', '')
def test_in_package(self):
# .bacon in spam
self.assertEqual('spam.eggs.bacon',
- util.resolve_name('.bacon', 'spam.eggs'))
+ self.util.resolve_name('.bacon', 'spam.eggs'))
def test_other_package(self):
# ..bacon in spam.bacon
self.assertEqual('spam.bacon',
- util.resolve_name('..bacon', 'spam.eggs'))
+ self.util.resolve_name('..bacon', 'spam.eggs'))
def test_escape(self):
# ..bacon in spam
with self.assertRaises(ValueError):
- util.resolve_name('..bacon', 'spam')
+ self.util.resolve_name('..bacon', 'spam')
+
+Frozen_ResolveNameTests, Source_ResolveNameTests = test_util.test_both(
+ ResolveNameTests,
+ util=[frozen_util, source_util])
+
+
+class FindSpecTests:
+
+ class FakeMetaFinder:
+ @staticmethod
+ def find_spec(name, path=None, target=None): return name, path, target
+
+ def test_sys_modules(self):
+ name = 'some_mod'
+ with test_util.uncache(name):
+ module = types.ModuleType(name)
+ loader = 'a loader!'
+ spec = self.machinery.ModuleSpec(name, loader)
+ module.__loader__ = loader
+ module.__spec__ = spec
+ sys.modules[name] = module
+ found = self.util.find_spec(name)
+ self.assertEqual(found, spec)
+
+ def test_sys_modules_without___loader__(self):
+ name = 'some_mod'
+ with test_util.uncache(name):
+ module = types.ModuleType(name)
+ del module.__loader__
+ loader = 'a loader!'
+ spec = self.machinery.ModuleSpec(name, loader)
+ module.__spec__ = spec
+ sys.modules[name] = module
+ found = self.util.find_spec(name)
+ self.assertEqual(found, spec)
+
+ def test_sys_modules_spec_is_None(self):
+ name = 'some_mod'
+ with test_util.uncache(name):
+ module = types.ModuleType(name)
+ module.__spec__ = None
+ sys.modules[name] = module
+ with self.assertRaises(ValueError):
+ self.util.find_spec(name)
+
+ def test_sys_modules_loader_is_None(self):
+ name = 'some_mod'
+ with test_util.uncache(name):
+ module = types.ModuleType(name)
+ spec = self.machinery.ModuleSpec(name, None)
+ module.__spec__ = spec
+ sys.modules[name] = module
+ found = self.util.find_spec(name)
+ self.assertEqual(found, spec)
+ def test_sys_modules_spec_is_not_set(self):
+ name = 'some_mod'
+ with test_util.uncache(name):
+ module = types.ModuleType(name)
+ try:
+ del module.__spec__
+ except AttributeError:
+ pass
+ sys.modules[name] = module
+ with self.assertRaises(ValueError):
+ self.util.find_spec(name)
-def test_main():
- from test import support
- support.run_unittest(
- ModuleForLoaderTests,
- SetPackageTests,
- ResolveNameTests
- )
+ def test_success(self):
+ name = 'some_mod'
+ with test_util.uncache(name):
+ with test_util.import_state(meta_path=[self.FakeMetaFinder]):
+ self.assertEqual((name, None, None),
+ self.util.find_spec(name))
+
+# def test_success_path(self):
+# # Searching on a path should work.
+# name = 'some_mod'
+# path = 'path to some place'
+# with test_util.uncache(name):
+# with test_util.import_state(meta_path=[self.FakeMetaFinder]):
+# self.assertEqual((name, path, None),
+# self.util.find_spec(name, path))
+
+ def test_nothing(self):
+ # None is returned upon failure to find a loader.
+ self.assertIsNone(self.util.find_spec('nevergoingtofindthismodule'))
+
+ def test_find_submodule(self):
+ name = 'spam'
+ subname = 'ham'
+ with test_util.temp_module(name, pkg=True) as pkg_dir:
+ fullname, _ = test_util.submodule(name, subname, pkg_dir)
+ spec = self.util.find_spec(fullname)
+ self.assertIsNot(spec, None)
+ self.assertIn(name, sorted(sys.modules))
+ self.assertNotIn(fullname, sorted(sys.modules))
+ # Ensure successive calls behave the same.
+ spec_again = self.util.find_spec(fullname)
+ self.assertEqual(spec_again, spec)
+
+ def test_find_submodule_parent_already_imported(self):
+ name = 'spam'
+ subname = 'ham'
+ with test_util.temp_module(name, pkg=True) as pkg_dir:
+ self.init.import_module(name)
+ fullname, _ = test_util.submodule(name, subname, pkg_dir)
+ spec = self.util.find_spec(fullname)
+ self.assertIsNot(spec, None)
+ self.assertIn(name, sorted(sys.modules))
+ self.assertNotIn(fullname, sorted(sys.modules))
+ # Ensure successive calls behave the same.
+ spec_again = self.util.find_spec(fullname)
+ self.assertEqual(spec_again, spec)
+
+ def test_find_relative_module(self):
+ name = 'spam'
+ subname = 'ham'
+ with test_util.temp_module(name, pkg=True) as pkg_dir:
+ fullname, _ = test_util.submodule(name, subname, pkg_dir)
+ relname = '.' + subname
+ spec = self.util.find_spec(relname, name)
+ self.assertIsNot(spec, None)
+ self.assertIn(name, sorted(sys.modules))
+ self.assertNotIn(fullname, sorted(sys.modules))
+ # Ensure successive calls behave the same.
+ spec_again = self.util.find_spec(fullname)
+ self.assertEqual(spec_again, spec)
+
+ def test_find_relative_module_missing_package(self):
+ name = 'spam'
+ subname = 'ham'
+ with test_util.temp_module(name, pkg=True) as pkg_dir:
+ fullname, _ = test_util.submodule(name, subname, pkg_dir)
+ relname = '.' + subname
+ with self.assertRaises(ValueError):
+ self.util.find_spec(relname)
+ self.assertNotIn(name, sorted(sys.modules))
+ self.assertNotIn(fullname, sorted(sys.modules))
+
+
+class Frozen_FindSpecTests(FindSpecTests, unittest.TestCase):
+ init = frozen_init
+ machinery = frozen_machinery
+ util = frozen_util
+
+class Source_FindSpecTests(FindSpecTests, unittest.TestCase):
+ init = source_init
+ machinery = source_machinery
+ util = source_util
+
+
+class MagicNumberTests:
+
+ def test_length(self):
+ # Should be 4 bytes.
+ self.assertEqual(len(self.util.MAGIC_NUMBER), 4)
+
+ def test_incorporates_rn(self):
+ # The magic number uses \r\n to come out wrong when splitting on lines.
+ self.assertTrue(self.util.MAGIC_NUMBER.endswith(b'\r\n'))
+
+Frozen_MagicNumberTests, Source_MagicNumberTests = test_util.test_both(
+ MagicNumberTests, util=[frozen_util, source_util])
+
+
+class PEP3147Tests:
+
+ """Tests of PEP 3147-related functions: cache_from_source and source_from_cache."""
+
+ tag = sys.implementation.cache_tag
+
+ @unittest.skipUnless(sys.implementation.cache_tag is not None,
+ 'requires sys.implementation.cache_tag not be None')
+ def test_cache_from_source(self):
+ # Given the path to a .py file, return the path to its PEP 3147
+ # defined .pyc file (i.e. under __pycache__).
+ path = os.path.join('foo', 'bar', 'baz', 'qux.py')
+ expect = os.path.join('foo', 'bar', 'baz', '__pycache__',
+ 'qux.{}.pyc'.format(self.tag))
+ self.assertEqual(self.util.cache_from_source(path, True), expect)
+
+ def test_cache_from_source_no_cache_tag(self):
+ # No cache tag means NotImplementedError.
+ with support.swap_attr(sys.implementation, 'cache_tag', None):
+ with self.assertRaises(NotImplementedError):
+ self.util.cache_from_source('whatever.py')
+
+ def test_cache_from_source_no_dot(self):
+ # Directory with a dot, filename without dot.
+ path = os.path.join('foo.bar', 'file')
+ expect = os.path.join('foo.bar', '__pycache__',
+ 'file{}.pyc'.format(self.tag))
+ self.assertEqual(self.util.cache_from_source(path, True), expect)
+
+ def test_cache_from_source_optimized(self):
+ # Given the path to a .py file, return the path to its PEP 3147
+ # defined .pyo file (i.e. under __pycache__).
+ path = os.path.join('foo', 'bar', 'baz', 'qux.py')
+ expect = os.path.join('foo', 'bar', 'baz', '__pycache__',
+ 'qux.{}.pyo'.format(self.tag))
+ self.assertEqual(self.util.cache_from_source(path, False), expect)
+
+ def test_cache_from_source_cwd(self):
+ path = 'foo.py'
+ expect = os.path.join('__pycache__', 'foo.{}.pyc'.format(self.tag))
+ self.assertEqual(self.util.cache_from_source(path, True), expect)
+
+ def test_cache_from_source_override(self):
+ # When debug_override is not None, it can be any true-ish or false-ish
+ # value.
+ path = os.path.join('foo', 'bar', 'baz.py')
+ partial_expect = os.path.join('foo', 'bar', '__pycache__',
+ 'baz.{}.py'.format(self.tag))
+ self.assertEqual(self.util.cache_from_source(path, []), partial_expect + 'o')
+ self.assertEqual(self.util.cache_from_source(path, [17]),
+ partial_expect + 'c')
+ # However if the bool-ishness can't be determined, the exception
+ # propagates.
+ class Bearish:
+ def __bool__(self): raise RuntimeError
+ with self.assertRaises(RuntimeError):
+ self.util.cache_from_source('/foo/bar/baz.py', Bearish())
+
+ @unittest.skipUnless(os.sep == '\\' and os.altsep == '/',
+ 'test meaningful only where os.altsep is defined')
+ def test_sep_altsep_and_sep_cache_from_source(self):
+ # Windows path and PEP 3147 where sep is right of altsep.
+ self.assertEqual(
+ self.util.cache_from_source('\\foo\\bar\\baz/qux.py', True),
+ '\\foo\\bar\\baz\\__pycache__\\qux.{}.pyc'.format(self.tag))
+
+ @unittest.skipUnless(sys.implementation.cache_tag is not None,
+ 'requires sys.implementation.cache_tag to not be '
+ 'None')
+ def test_source_from_cache(self):
+ # Given the path to a PEP 3147 defined .pyc file, return the path to
+ # its source. This tests the good path.
+ path = os.path.join('foo', 'bar', 'baz', '__pycache__',
+ 'qux.{}.pyc'.format(self.tag))
+ expect = os.path.join('foo', 'bar', 'baz', 'qux.py')
+ self.assertEqual(self.util.source_from_cache(path), expect)
+
+ def test_source_from_cache_no_cache_tag(self):
+ # If sys.implementation.cache_tag is None, raise NotImplementedError.
+ path = os.path.join('blah', '__pycache__', 'whatever.pyc')
+ with support.swap_attr(sys.implementation, 'cache_tag', None):
+ with self.assertRaises(NotImplementedError):
+ self.util.source_from_cache(path)
+
+ def test_source_from_cache_bad_path(self):
+ # When the path to a pyc file is not in PEP 3147 format, a ValueError
+ # is raised.
+ self.assertRaises(
+ ValueError, self.util.source_from_cache, '/foo/bar/bazqux.pyc')
+
+ def test_source_from_cache_no_slash(self):
+ # No slashes at all in path -> ValueError
+ self.assertRaises(
+ ValueError, self.util.source_from_cache, 'foo.cpython-32.pyc')
+
+ def test_source_from_cache_too_few_dots(self):
+ # Too few dots in final path component -> ValueError
+ self.assertRaises(
+ ValueError, self.util.source_from_cache, '__pycache__/foo.pyc')
+
+ def test_source_from_cache_too_many_dots(self):
+ # Too many dots in final path component -> ValueError
+ self.assertRaises(
+ ValueError, self.util.source_from_cache,
+ '__pycache__/foo.cpython-32.foo.pyc')
+
+ def test_source_from_cache_no__pycache__(self):
+ # Another problem with the path -> ValueError
+ self.assertRaises(
+ ValueError, self.util.source_from_cache,
+ '/foo/bar/foo.cpython-32.foo.pyc')
+
+Frozen_PEP3147Tests, Source_PEP3147Tests = test_util.test_both(
+ PEP3147Tests,
+ util=[frozen_util, source_util])
if __name__ == '__main__':
- test_main()
+ unittest.main()
diff --git a/Lib/test/test_importlib/test_windows.py b/Lib/test/test_importlib/test_windows.py
new file mode 100644
index 0000000000..96b4adcd05
--- /dev/null
+++ b/Lib/test/test_importlib/test_windows.py
@@ -0,0 +1,29 @@
+from . import util
+frozen_machinery, source_machinery = util.import_importlib('importlib.machinery')
+
+import sys
+import unittest
+
+
+@unittest.skipUnless(sys.platform.startswith('win'), 'requires Windows')
+class WindowsRegistryFinderTests:
+
+ # XXX Need a test that finds the spec via the registry.
+
+ def test_find_spec_missing(self):
+ spec = self.machinery.WindowsRegistryFinder.find_spec('spam')
+ self.assertIs(spec, None)
+
+ def test_find_module_missing(self):
+ loader = self.machinery.WindowsRegistryFinder.find_module('spam')
+ self.assertIs(loader, None)
+
+
+class Frozen_WindowsRegistryFinderTests(WindowsRegistryFinderTests,
+ unittest.TestCase):
+ machinery = frozen_machinery
+
+
+class Source_WindowsRegistryFinderTests(WindowsRegistryFinderTests,
+ unittest.TestCase):
+ machinery = source_machinery
diff --git a/Lib/test/test_importlib/util.py b/Lib/test/test_importlib/util.py
index ef32f7d690..885cec3b29 100644
--- a/Lib/test/test_importlib/util.py
+++ b/Lib/test/test_importlib/util.py
@@ -1,9 +1,31 @@
from contextlib import contextmanager
-import imp
+from importlib import util, invalidate_caches
import os.path
from test import support
import unittest
import sys
+import types
+
+
+def import_importlib(module_name):
+ """Import a module from importlib both w/ and w/o _frozen_importlib."""
+ fresh = ('importlib',) if '.' in module_name else ()
+ frozen = support.import_fresh_module(module_name)
+ source = support.import_fresh_module(module_name, fresh=fresh,
+ blocked=('_frozen_importlib',))
+ return frozen, source
+
+
+def test_both(test_class, **kwargs):
+ frozen_tests = types.new_class('Frozen_'+test_class.__name__,
+ (test_class, unittest.TestCase))
+ source_tests = types.new_class('Source_'+test_class.__name__,
+ (test_class, unittest.TestCase))
+ frozen_tests.__module__ = source_tests.__module__ = test_class.__module__
+ for attr, (frozen_value, source_value) in kwargs.items():
+ setattr(frozen_tests, attr, frozen_value)
+ setattr(source_tests, attr, source_value)
+ return frozen_tests, source_tests
CASE_INSENSITIVE_FS = True
@@ -24,6 +46,13 @@ def case_insensitive_tests(test):
"requires a case-insensitive filesystem")(test)
+def submodule(parent, name, pkg_dir, content=''):
+ path = os.path.join(pkg_dir, name + '.py')
+ with open(path, 'w') as subfile:
+ subfile.write(content)
+ return '{}.{}'.format(parent, name), path
+
+
@contextmanager
def uncache(*names):
"""Uncache a module from sys.modules.
@@ -49,6 +78,31 @@ def uncache(*names):
except KeyError:
pass
+
+@contextmanager
+def temp_module(name, content='', *, pkg=False):
+ conflicts = [n for n in sys.modules if n.partition('.')[0] == name]
+ with support.temp_cwd(None) as cwd:
+ with uncache(name, *conflicts):
+ with support.DirsOnSysPath(cwd):
+ invalidate_caches()
+
+ location = os.path.join(cwd, name)
+ if pkg:
+ modpath = os.path.join(location, '__init__.py')
+ os.mkdir(name)
+ else:
+ modpath = location + '.py'
+ if content is None:
+ # Make sure the module file gets created.
+ content = ''
+ if content is not None:
+ # not a namespace package
+ with open(modpath, 'w') as modfile:
+ modfile.write(content)
+ yield location
+
+
@contextmanager
def import_state(**kwargs):
"""Context manager to manage the various importers and stored state in the
@@ -80,9 +134,9 @@ def import_state(**kwargs):
setattr(sys, attr, value)
-class mock_modules:
+class _ImporterMock:
- """A mock importer/loader."""
+ """Base class to help with creating importer mocks."""
def __init__(self, *names, module_code={}):
self.modules = {}
@@ -98,7 +152,7 @@ class mock_modules:
package = name.rsplit('.', 1)[0]
else:
package = import_name
- module = imp.new_module(import_name)
+ module = types.ModuleType(import_name)
module.__loader__ = self
module.__file__ = '<mock __file__>'
module.__package__ = package
@@ -112,6 +166,19 @@ class mock_modules:
def __getitem__(self, name):
return self.modules[name]
+ def __enter__(self):
+ self._uncache = uncache(*self.modules.keys())
+ self._uncache.__enter__()
+ return self
+
+ def __exit__(self, *exc_info):
+ self._uncache.__exit__(None, None, None)
+
+
+class mock_modules(_ImporterMock):
+
+ """Importer mock using PEP 302 APIs."""
+
def find_module(self, fullname, path=None):
if fullname not in self.modules:
return None
@@ -131,10 +198,28 @@ class mock_modules:
raise
return self.modules[fullname]
- def __enter__(self):
- self._uncache = uncache(*self.modules.keys())
- self._uncache.__enter__()
- return self
+class mock_spec(_ImporterMock):
- def __exit__(self, *exc_info):
- self._uncache.__exit__(None, None, None)
+ """Importer mock using PEP 451 APIs."""
+
+ def find_spec(self, fullname, path=None, parent=None):
+ try:
+ module = self.modules[fullname]
+ except KeyError:
+ return None
+ is_package = hasattr(module, '__path__')
+ spec = util.spec_from_file_location(
+ fullname, module.__file__, loader=self,
+ submodule_search_locations=getattr(module, '__path__', None))
+ return spec
+
+ def create_module(self, spec):
+ if spec.name not in self.modules:
+ raise ImportError
+ return self.modules[spec.name]
+
+ def exec_module(self, module):
+ try:
+ self.module_code[module.__spec__.name]()
+ except KeyError:
+ pass