[Python-checkins] r69352 - in python/branches/py3k/Lib/importlib: NOTES _bootstrap.py

brett.cannon python-checkins at python.org
Fri Feb 6 03:47:33 CET 2009


Author: brett.cannon
Date: Fri Feb  6 03:47:33 2009
New Revision: 69352

Log:
Initial, untested stab at writing a common denominator function for __import__
and import_module.


Modified:
   python/branches/py3k/Lib/importlib/NOTES
   python/branches/py3k/Lib/importlib/_bootstrap.py

Modified: python/branches/py3k/Lib/importlib/NOTES
==============================================================================
--- python/branches/py3k/Lib/importlib/NOTES	(original)
+++ python/branches/py3k/Lib/importlib/NOTES	Fri Feb  6 03:47:33 2009
@@ -15,6 +15,19 @@
 
     + 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.
 

Modified: python/branches/py3k/Lib/importlib/_bootstrap.py
==============================================================================
--- python/branches/py3k/Lib/importlib/_bootstrap.py	(original)
+++ python/branches/py3k/Lib/importlib/_bootstrap.py	Fri Feb  6 03:47:33 2009
@@ -676,6 +676,48 @@
         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 @@
         (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


More information about the Python-checkins mailing list