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
|
||||
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_module.
|
||||
|
||||
|
|
|
@ -676,6 +676,48 @@ class ImportLockContext(object):
|
|||
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 that implements the __import__ interface.
|
||||
|
@ -950,6 +992,7 @@ class Import(object):
|
|||
(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:
|
||||
raise ValueError("Empty module name")
|
||||
is_pkg = True if '__path__' in globals else False
|
||||
|
|
Loading…
Reference in New Issue