diff options
author | Brett Cannon <bcannon@gmail.com> | 2009-02-06 02:47:33 (GMT) |
---|---|---|
committer | Brett Cannon <bcannon@gmail.com> | 2009-02-06 02:47:33 (GMT) |
commit | 7f9876c0daf73b1da3a7bc3ab62add0d1b10706a (patch) | |
tree | 65c2e0a352b057d075cb21fc70af5e0b0194a123 /Lib/importlib/_bootstrap.py | |
parent | 5c6d7877c58cfe348b2a302d3bd924cd096a7ba2 (diff) | |
download | cpython-7f9876c0daf73b1da3a7bc3ab62add0d1b10706a.zip cpython-7f9876c0daf73b1da3a7bc3ab62add0d1b10706a.tar.gz cpython-7f9876c0daf73b1da3a7bc3ab62add0d1b10706a.tar.bz2 |
Initial, untested stab at writing a common denominator function for __import__
and import_module.
Diffstat (limited to 'Lib/importlib/_bootstrap.py')
-rw-r--r-- | Lib/importlib/_bootstrap.py | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py index 8eff65c..2107e9e 100644 --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -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 |