mirror of https://github.com/python/cpython.git
Initial, untested stab at writing a common denominator function for __import__
and import_module.
This commit is contained in:
parent
5c6d7877c5
commit
7f9876c0da
|
@ -15,6 +15,19 @@ to do
|
||||||
|
|
||||||
+ Create a greatest common denominator function for __import__/import_module
|
+ Create a greatest common denominator function for __import__/import_module
|
||||||
that takes in an absolute module name and performs the import.
|
that takes in an absolute module name and performs the import.
|
||||||
|
|
||||||
|
- Needs of __import__
|
||||||
|
|
||||||
|
* Figure out caller's package.
|
||||||
|
* Import module.
|
||||||
|
* Set __package__.
|
||||||
|
* Figure out what module to return.
|
||||||
|
|
||||||
|
- Needs of import_module
|
||||||
|
|
||||||
|
* Resolve name/level.
|
||||||
|
* Import module.
|
||||||
|
|
||||||
+ Use GCD import for __import__.
|
+ Use GCD import for __import__.
|
||||||
+ Use GCD import for import_module.
|
+ Use GCD import for import_module.
|
||||||
|
|
||||||
|
|
|
@ -676,6 +676,48 @@ def __exit__(self, exc_type, exc_value, exc_traceback):
|
||||||
imp.release_lock()
|
imp.release_lock()
|
||||||
|
|
||||||
|
|
||||||
|
def _gcd_import(name, package=None, level=0):
|
||||||
|
"""Import and return the module based on its name, the package the call is
|
||||||
|
being made from, and the level adjustment.
|
||||||
|
|
||||||
|
This function represents the greatest common denominator of functionality
|
||||||
|
between import_module and __import__.
|
||||||
|
"""
|
||||||
|
if package and package not in sys.modules:
|
||||||
|
msg = "Parent module {0!r} not loaded, cannot perform relative import"
|
||||||
|
raise SystemError(msg.format(package))
|
||||||
|
dot = len(package)
|
||||||
|
if level > 0:
|
||||||
|
for x in range(level, 1, -1):
|
||||||
|
try:
|
||||||
|
dot = package.rindex('.', 0, dot)
|
||||||
|
except AttributeError:
|
||||||
|
raise ValueError("__package__ not set to a string")
|
||||||
|
except ValueError:
|
||||||
|
raise ValueError("attempted relative import beyond top-level "
|
||||||
|
"package")
|
||||||
|
name = "{0}.{1}".format(package[:dot], name)
|
||||||
|
with ImportLockContext():
|
||||||
|
try:
|
||||||
|
return sys.modules[name]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
parent = name.rpartition('.')[0]
|
||||||
|
path = None
|
||||||
|
if parent:
|
||||||
|
if parent not in sys.modules:
|
||||||
|
parent_module = _gcd_import(parent)
|
||||||
|
else:
|
||||||
|
parent_module = sys.modules[parent]
|
||||||
|
path = parent_module.__path__
|
||||||
|
for finder in sys.meta_path + [PathFinder]:
|
||||||
|
loader = finder.find_module(name, path)
|
||||||
|
if loader: # XXX Worth checking for None explicitly?
|
||||||
|
return loader.load_module(name)
|
||||||
|
else:
|
||||||
|
raise ImportError("No module named {0}".format(name))
|
||||||
|
|
||||||
|
|
||||||
class Import(object):
|
class Import(object):
|
||||||
|
|
||||||
"""Class that implements the __import__ interface.
|
"""Class that implements the __import__ interface.
|
||||||
|
@ -950,6 +992,7 @@ def __call__(self, name, globals={}, locals={}, fromlist=[], level=0):
|
||||||
(e.g. has a value of 2 for ``from .. import foo``).
|
(e.g. has a value of 2 for ``from .. import foo``).
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
# TODO(brett.cannon) outdated check; just care that level >= 0
|
||||||
if not name and level < 1:
|
if not name and level < 1:
|
||||||
raise ValueError("Empty module name")
|
raise ValueError("Empty module name")
|
||||||
is_pkg = True if '__path__' in globals else False
|
is_pkg = True if '__path__' in globals else False
|
||||||
|
|
Loading…
Reference in New Issue