Skip to content

Commit c2baf11

Browse files
committed
test: move import_helper out
1 parent 1269c7f commit c2baf11

File tree

2 files changed

+356
-224
lines changed

2 files changed

+356
-224
lines changed

Lib/test/support/__init__.py

Lines changed: 1 addition & 224 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,7 @@
7979
# exceptions
8080
"Error", "TestFailed", "TestDidNotRun", "ResourceDenied",
8181
# imports
82-
"import_module", "import_fresh_module", "CleanImport",
8382
# modules
84-
"unload", "forget",
8583
# io
8684
"record_original_stdout", "get_original_stdout", "captured_stdout",
8785
"captured_stdin", "captured_stderr",
@@ -198,21 +196,6 @@ class ResourceDenied(unittest.SkipTest):
198196
and unexpected skips.
199197
"""
200198

201-
@contextlib.contextmanager
202-
def _ignore_deprecated_imports(ignore=True):
203-
"""Context manager to suppress package and module deprecation
204-
warnings when importing them.
205-
206-
If ignore is False, this context manager has no effect.
207-
"""
208-
if ignore:
209-
with warnings.catch_warnings():
210-
warnings.filterwarnings("ignore", ".+ (module|package)",
211-
DeprecationWarning)
212-
yield
213-
else:
214-
yield
215-
216199

217200
def ignore_warnings(*, category):
218201
"""Decorator to suppress deprecation warnings.
@@ -230,52 +213,6 @@ def wrapper(self, *args, **kwargs):
230213
return decorator
231214

232215

233-
def import_module(name, deprecated=False, *, required_on=()):
234-
"""Import and return the module to be tested, raising SkipTest if
235-
it is not available.
236-
237-
If deprecated is True, any module or package deprecation messages
238-
will be suppressed. If a module is required on a platform but optional for
239-
others, set required_on to an iterable of platform prefixes which will be
240-
compared against sys.platform.
241-
"""
242-
with _ignore_deprecated_imports(deprecated):
243-
try:
244-
return importlib.import_module(name)
245-
except ImportError as msg:
246-
if sys.platform.startswith(tuple(required_on)):
247-
raise
248-
raise unittest.SkipTest(str(msg))
249-
250-
251-
def _save_and_remove_module(name, orig_modules):
252-
"""Helper function to save and remove a module from sys.modules
253-
254-
Raise ImportError if the module can't be imported.
255-
"""
256-
# try to import the module and raise an error if it can't be imported
257-
if name not in sys.modules:
258-
__import__(name)
259-
del sys.modules[name]
260-
for modname in list(sys.modules):
261-
if modname == name or modname.startswith(name + '.'):
262-
orig_modules[modname] = sys.modules[modname]
263-
del sys.modules[modname]
264-
265-
def _save_and_block_module(name, orig_modules):
266-
"""Helper function to save and block a module in sys.modules
267-
268-
Return True if the module was in sys.modules, False otherwise.
269-
"""
270-
saved = True
271-
try:
272-
orig_modules[name] = sys.modules[name]
273-
except KeyError:
274-
saved = False
275-
sys.modules[name] = None
276-
return saved
277-
278-
279216
def anticipate_failure(condition):
280217
"""Decorator to mark a test that is known to be broken in some cases
281218
@@ -304,56 +241,6 @@ def load_tests(*args):
304241
return standard_tests
305242

306243

307-
def import_fresh_module(name, fresh=(), blocked=(), deprecated=False):
308-
"""Import and return a module, deliberately bypassing sys.modules.
309-
310-
This function imports and returns a fresh copy of the named Python module
311-
by removing the named module from sys.modules before doing the import.
312-
Note that unlike reload, the original module is not affected by
313-
this operation.
314-
315-
*fresh* is an iterable of additional module names that are also removed
316-
from the sys.modules cache before doing the import.
317-
318-
*blocked* is an iterable of module names that are replaced with None
319-
in the module cache during the import to ensure that attempts to import
320-
them raise ImportError.
321-
322-
The named module and any modules named in the *fresh* and *blocked*
323-
parameters are saved before starting the import and then reinserted into
324-
sys.modules when the fresh import is complete.
325-
326-
Module and package deprecation messages are suppressed during this import
327-
if *deprecated* is True.
328-
329-
This function will raise ImportError if the named module cannot be
330-
imported.
331-
"""
332-
# NOTE: test_heapq, test_json and test_warnings include extra sanity checks
333-
# to make sure that this utility function is working as expected
334-
with _ignore_deprecated_imports(deprecated):
335-
# Keep track of modules saved for later restoration as well
336-
# as those which just need a blocking entry removed
337-
orig_modules = {}
338-
names_to_remove = []
339-
_save_and_remove_module(name, orig_modules)
340-
try:
341-
for fresh_name in fresh:
342-
_save_and_remove_module(fresh_name, orig_modules)
343-
for blocked_name in blocked:
344-
if not _save_and_block_module(blocked_name, orig_modules):
345-
names_to_remove.append(blocked_name)
346-
fresh_module = importlib.import_module(name)
347-
except ImportError:
348-
fresh_module = None
349-
finally:
350-
for orig_name, module in orig_modules.items():
351-
sys.modules[orig_name] = module
352-
for name_to_remove in names_to_remove:
353-
del sys.modules[name_to_remove]
354-
return fresh_module
355-
356-
357244
def get_attribute(obj, name):
358245
"""Get an attribute, raising SkipTest if AttributeError is raised."""
359246
try:
@@ -382,12 +269,6 @@ def record_original_stdout(stdout):
382269
def get_original_stdout():
383270
return _original_stdout or sys.stdout
384271

385-
def unload(name):
386-
try:
387-
del sys.modules[name]
388-
except KeyError:
389-
pass
390-
391272
def _force_run(path, func, *args):
392273
try:
393274
return func(*args)
@@ -528,34 +409,6 @@ def rmtree(path):
528409
except FileNotFoundError:
529410
pass
530411

531-
def make_legacy_pyc(source):
532-
"""Move a PEP 3147/488 pyc file to its legacy pyc location.
533-
534-
:param source: The file system path to the source file. The source file
535-
does not need to exist, however the PEP 3147/488 pyc file must exist.
536-
:return: The file system path to the legacy pyc file.
537-
"""
538-
pyc_file = importlib.util.cache_from_source(source)
539-
up_one = os.path.dirname(os.path.abspath(source))
540-
legacy_pyc = os.path.join(up_one, source + 'c')
541-
os.rename(pyc_file, legacy_pyc)
542-
return legacy_pyc
543-
544-
def forget(modname):
545-
"""'Forget' a module was ever imported.
546-
547-
This removes the module from sys.modules and deletes any PEP 3147/488 or
548-
legacy .pyc files.
549-
"""
550-
unload(modname)
551-
for dirname in sys.path:
552-
source = os.path.join(dirname, modname + '.py')
553-
# It doesn't matter if they exist or not, unlink all possible
554-
# combinations of PEP 3147/488 and legacy pyc files.
555-
unlink(source + 'c')
556-
for opt in ('', 1, 2):
557-
unlink(importlib.util.cache_from_source(source, optimization=opt))
558-
559412
# Check whether a gui is actually available
560413
def _is_gui_available():
561414
if hasattr(_is_gui_available, 'result'):
@@ -1225,62 +1078,6 @@ def check_no_resource_warning(testcase):
12251078
yield
12261079

12271080

1228-
class CleanImport(object):
1229-
"""Context manager to force import to return a new module reference.
1230-
1231-
This is useful for testing module-level behaviours, such as
1232-
the emission of a DeprecationWarning on import.
1233-
1234-
Use like this:
1235-
1236-
with CleanImport("foo"):
1237-
importlib.import_module("foo") # new reference
1238-
"""
1239-
1240-
def __init__(self, *module_names):
1241-
self.original_modules = sys.modules.copy()
1242-
for module_name in module_names:
1243-
if module_name in sys.modules:
1244-
module = sys.modules[module_name]
1245-
# It is possible that module_name is just an alias for
1246-
# another module (e.g. stub for modules renamed in 3.x).
1247-
# In that case, we also need delete the real module to clear
1248-
# the import cache.
1249-
if module.__name__ != module_name:
1250-
del sys.modules[module.__name__]
1251-
del sys.modules[module_name]
1252-
1253-
def __enter__(self):
1254-
return self
1255-
1256-
def __exit__(self, *ignore_exc):
1257-
sys.modules.update(self.original_modules)
1258-
1259-
1260-
class DirsOnSysPath(object):
1261-
"""Context manager to temporarily add directories to sys.path.
1262-
1263-
This makes a copy of sys.path, appends any directories given
1264-
as positional arguments, then reverts sys.path to the copied
1265-
settings when the context ends.
1266-
1267-
Note that *all* sys.path modifications in the body of the
1268-
context manager, including replacement of the object,
1269-
will be reverted at the end of the block.
1270-
"""
1271-
1272-
def __init__(self, *paths):
1273-
self.original_value = sys.path[:]
1274-
self.original_object = sys.path
1275-
sys.path.extend(paths)
1276-
1277-
def __enter__(self):
1278-
return self
1279-
1280-
def __exit__(self, *ignore_exc):
1281-
sys.path = self.original_object
1282-
sys.path[:] = self.original_value
1283-
12841081

12851082
class TransientResource(object):
12861083

@@ -2024,25 +1821,6 @@ def print_warning(msg):
20241821
# log warnings even if sys.stderr is captured temporarily by a test.
20251822
print_warning.orig_stderr = sys.stderr
20261823

2027-
def modules_setup():
2028-
return sys.modules.copy(),
2029-
2030-
def modules_cleanup(oldmodules):
2031-
# Encoders/decoders are registered permanently within the internal
2032-
# codec cache. If we destroy the corresponding modules their
2033-
# globals will be set to None which will trip up the cached functions.
2034-
encodings = [(k, v) for k, v in sys.modules.items()
2035-
if k.startswith('encodings.')]
2036-
sys.modules.clear()
2037-
sys.modules.update(encodings)
2038-
# XXX: This kind of problem can affect more than just encodings. In particular
2039-
# extension modules (such as _ssl) don't cope with reloading properly.
2040-
# Really, test modules should be cleaning out the test specific modules they
2041-
# know they added (ala test_runpy) rather than relying on this function (as
2042-
# test_importhooks and test_pkg do currently).
2043-
# Implicitly imported *real* modules should be left alone (see issue 10556).
2044-
sys.modules.update(oldmodules)
2045-
20461824
#=======================================================================
20471825
# Threading support to prevent reporting refleaks when running regrtest.py -R
20481826

@@ -2075,8 +1853,7 @@ def threading_cleanup(*original_values):
20751853
if values == original_values:
20761854
break
20771855

2078-
if not count:
2079-
# Display a warning at the first iteration
1856+
if not count: # Display a warning at the first iteration
20801857
environment_altered = True
20811858
dangling_threads = values[1]
20821859
print_warning(f"threading_cleanup() failed to cleanup "

0 commit comments

Comments
 (0)