mirror of
https://github.com/python/cpython.git
synced 2025-07-24 11:44:31 +00:00
Issue #19721: Consolidate test_importlib utility code into a single
module.
This commit is contained in:
parent
91795c8e34
commit
732ac654c8
25 changed files with 249 additions and 270 deletions
|
@ -1,6 +1,5 @@
|
|||
"""Test case-sensitivity (PEP 235)."""
|
||||
from .. import util
|
||||
from . import util as source_util
|
||||
|
||||
importlib = util.import_importlib('importlib')
|
||||
machinery = util.import_importlib('importlib.machinery')
|
||||
|
@ -32,7 +31,7 @@ class CaseSensitivityTest:
|
|||
"""Look for a module with matching and non-matching sensitivity."""
|
||||
sensitive_pkg = 'sensitive.{0}'.format(self.name)
|
||||
insensitive_pkg = 'insensitive.{0}'.format(self.name.lower())
|
||||
context = source_util.create_modules(insensitive_pkg, sensitive_pkg)
|
||||
context = util.create_modules(insensitive_pkg, sensitive_pkg)
|
||||
with context as mapping:
|
||||
sensitive_path = os.path.join(mapping['.root'], 'sensitive')
|
||||
insensitive_path = os.path.join(mapping['.root'], 'insensitive')
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
from .. import abc
|
||||
from .. import util
|
||||
from . import util as source_util
|
||||
|
||||
importlib = util.import_importlib('importlib')
|
||||
importlib_abc = util.import_importlib('importlib.abc')
|
||||
|
@ -71,7 +70,7 @@ class SimpleTest(abc.LoaderTests):
|
|||
|
||||
# [basic]
|
||||
def test_module(self):
|
||||
with source_util.create_modules('_temp') as mapping:
|
||||
with util.create_modules('_temp') as mapping:
|
||||
loader = self.machinery.SourceFileLoader('_temp', mapping['_temp'])
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore', DeprecationWarning)
|
||||
|
@ -83,7 +82,7 @@ class SimpleTest(abc.LoaderTests):
|
|||
self.assertEqual(getattr(module, attr), value)
|
||||
|
||||
def test_package(self):
|
||||
with source_util.create_modules('_pkg.__init__') as mapping:
|
||||
with util.create_modules('_pkg.__init__') as mapping:
|
||||
loader = self.machinery.SourceFileLoader('_pkg',
|
||||
mapping['_pkg.__init__'])
|
||||
with warnings.catch_warnings():
|
||||
|
@ -98,7 +97,7 @@ class SimpleTest(abc.LoaderTests):
|
|||
|
||||
|
||||
def test_lacking_parent(self):
|
||||
with source_util.create_modules('_pkg.__init__', '_pkg.mod')as mapping:
|
||||
with util.create_modules('_pkg.__init__', '_pkg.mod')as mapping:
|
||||
loader = self.machinery.SourceFileLoader('_pkg.mod',
|
||||
mapping['_pkg.mod'])
|
||||
with warnings.catch_warnings():
|
||||
|
@ -115,7 +114,7 @@ class SimpleTest(abc.LoaderTests):
|
|||
return lambda name: fxn(name) + 1
|
||||
|
||||
def test_module_reuse(self):
|
||||
with source_util.create_modules('_temp') as mapping:
|
||||
with util.create_modules('_temp') as mapping:
|
||||
loader = self.machinery.SourceFileLoader('_temp', mapping['_temp'])
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore', DeprecationWarning)
|
||||
|
@ -139,7 +138,7 @@ class SimpleTest(abc.LoaderTests):
|
|||
attributes = ('__file__', '__path__', '__package__')
|
||||
value = '<test>'
|
||||
name = '_temp'
|
||||
with source_util.create_modules(name) as mapping:
|
||||
with util.create_modules(name) as mapping:
|
||||
orig_module = types.ModuleType(name)
|
||||
for attr in attributes:
|
||||
setattr(orig_module, attr, value)
|
||||
|
@ -159,7 +158,7 @@ class SimpleTest(abc.LoaderTests):
|
|||
|
||||
# [syntax error]
|
||||
def test_bad_syntax(self):
|
||||
with source_util.create_modules('_temp') as mapping:
|
||||
with util.create_modules('_temp') as mapping:
|
||||
with open(mapping['_temp'], 'w') as file:
|
||||
file.write('=')
|
||||
loader = self.machinery.SourceFileLoader('_temp', mapping['_temp'])
|
||||
|
@ -190,11 +189,11 @@ class SimpleTest(abc.LoaderTests):
|
|||
if os.path.exists(pycache):
|
||||
shutil.rmtree(pycache)
|
||||
|
||||
@source_util.writes_bytecode_files
|
||||
@util.writes_bytecode_files
|
||||
def test_timestamp_overflow(self):
|
||||
# When a modification timestamp is larger than 2**32, it should be
|
||||
# truncated rather than raise an OverflowError.
|
||||
with source_util.create_modules('_temp') as mapping:
|
||||
with util.create_modules('_temp') as mapping:
|
||||
source = mapping['_temp']
|
||||
compiled = self.util.cache_from_source(source)
|
||||
with open(source, 'w') as f:
|
||||
|
@ -275,45 +274,45 @@ class BadBytecodeTest:
|
|||
return bytecode_path
|
||||
|
||||
def _test_empty_file(self, test, *, del_source=False):
|
||||
with source_util.create_modules('_temp') as mapping:
|
||||
with util.create_modules('_temp') as mapping:
|
||||
bc_path = self.manipulate_bytecode('_temp', mapping,
|
||||
lambda bc: b'',
|
||||
del_source=del_source)
|
||||
test('_temp', mapping, bc_path)
|
||||
|
||||
@source_util.writes_bytecode_files
|
||||
@util.writes_bytecode_files
|
||||
def _test_partial_magic(self, test, *, del_source=False):
|
||||
# When their are less than 4 bytes to a .pyc, regenerate it if
|
||||
# possible, else raise ImportError.
|
||||
with source_util.create_modules('_temp') as mapping:
|
||||
with util.create_modules('_temp') as mapping:
|
||||
bc_path = self.manipulate_bytecode('_temp', mapping,
|
||||
lambda bc: bc[:3],
|
||||
del_source=del_source)
|
||||
test('_temp', mapping, bc_path)
|
||||
|
||||
def _test_magic_only(self, test, *, del_source=False):
|
||||
with source_util.create_modules('_temp') as mapping:
|
||||
with util.create_modules('_temp') as mapping:
|
||||
bc_path = self.manipulate_bytecode('_temp', mapping,
|
||||
lambda bc: bc[:4],
|
||||
del_source=del_source)
|
||||
test('_temp', mapping, bc_path)
|
||||
|
||||
def _test_partial_timestamp(self, test, *, del_source=False):
|
||||
with source_util.create_modules('_temp') as mapping:
|
||||
with util.create_modules('_temp') as mapping:
|
||||
bc_path = self.manipulate_bytecode('_temp', mapping,
|
||||
lambda bc: bc[:7],
|
||||
del_source=del_source)
|
||||
test('_temp', mapping, bc_path)
|
||||
|
||||
def _test_partial_size(self, test, *, del_source=False):
|
||||
with source_util.create_modules('_temp') as mapping:
|
||||
with util.create_modules('_temp') as mapping:
|
||||
bc_path = self.manipulate_bytecode('_temp', mapping,
|
||||
lambda bc: bc[:11],
|
||||
del_source=del_source)
|
||||
test('_temp', mapping, bc_path)
|
||||
|
||||
def _test_no_marshal(self, *, del_source=False):
|
||||
with source_util.create_modules('_temp') as mapping:
|
||||
with util.create_modules('_temp') as mapping:
|
||||
bc_path = self.manipulate_bytecode('_temp', mapping,
|
||||
lambda bc: bc[:12],
|
||||
del_source=del_source)
|
||||
|
@ -322,7 +321,7 @@ class BadBytecodeTest:
|
|||
self.import_(file_path, '_temp')
|
||||
|
||||
def _test_non_code_marshal(self, *, del_source=False):
|
||||
with source_util.create_modules('_temp') as mapping:
|
||||
with util.create_modules('_temp') as mapping:
|
||||
bytecode_path = self.manipulate_bytecode('_temp', mapping,
|
||||
lambda bc: bc[:12] + marshal.dumps(b'abcd'),
|
||||
del_source=del_source)
|
||||
|
@ -333,7 +332,7 @@ class BadBytecodeTest:
|
|||
self.assertEqual(cm.exception.path, bytecode_path)
|
||||
|
||||
def _test_bad_marshal(self, *, del_source=False):
|
||||
with source_util.create_modules('_temp') as mapping:
|
||||
with util.create_modules('_temp') as mapping:
|
||||
bytecode_path = self.manipulate_bytecode('_temp', mapping,
|
||||
lambda bc: bc[:12] + b'<test>',
|
||||
del_source=del_source)
|
||||
|
@ -342,7 +341,7 @@ class BadBytecodeTest:
|
|||
self.import_(file_path, '_temp')
|
||||
|
||||
def _test_bad_magic(self, test, *, del_source=False):
|
||||
with source_util.create_modules('_temp') as mapping:
|
||||
with util.create_modules('_temp') as mapping:
|
||||
bc_path = self.manipulate_bytecode('_temp', mapping,
|
||||
lambda bc: b'\x00\x00\x00\x00' + bc[4:])
|
||||
test('_temp', mapping, bc_path)
|
||||
|
@ -371,7 +370,7 @@ class SourceLoaderBadBytecodeTest:
|
|||
def setUpClass(cls):
|
||||
cls.loader = cls.machinery.SourceFileLoader
|
||||
|
||||
@source_util.writes_bytecode_files
|
||||
@util.writes_bytecode_files
|
||||
def test_empty_file(self):
|
||||
# When a .pyc is empty, regenerate it if possible, else raise
|
||||
# ImportError.
|
||||
|
@ -390,7 +389,7 @@ class SourceLoaderBadBytecodeTest:
|
|||
|
||||
self._test_partial_magic(test)
|
||||
|
||||
@source_util.writes_bytecode_files
|
||||
@util.writes_bytecode_files
|
||||
def test_magic_only(self):
|
||||
# When there is only the magic number, regenerate the .pyc if possible,
|
||||
# else raise EOFError.
|
||||
|
@ -401,7 +400,7 @@ class SourceLoaderBadBytecodeTest:
|
|||
|
||||
self._test_magic_only(test)
|
||||
|
||||
@source_util.writes_bytecode_files
|
||||
@util.writes_bytecode_files
|
||||
def test_bad_magic(self):
|
||||
# When the magic number is different, the bytecode should be
|
||||
# regenerated.
|
||||
|
@ -413,7 +412,7 @@ class SourceLoaderBadBytecodeTest:
|
|||
|
||||
self._test_bad_magic(test)
|
||||
|
||||
@source_util.writes_bytecode_files
|
||||
@util.writes_bytecode_files
|
||||
def test_partial_timestamp(self):
|
||||
# When the timestamp is partial, regenerate the .pyc, else
|
||||
# raise EOFError.
|
||||
|
@ -424,7 +423,7 @@ class SourceLoaderBadBytecodeTest:
|
|||
|
||||
self._test_partial_timestamp(test)
|
||||
|
||||
@source_util.writes_bytecode_files
|
||||
@util.writes_bytecode_files
|
||||
def test_partial_size(self):
|
||||
# When the size is partial, regenerate the .pyc, else
|
||||
# raise EOFError.
|
||||
|
@ -435,29 +434,29 @@ class SourceLoaderBadBytecodeTest:
|
|||
|
||||
self._test_partial_size(test)
|
||||
|
||||
@source_util.writes_bytecode_files
|
||||
@util.writes_bytecode_files
|
||||
def test_no_marshal(self):
|
||||
# When there is only the magic number and timestamp, raise EOFError.
|
||||
self._test_no_marshal()
|
||||
|
||||
@source_util.writes_bytecode_files
|
||||
@util.writes_bytecode_files
|
||||
def test_non_code_marshal(self):
|
||||
self._test_non_code_marshal()
|
||||
# XXX ImportError when sourceless
|
||||
|
||||
# [bad marshal]
|
||||
@source_util.writes_bytecode_files
|
||||
@util.writes_bytecode_files
|
||||
def test_bad_marshal(self):
|
||||
# Bad marshal data should raise a ValueError.
|
||||
self._test_bad_marshal()
|
||||
|
||||
# [bad timestamp]
|
||||
@source_util.writes_bytecode_files
|
||||
@util.writes_bytecode_files
|
||||
def test_old_timestamp(self):
|
||||
# When the timestamp is older than the source, bytecode should be
|
||||
# regenerated.
|
||||
zeros = b'\x00\x00\x00\x00'
|
||||
with source_util.create_modules('_temp') as mapping:
|
||||
with util.create_modules('_temp') as mapping:
|
||||
py_compile.compile(mapping['_temp'])
|
||||
bytecode_path = self.util.cache_from_source(mapping['_temp'])
|
||||
with open(bytecode_path, 'r+b') as bytecode_file:
|
||||
|
@ -471,10 +470,10 @@ class SourceLoaderBadBytecodeTest:
|
|||
self.assertEqual(bytecode_file.read(4), source_timestamp)
|
||||
|
||||
# [bytecode read-only]
|
||||
@source_util.writes_bytecode_files
|
||||
@util.writes_bytecode_files
|
||||
def test_read_only_bytecode(self):
|
||||
# When bytecode is read-only but should be rewritten, fail silently.
|
||||
with source_util.create_modules('_temp') as mapping:
|
||||
with util.create_modules('_temp') as mapping:
|
||||
# Create bytecode that will need to be re-created.
|
||||
py_compile.compile(mapping['_temp'])
|
||||
bytecode_path = self.util.cache_from_source(mapping['_temp'])
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
from .. import abc
|
||||
from .. import util
|
||||
from . import util as source_util
|
||||
|
||||
machinery = util.import_importlib('importlib.machinery')
|
||||
|
||||
|
@ -60,7 +59,7 @@ class FinderTests(abc.FinderTests):
|
|||
"""
|
||||
if create is None:
|
||||
create = {test}
|
||||
with source_util.create_modules(*create) as mapping:
|
||||
with util.create_modules(*create) as mapping:
|
||||
if compile_:
|
||||
for name in compile_:
|
||||
py_compile.compile(mapping[name])
|
||||
|
@ -100,14 +99,14 @@ class FinderTests(abc.FinderTests):
|
|||
|
||||
# [sub module]
|
||||
def test_module_in_package(self):
|
||||
with source_util.create_modules('pkg.__init__', 'pkg.sub') as mapping:
|
||||
with util.create_modules('pkg.__init__', 'pkg.sub') as mapping:
|
||||
pkg_dir = os.path.dirname(mapping['pkg.__init__'])
|
||||
loader = self.import_(pkg_dir, 'pkg.sub')
|
||||
self.assertTrue(hasattr(loader, 'load_module'))
|
||||
|
||||
# [sub package]
|
||||
def test_package_in_package(self):
|
||||
context = source_util.create_modules('pkg.__init__', 'pkg.sub.__init__')
|
||||
context = util.create_modules('pkg.__init__', 'pkg.sub.__init__')
|
||||
with context as mapping:
|
||||
pkg_dir = os.path.dirname(mapping['pkg.__init__'])
|
||||
loader = self.import_(pkg_dir, 'pkg.sub')
|
||||
|
@ -120,7 +119,7 @@ class FinderTests(abc.FinderTests):
|
|||
self.assertIn('__init__', loader.get_filename(name))
|
||||
|
||||
def test_failure(self):
|
||||
with source_util.create_modules('blah') as mapping:
|
||||
with util.create_modules('blah') as mapping:
|
||||
nothing = self.import_(mapping['.root'], 'sdfsadsadf')
|
||||
self.assertIsNone(nothing)
|
||||
|
||||
|
@ -147,7 +146,7 @@ class FinderTests(abc.FinderTests):
|
|||
# Regression test for http://bugs.python.org/issue14846
|
||||
def test_dir_removal_handling(self):
|
||||
mod = 'mod'
|
||||
with source_util.create_modules(mod) as mapping:
|
||||
with util.create_modules(mod) as mapping:
|
||||
finder = self.get_finder(mapping['.root'])
|
||||
found = self._find(finder, 'mod', loader_only=True)
|
||||
self.assertIsNotNone(found)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
from .. import util
|
||||
from . import util as source_util
|
||||
|
||||
machinery = util.import_importlib('importlib.machinery')
|
||||
|
||||
|
@ -15,7 +14,7 @@ class PathHookTest:
|
|||
self.machinery.SOURCE_SUFFIXES))
|
||||
|
||||
def test_success(self):
|
||||
with source_util.create_modules('dummy') as mapping:
|
||||
with util.create_modules('dummy') as mapping:
|
||||
self.assertTrue(hasattr(self.path_hook()(mapping['.root']),
|
||||
'find_module'))
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
from .. import util
|
||||
from . import util as source_util
|
||||
|
||||
machinery = util.import_importlib('importlib.machinery')
|
||||
|
||||
|
@ -37,7 +36,7 @@ class EncodingTest:
|
|||
module_name = '_temp'
|
||||
|
||||
def run_test(self, source):
|
||||
with source_util.create_modules(self.module_name) as mapping:
|
||||
with util.create_modules(self.module_name) as mapping:
|
||||
with open(mapping[self.module_name], 'wb') as file:
|
||||
file.write(source)
|
||||
loader = self.machinery.SourceFileLoader(self.module_name,
|
||||
|
@ -120,7 +119,7 @@ class LineEndingTest:
|
|||
module_name = '_temp'
|
||||
source_lines = [b"a = 42", b"b = -13", b'']
|
||||
source = line_ending.join(source_lines)
|
||||
with source_util.create_modules(module_name) as mapping:
|
||||
with util.create_modules(module_name) as mapping:
|
||||
with open(mapping[module_name], 'wb') as file:
|
||||
file.write(source)
|
||||
loader = self.machinery.SourceFileLoader(module_name,
|
||||
|
|
|
@ -1,96 +0,0 @@
|
|||
from .. import util
|
||||
import contextlib
|
||||
import errno
|
||||
import functools
|
||||
import os
|
||||
import os.path
|
||||
import sys
|
||||
import tempfile
|
||||
from test import support
|
||||
|
||||
|
||||
def writes_bytecode_files(fxn):
|
||||
"""Decorator to protect sys.dont_write_bytecode from mutation and to skip
|
||||
tests that require it to be set to False."""
|
||||
if sys.dont_write_bytecode:
|
||||
return lambda *args, **kwargs: None
|
||||
@functools.wraps(fxn)
|
||||
def wrapper(*args, **kwargs):
|
||||
original = sys.dont_write_bytecode
|
||||
sys.dont_write_bytecode = False
|
||||
try:
|
||||
to_return = fxn(*args, **kwargs)
|
||||
finally:
|
||||
sys.dont_write_bytecode = original
|
||||
return to_return
|
||||
return wrapper
|
||||
|
||||
|
||||
def ensure_bytecode_path(bytecode_path):
|
||||
"""Ensure that the __pycache__ directory for PEP 3147 pyc file exists.
|
||||
|
||||
:param bytecode_path: File system path to PEP 3147 pyc file.
|
||||
"""
|
||||
try:
|
||||
os.mkdir(os.path.dirname(bytecode_path))
|
||||
except OSError as error:
|
||||
if error.errno != errno.EEXIST:
|
||||
raise
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def create_modules(*names):
|
||||
"""Temporarily create each named module with an attribute (named 'attr')
|
||||
that contains the name passed into the context manager that caused the
|
||||
creation of the module.
|
||||
|
||||
All files are created in a temporary directory returned by
|
||||
tempfile.mkdtemp(). This directory is inserted at the beginning of
|
||||
sys.path. When the context manager exits all created files (source and
|
||||
bytecode) are explicitly deleted.
|
||||
|
||||
No magic is performed when creating packages! This means that if you create
|
||||
a module within a package you must also create the package's __init__ as
|
||||
well.
|
||||
|
||||
"""
|
||||
source = 'attr = {0!r}'
|
||||
created_paths = []
|
||||
mapping = {}
|
||||
state_manager = None
|
||||
uncache_manager = None
|
||||
try:
|
||||
temp_dir = tempfile.mkdtemp()
|
||||
mapping['.root'] = temp_dir
|
||||
import_names = set()
|
||||
for name in names:
|
||||
if not name.endswith('__init__'):
|
||||
import_name = name
|
||||
else:
|
||||
import_name = name[:-len('.__init__')]
|
||||
import_names.add(import_name)
|
||||
if import_name in sys.modules:
|
||||
del sys.modules[import_name]
|
||||
name_parts = name.split('.')
|
||||
file_path = temp_dir
|
||||
for directory in name_parts[:-1]:
|
||||
file_path = os.path.join(file_path, directory)
|
||||
if not os.path.exists(file_path):
|
||||
os.mkdir(file_path)
|
||||
created_paths.append(file_path)
|
||||
file_path = os.path.join(file_path, name_parts[-1] + '.py')
|
||||
with open(file_path, 'w') as file:
|
||||
file.write(source.format(name))
|
||||
created_paths.append(file_path)
|
||||
mapping[name] = file_path
|
||||
uncache_manager = util.uncache(*import_names)
|
||||
uncache_manager.__enter__()
|
||||
state_manager = util.import_state(path=[temp_dir])
|
||||
state_manager.__enter__()
|
||||
yield mapping
|
||||
finally:
|
||||
if state_manager is not None:
|
||||
state_manager.__exit__(None, None, None)
|
||||
if uncache_manager is not None:
|
||||
uncache_manager.__exit__(None, None, None)
|
||||
support.rmtree(temp_dir)
|
Loading…
Add table
Add a link
Reference in a new issue