Commit ce43ddfe authored by Brett Cannon's avatar Brett Cannon

Do a little bit of reorganization on importlib._bootstrap.

parent 3eeaa0a8
...@@ -16,6 +16,8 @@ work. One should use importlib as the public-facing version of this module. ...@@ -16,6 +16,8 @@ work. One should use importlib as the public-facing version of this module.
# anything specified at the class level. # anything specified at the class level.
# Bootstrap-related code ######################################################
# XXX Could also expose Modules/getpath.c:joinpath() # XXX Could also expose Modules/getpath.c:joinpath()
def _path_join(*args): def _path_join(*args):
"""Replacement for os.path.join.""" """Replacement for os.path.join."""
...@@ -97,6 +99,8 @@ def _wrap(new, old): ...@@ -97,6 +99,8 @@ def _wrap(new, old):
new.__dict__.update(old.__dict__) new.__dict__.update(old.__dict__)
# Finder/loader utility code ##################################################
def set_package(fxn): def set_package(fxn):
"""Set __package__ on the returned module.""" """Set __package__ on the returned module."""
def wrapper(*args, **kwargs): def wrapper(*args, **kwargs):
...@@ -121,6 +125,56 @@ def set_loader(fxn): ...@@ -121,6 +125,56 @@ def set_loader(fxn):
return wrapper return wrapper
def module_for_loader(fxn):
"""Decorator to handle selecting the proper module for loaders.
Decorated modules are passed the module to use instead of the module name.
The module is either from sys.modules if it already exists (for reloading)
or is a new module which has __name__ set. If any exception is raised by
the decorated method and the decorator added a module to sys.modules, then
the module is deleted from sys.modules.
The decorator assumes that the decorated method takes self/cls as a first
argument and the module as the second argument.
"""
def decorated(self, fullname):
module = sys.modules.get(fullname)
is_reload = bool(module)
if not is_reload:
# This must be done before open() is called as the 'io' module
# implicitly imports 'locale' and would otherwise trigger an
# infinite loop.
module = imp.new_module(fullname)
sys.modules[fullname] = module
try:
return fxn(self, module)
except:
if not is_reload:
del sys.modules[fullname]
raise
_wrap(decorated, fxn)
return decorated
def _check_name(method):
"""Decorator to verify that the module being requested matches the one the
loader can handle.
The first argument (self) must define _name which the second argument is
comapred against. If the comparison fails then ImportError is raised.
"""
def inner(self, name, *args, **kwargs):
if self._name != name:
raise ImportError("loader cannot handle %s" % name)
return method(self, name, *args, **kwargs)
_wrap(inner, method)
return inner
# Finders/loaders #############################################################
class BuiltinImporter: class BuiltinImporter:
"""Meta path loader for built-in modules. """Meta path loader for built-in modules.
...@@ -224,21 +278,6 @@ class _ChainedFinder: ...@@ -224,21 +278,6 @@ class _ChainedFinder:
return None return None
def _check_name(method):
"""Decorator to verify that the module being requested matches the one the
loader can handle.
The first argument (self) must define _name which the second argument is
comapred against. If the comparison fails then ImportError is raised.
"""
def inner(self, name, *args, **kwargs):
if self._name != name:
raise ImportError("loader cannot handle %s" % name)
return method(self, name, *args, **kwargs)
_wrap(inner, method)
return inner
class _ExtensionFileLoader: class _ExtensionFileLoader:
...@@ -295,37 +334,6 @@ def _suffix_list(suffix_type): ...@@ -295,37 +334,6 @@ def _suffix_list(suffix_type):
if suffix[2] == suffix_type] if suffix[2] == suffix_type]
def module_for_loader(fxn):
"""Decorator to handle selecting the proper module for loaders.
Decorated modules are passed the module to use instead of the module name.
The module is either from sys.modules if it already exists (for reloading)
or is a new module which has __name__ set. If any exception is raised by
the decorated method and the decorator added a module to sys.modules, then
the module is deleted from sys.modules.
The decorator assumes that the decorated method takes self/cls as a first
argument and the module as the second argument.
"""
def decorated(self, fullname):
module = sys.modules.get(fullname)
is_reload = bool(module)
if not is_reload:
# This must be done before open() is called as the 'io' module
# implicitly imports 'locale' and would otherwise trigger an
# infinite loop.
module = imp.new_module(fullname)
sys.modules[fullname] = module
try:
return fxn(self, module)
except:
if not is_reload:
del sys.modules[fullname]
raise
_wrap(decorated, fxn)
return decorated
class PyLoader: class PyLoader:
...@@ -738,6 +746,21 @@ class PathFinder: ...@@ -738,6 +746,21 @@ class PathFinder:
return None return None
# Import itself ###############################################################
class _ImportLockContext:
"""Context manager for the import lock."""
def __enter__(self):
"""Acquire the import lock."""
imp.acquire_lock()
def __exit__(self, exc_type, exc_value, exc_traceback):
"""Release the import lock regardless of any raised exceptions."""
imp.release_lock()
_DEFAULT_PATH_HOOK = _chained_path_hook(ExtensionFileFinder, PyPycFileFinder) _DEFAULT_PATH_HOOK = _chained_path_hook(ExtensionFileFinder, PyPycFileFinder)
class _DefaultPathFinder(PathFinder): class _DefaultPathFinder(PathFinder):
...@@ -761,18 +784,6 @@ class _DefaultPathFinder(PathFinder): ...@@ -761,18 +784,6 @@ class _DefaultPathFinder(PathFinder):
return super()._path_importer_cache(path, _DEFAULT_PATH_HOOK) return super()._path_importer_cache(path, _DEFAULT_PATH_HOOK)
class _ImportLockContext:
"""Context manager for the import lock."""
def __enter__(self):
"""Acquire the import lock."""
imp.acquire_lock()
def __exit__(self, exc_type, exc_value, exc_traceback):
"""Release the import lock regardless of any raised exceptions."""
imp.release_lock()
_IMPLICIT_META_PATH = [BuiltinImporter, FrozenImporter, _DefaultPathFinder] _IMPLICIT_META_PATH = [BuiltinImporter, FrozenImporter, _DefaultPathFinder]
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment