Introduce importlib.util.ModuleManager which is a context manager to

handle providing (and cleaning up if needed) the module to be loaded.

A future commit will use the context manager in
Lib/importlib/_bootstrap.py and thus why the code is placed there
instead of in Lib/importlib/util.py.
This commit is contained in:
Brett Cannon 2013-05-28 17:29:34 -04:00
parent 4dbae88131
commit a3687f0d68
6 changed files with 3508 additions and 3341 deletions

View file

@ -9,7 +9,7 @@ work. One should use importlib as the public-facing version of this module.
#
# IMPORTANT: Whenever making changes to this module, be sure to run
# a top-level make in order to get the frozen version of the module
# update. Not doing so, will result in the Makefile to fail for
# update. Not doing so will result in the Makefile to fail for
# all others who don't have a ./python around to freeze the module
# in the early stages of compilation.
#
@ -20,10 +20,6 @@ work. One should use importlib as the public-facing version of this module.
# reference any injected objects! This includes not only global code but also
# anything specified at the class level.
# XXX Make sure all public names have no single leading underscore and all
# others do.
# Bootstrap-related code ######################################################
_CASE_INSENSITIVE_PLATFORMS = 'win', 'cygwin', 'darwin'
@ -498,6 +494,38 @@ def _verbose_message(message, *args, verbosity=1):
print(message.format(*args), file=sys.stderr)
class ModuleManager:
"""Context manager which returns the module to be loaded.
Does the proper unloading from sys.modules upon failure.
"""
def __init__(self, name):
self._name = name
def __enter__(self):
self._module = sys.modules.get(self._name)
self._is_reload = self._module is not None
if not self._is_reload:
# This must be done before open() is called as the 'io' module
# implicitly imports 'locale' and would otherwise trigger an
# infinite loop.
self._module = new_module(self._name)
# This must be done before putting the module in sys.modules
# (otherwise an optimization shortcut in import.c becomes wrong)
self._module.__initializing__ = True
sys.modules[self._name] = self._module
return self._module
def __exit__(self, *args):
self._module.__initializing__ = False
del self._module
if any(arg is not None for arg in args) and not self._is_reload:
del sys.modules[self._name]
def set_package(fxn):
"""Set __package__ on the returned module."""
def set_package_wrapper(*args, **kwargs):