diff options
author | Eric Snow <ericsnowcurrently@gmail.com> | 2021-09-14 23:31:45 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-14 23:31:45 (GMT) |
commit | a65c86889e208dddb26a7ebe7840c24edbcca775 (patch) | |
tree | ec55222c3ac183806fc06f0d60514ab21e6dc560 /Lib/test/support | |
parent | 1aaa85949717e4ab2ed700e58762f0a3ce049a37 (diff) | |
download | cpython-a65c86889e208dddb26a7ebe7840c24edbcca775.zip cpython-a65c86889e208dddb26a7ebe7840c24edbcca775.tar.gz cpython-a65c86889e208dddb26a7ebe7840c24edbcca775.tar.bz2 |
bpo-45020: Add -X frozen_modules=[on|off] to explicitly control use of frozen modules. (gh-28320)
Currently we freeze several modules into the runtime. For each of these modules it is essential to bootstrapping the runtime that they be frozen. Any other stdlib module that we later freeze into the runtime is not essential. We can just as well import from the .py file. This PR lets users explicitly choose which should be used, with the new "-X frozen_modules=[on|off]" CLI flag. The default is "off" for now.
https://bugs.python.org/issue45020
Diffstat (limited to 'Lib/test/support')
-rw-r--r-- | Lib/test/support/import_helper.py | 34 | ||||
-rw-r--r-- | Lib/test/support/os_helper.py | 4 |
2 files changed, 35 insertions, 3 deletions
diff --git a/Lib/test/support/import_helper.py b/Lib/test/support/import_helper.py index 5d1e940..10f745a 100644 --- a/Lib/test/support/import_helper.py +++ b/Lib/test/support/import_helper.py @@ -1,4 +1,5 @@ import contextlib +import _imp import importlib import importlib.util import os @@ -109,7 +110,24 @@ def _save_and_block_module(name, orig_modules): return saved -def import_fresh_module(name, fresh=(), blocked=(), deprecated=False): +@contextlib.contextmanager +def frozen_modules(enabled=True): + """Force frozen modules to be used (or not). + + This only applies to modules that haven't been imported yet. + Also, some essential modules will always be imported frozen. + """ + _imp._override_frozen_modules_for_tests(1 if enabled else -1) + try: + yield + finally: + _imp._override_frozen_modules_for_tests(0) + + +def import_fresh_module(name, fresh=(), blocked=(), *, + deprecated=False, + usefrozen=False, + ): """Import and return a module, deliberately bypassing sys.modules. This function imports and returns a fresh copy of the named Python module @@ -133,6 +151,9 @@ def import_fresh_module(name, fresh=(), blocked=(), deprecated=False): This function will raise ImportError if the named module cannot be imported. + + If "usefrozen" is False (the default) then the frozen importer is + disabled (except for essential modules like importlib._bootstrap). """ # NOTE: test_heapq, test_json and test_warnings include extra sanity checks # to make sure that this utility function is working as expected @@ -148,7 +169,8 @@ def import_fresh_module(name, fresh=(), blocked=(), deprecated=False): for blocked_name in blocked: if not _save_and_block_module(blocked_name, orig_modules): names_to_remove.append(blocked_name) - fresh_module = importlib.import_module(name) + with frozen_modules(usefrozen): + fresh_module = importlib.import_module(name) except ImportError: fresh_module = None finally: @@ -169,9 +191,12 @@ class CleanImport(object): with CleanImport("foo"): importlib.import_module("foo") # new reference + + If "usefrozen" is False (the default) then the frozen importer is + disabled (except for essential modules like importlib._bootstrap). """ - def __init__(self, *module_names): + def __init__(self, *module_names, usefrozen=False): self.original_modules = sys.modules.copy() for module_name in module_names: if module_name in sys.modules: @@ -183,12 +208,15 @@ class CleanImport(object): if module.__name__ != module_name: del sys.modules[module.__name__] del sys.modules[module_name] + self._frozen_modules = frozen_modules(usefrozen) def __enter__(self): + self._frozen_modules.__enter__() return self def __exit__(self, *ignore_exc): sys.modules.update(self.original_modules) + self._frozen_modules.__exit__(*ignore_exc) class DirsOnSysPath(object): diff --git a/Lib/test/support/os_helper.py b/Lib/test/support/os_helper.py index d9807a1..ce01417 100644 --- a/Lib/test/support/os_helper.py +++ b/Lib/test/support/os_helper.py @@ -599,6 +599,10 @@ class EnvironmentVarGuard(collections.abc.MutableMapping): def unset(self, envvar): del self[envvar] + def copy(self): + # We do what os.environ.copy() does. + return dict(self) + def __enter__(self): return self |