Split out support code that is specific to source tests out of

importlib.test.support to importlib.test.source.util.
This commit is contained in:
Brett Cannon 2009-02-01 03:08:31 +00:00
parent 30b047dc35
commit 4ee2cdaf65
8 changed files with 123 additions and 113 deletions

View file

@ -3,9 +3,6 @@ to do
* Reorganize support code.
+ Separate general support code and importer-specific (e.g. source) support
code.
- Create support modules for each subdirectory (as needed).
+ Add a file loader mock that returns monotonically increasing mtime.
- Use in source/test_reload.
- Use in source/test_load_module_mixed.

View file

@ -1,6 +1,7 @@
"""Test case-sensitivity (PEP 235)."""
import importlib
from .. import support
from . import util as source_util
import os
import sys
from test import support as test_support
@ -25,7 +26,8 @@ def sensitivity_test(self):
"""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())
with support.create_modules(insensitive_pkg, sensitive_pkg) as mapping:
context = source_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')
return self.find(sensitive_path), self.find(insensitive_path)

View file

@ -1,6 +1,7 @@
import importlib
from .. import abc
from .. import support
from . import util as source_util
import os
import py_compile
import unittest
@ -45,7 +46,7 @@ def run_test(self, test, create=None, *, compile_=None, unlink=None):
"""
if create is None:
create = {test}
with support.create_modules(*create) as mapping:
with source_util.create_modules(*create) as mapping:
if compile_:
for name in compile_:
py_compile.compile(mapping[name])
@ -76,14 +77,14 @@ def test_package(self):
# [sub module]
def test_module_in_package(self):
with support.create_modules('pkg.__init__', 'pkg.sub') as mapping:
with source_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.assert_(hasattr(loader, 'load_module'))
# [sub package]
def test_package_in_package(self):
context = support.create_modules('pkg.__init__', 'pkg.sub.__init__')
context = source_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')
@ -91,7 +92,7 @@ def test_package_in_package(self):
# [sub empty]
def test_empty_sub_directory(self):
context = support.create_modules('pkg.__init__', 'pkg.sub.__init__')
context = source_util.create_modules('pkg.__init__', 'pkg.sub.__init__')
with warnings.catch_warnings():
warnings.simplefilter("error", ImportWarning)
with context as mapping:
@ -109,7 +110,7 @@ def test_package_over_module(self):
def test_failure(self):
with support.create_modules('blah') as mapping:
with source_util.create_modules('blah') as mapping:
nothing = self.import_(mapping['.root'], 'sdfsadsadf')
self.assert_(nothing is None)

View file

@ -1,6 +1,7 @@
import importlib
from .. import abc
from .. import support
from . import util as source_util
import imp
import os
@ -18,7 +19,7 @@ class SimpleTest(unittest.TestCase):
# [basic]
def test_module(self):
with support.create_modules('_temp') as mapping:
with source_util.create_modules('_temp') as mapping:
loader = importlib._PyFileLoader('_temp', mapping['_temp'], False)
module = loader.load_module('_temp')
self.assert_('_temp' in sys.modules)
@ -28,7 +29,7 @@ def test_module(self):
self.assertEqual(getattr(module, attr), value)
def test_package(self):
with support.create_modules('_pkg.__init__') as mapping:
with source_util.create_modules('_pkg.__init__') as mapping:
loader = importlib._PyFileLoader('_pkg', mapping['_pkg.__init__'],
True)
module = loader.load_module('_pkg')
@ -41,7 +42,7 @@ def test_package(self):
def test_lacking_parent(self):
with support.create_modules('_pkg.__init__', '_pkg.mod')as mapping:
with source_util.create_modules('_pkg.__init__', '_pkg.mod')as mapping:
loader = importlib._PyFileLoader('_pkg.mod', mapping['_pkg.mod'],
False)
module = loader.load_module('_pkg.mod')
@ -56,7 +57,7 @@ def fake_mtime(self, fxn):
return lambda name: fxn(name) + 1
def test_module_reuse(self):
with support.create_modules('_temp') as mapping:
with source_util.create_modules('_temp') as mapping:
loader = importlib._PyFileLoader('_temp', mapping['_temp'], False)
module = loader.load_module('_temp')
module_id = id(module)
@ -81,7 +82,7 @@ def test_state_after_failure(self):
attributes = ('__file__', '__path__', '__package__')
value = '<test>'
name = '_temp'
with support.create_modules(name) as mapping:
with source_util.create_modules(name) as mapping:
orig_module = imp.new_module(name)
for attr in attributes:
setattr(orig_module, attr, value)
@ -94,7 +95,7 @@ def test_state_after_failure(self):
# [syntax error]
def test_bad_syntax(self):
with support.create_modules('_temp') as mapping:
with source_util.create_modules('_temp') as mapping:
with open(mapping['_temp'], 'w') as file:
file.write('=')
loader = importlib._PyFileLoader('_temp', mapping['_temp'], False)
@ -109,12 +110,12 @@ class DontWriteBytecodeTest(unittest.TestCase):
def tearDown(self):
sys.dont_write_bytecode = False
@support.writes_bytecode
@source_util.writes_bytecode
def run_test(self, assertion):
with support.create_modules('_temp') as mapping:
with source_util.create_modules('_temp') as mapping:
loader = importlib._PyFileLoader('_temp', mapping['_temp'], False)
loader.load_module('_temp')
bytecode_path = support.bytecode_path(mapping['_temp'])
bytecode_path = source_util.bytecode_path(mapping['_temp'])
assertion(bytecode_path)
def test_bytecode_written(self):
@ -137,10 +138,10 @@ class BadDataTest(unittest.TestCase):
# [bad magic]
def test_bad_magic(self):
with support.create_modules('_temp') as mapping:
with source_util.create_modules('_temp') as mapping:
py_compile.compile(mapping['_temp'])
os.unlink(mapping['_temp'])
bytecode_path = support.bytecode_path(mapping['_temp'])
bytecode_path = source_util.bytecode_path(mapping['_temp'])
with open(bytecode_path, 'r+b') as file:
file.seek(0)
file.write(b'\x00\x00\x00\x00')
@ -164,7 +165,7 @@ def import_(self, file, module, *, pkg=False):
def run_test(self, test, *create, pkg=False):
create += (test,)
with support.create_modules(*create) as mapping:
with source_util.create_modules(*create) as mapping:
for name in create:
py_compile.compile(mapping[name])
if pkg:
@ -217,11 +218,11 @@ def import_(self, file, module_name):
self.assert_(module_name in sys.modules)
# [bad magic]
@support.writes_bytecode
@source_util.writes_bytecode
def test_bad_magic(self):
with support.create_modules('_temp') as mapping:
with source_util.create_modules('_temp') as mapping:
py_compile.compile(mapping['_temp'])
bytecode_path = support.bytecode_path(mapping['_temp'])
bytecode_path = source_util.bytecode_path(mapping['_temp'])
with open(bytecode_path, 'r+b') as bytecode_file:
bytecode_file.seek(0)
bytecode_file.write(b'\x00\x00\x00\x00')
@ -230,12 +231,12 @@ def test_bad_magic(self):
self.assertEqual(bytecode_file.read(4), imp.get_magic())
# [bad timestamp]
@support.writes_bytecode
@source_util.writes_bytecode
def test_bad_bytecode(self):
zeros = b'\x00\x00\x00\x00'
with support.create_modules('_temp') as mapping:
with source_util.create_modules('_temp') as mapping:
py_compile.compile(mapping['_temp'])
bytecode_path = support.bytecode_path(mapping['_temp'])
bytecode_path = source_util.bytecode_path(mapping['_temp'])
with open(bytecode_path, 'r+b') as bytecode_file:
bytecode_file.seek(4)
bytecode_file.write(zeros)
@ -248,8 +249,8 @@ def test_bad_bytecode(self):
# [bad marshal]
def test_bad_marshal(self):
with support.create_modules('_temp') as mapping:
bytecode_path = support.bytecode_path(mapping['_temp'])
with source_util.create_modules('_temp') as mapping:
bytecode_path = source_util.bytecode_path(mapping['_temp'])
source_mtime = os.path.getmtime(mapping['_temp'])
source_timestamp = importlib._w_long(source_mtime)
with open(bytecode_path, 'wb') as bytecode_file:

View file

@ -1,5 +1,5 @@
import importlib
from .. import support
from . import util
import unittest
@ -9,7 +9,7 @@ class PathHookTest(unittest.TestCase):
def test_success(self):
# XXX Only work on existing directories?
with support.create_modules('dummy') as mapping:
with util.create_modules('dummy') as mapping:
self.assert_(hasattr(importlib.FileImporter(mapping['.root']),
'find_module'))

View file

@ -1,5 +1,6 @@
import importlib
from .. import support
from . import util as source_util
import codecs
import re
@ -32,7 +33,7 @@ class EncodingTest(unittest.TestCase):
module_name = '_temp'
def run_test(self, source):
with support.create_modules(self.module_name) as mapping:
with source_util.create_modules(self.module_name) as mapping:
with open(mapping[self.module_name], 'wb')as file:
file.write(source)
loader = importlib._PyFileLoader(self.module_name,
@ -93,7 +94,7 @@ def run_test(self, line_ending):
module_name = '_temp'
source_lines = [b"a = 42", b"b = -13", b'']
source = line_ending.join(source_lines)
with support.create_modules(module_name) as mapping:
with source_util.create_modules(module_name) as mapping:
with open(mapping[module_name], 'wb') as file:
file.write(source)
loader = importlib._PyFileLoader(module_name, mapping[module_name],

View file

@ -0,0 +1,88 @@
from .. import support as util
import contextlib
import imp
import os
import os.path
import sys
import tempfile
from test import support as support
def writes_bytecode(fxn):
"""Decorator that returns the function if writing bytecode is enabled, else
a stub function that accepts anything and simply returns None."""
if sys.dont_write_bytecode:
return lambda *args, **kwargs: None
else:
return fxn
def bytecode_path(source_path):
for suffix, _, type_ in imp.get_suffixes():
if type_ == imp.PY_COMPILED:
bc_suffix = suffix
break
else:
raise ValueError("no bytecode suffix is defined")
return os.path.splitext(source_path)[0] + bc_suffix
@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 specified by
tempfile.gettempdir(). 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 = {}
try:
temp_dir = tempfile.gettempdir()
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:
state_manager.__exit__(None, None, None)
uncache_manager.__exit__(None, None, None)
# Reverse the order for path removal to unroll directory creation.
for path in reversed(created_paths):
if file_path.endswith('.py'):
support.unlink(path)
support.unlink(path + 'c')
support.unlink(path + 'o')
else:
os.rmdir(path)

View file

@ -6,7 +6,6 @@
import os.path
from test.support import unlink
import sys
from tempfile import gettempdir
using___import__ = False
@ -28,14 +27,6 @@ def inner(*args, **kwargs):
update_wrapper(inner, fxn)
return inner
def writes_bytecode(fxn):
"""Decorator that returns the function if writing bytecode is enabled, else
a stub function that accepts anything and simply returns None."""
if sys.dont_write_bytecode:
return lambda *args, **kwargs: None
else:
return fxn
def case_insensitive_tests(class_):
"""Class decorator that nullifies tests that require a case-insensitive
@ -102,67 +93,6 @@ def import_state(**kwargs):
setattr(sys, attr, value)
@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 specified by
tempfile.gettempdir(). 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 = {}
try:
temp_dir = gettempdir()
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 = uncache(*import_names)
uncache_manager.__enter__()
state_manager = import_state(path=[temp_dir])
state_manager.__enter__()
yield mapping
finally:
state_manager.__exit__(None, None, None)
uncache_manager.__exit__(None, None, None)
# Reverse the order for path removal to unroll directory creation.
for path in reversed(created_paths):
if file_path.endswith('.py'):
unlink(path)
unlink(path + 'c')
unlink(path + 'o')
else:
os.rmdir(path)
class mock_modules:
"""A mock importer/loader."""
@ -221,13 +151,3 @@ def hook(entry):
raise ImportError
return importer
return hook
def bytecode_path(source_path):
for suffix, _, type_ in imp.get_suffixes():
if type_ == imp.PY_COMPILED:
bc_suffix = suffix
break
else:
raise ValueError("no bytecode suffix is defined")
return os.path.splitext(source_path)[0] + bc_suffix