[Python-checkins] r75423 - in python/trunk: Lib/ihooks.py Misc/NEWS

neil.schemenauer python-checkins at python.org
Wed Oct 14 21:23:53 CEST 2009


Author: neil.schemenauer
Date: Wed Oct 14 21:23:53 2009
New Revision: 75423

Log:
Add support to the ihooks module for relative imports.


Modified:
   python/trunk/Lib/ihooks.py
   python/trunk/Misc/NEWS

Modified: python/trunk/Lib/ihooks.py
==============================================================================
--- python/trunk/Lib/ihooks.py	(original)
+++ python/trunk/Lib/ihooks.py	Wed Oct 14 21:23:53 2009
@@ -49,7 +49,7 @@
 would also do wise to install a different version of reload().
 
 """
-from warnings import warnpy3k
+from warnings import warnpy3k, warn
 warnpy3k("the ihooks module has been removed in Python 3.0", stacklevel=2)
 del warnpy3k
 
@@ -401,8 +401,9 @@
 
     """A module importer that supports packages."""
 
-    def import_module(self, name, globals=None, locals=None, fromlist=None):
-        parent = self.determine_parent(globals)
+    def import_module(self, name, globals=None, locals=None, fromlist=None,
+                      level=-1):
+        parent = self.determine_parent(globals, level)
         q, tail = self.find_head_package(parent, str(name))
         m = self.load_tail(q, tail)
         if not fromlist:
@@ -411,21 +412,50 @@
             self.ensure_fromlist(m, fromlist)
         return m
 
-    def determine_parent(self, globals):
-        if not globals or not "__name__" in globals:
+    def determine_parent(self, globals, level=-1):
+        if not globals or not level:
             return None
-        pname = globals['__name__']
-        if "__path__" in globals:
-            parent = self.modules[pname]
-            assert globals is parent.__dict__
-            return parent
-        if '.' in pname:
-            i = pname.rfind('.')
-            pname = pname[:i]
-            parent = self.modules[pname]
-            assert parent.__name__ == pname
-            return parent
-        return None
+        pkgname = globals.get('__package__')
+        if pkgname is not None:
+            if not pkgname and level > 0:
+                raise ValueError, 'Attempted relative import in non-package'
+        else:
+            # __package__ not set, figure it out and set it
+            modname = globals.get('__name__')
+            if modname is None:
+                return None
+            if "__path__" in globals:
+                # __path__ is set so modname is already the package name
+                pkgname = modname
+            else:
+                # normal module, work out package name if any
+                if '.' not in modname:
+                    if level > 0:
+                        raise ValueError, ('Attempted relative import in '
+                                           'non-package')
+                    globals['__package__'] = None
+                    return None
+                pkgname = modname.rpartition('.')[0]
+            globals['__package__'] = pkgname
+        if level > 0:
+            dot = len(pkgname)
+            for x in range(level, 1, -1):
+                try:
+                    dot = pkgname.rindex('.', 0, dot)
+                except ValueError:
+                    raise ValueError('attempted relative import beyond '
+                                     'top-level package')
+            pkgname = pkgname[:dot]
+        try:
+            return sys.modules[pkgname]
+        except KeyError:
+            if level < 1:
+                warn("Parent module '%s' not found while handling "
+                     "absolute import" % pkgname, RuntimeWarning, 1)
+                return None
+            else:
+                raise SystemError, ("Parent module '%s' not loaded, cannot "
+                                    "perform relative import" % pkgname)
 
     def find_head_package(self, parent, name):
         if '.' in name:
@@ -446,7 +476,7 @@
             parent = None
             q = self.import_it(head, qname, parent)
             if q: return q, tail
-        raise ImportError, "No module named " + qname
+        raise ImportError, "No module named '%s'" % qname
 
     def load_tail(self, q, tail):
         m = q
@@ -457,7 +487,7 @@
             mname = "%s.%s" % (m.__name__, head)
             m = self.import_it(head, mname, m)
             if not m:
-                raise ImportError, "No module named " + mname
+                raise ImportError, "No module named '%s'" % mname
         return m
 
     def ensure_fromlist(self, m, fromlist, recursive=0):
@@ -475,11 +505,13 @@
                 subname = "%s.%s" % (m.__name__, sub)
                 submod = self.import_it(sub, subname, m)
                 if not submod:
-                    raise ImportError, "No module named " + subname
+                    raise ImportError, "No module named '%s'" % subname
 
     def import_it(self, partname, fqname, parent, force_load=0):
         if not partname:
-            raise ValueError, "Empty module name"
+            # completely empty module name should only happen in
+            # 'from . import' or __import__("")
+            return parent
         if not force_load:
             try:
                 return self.modules[fqname]

Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS	(original)
+++ python/trunk/Misc/NEWS	Wed Oct 14 21:23:53 2009
@@ -405,6 +405,8 @@
 Library
 -------
 
+- Add support to the `ihooks` module for relative imports.
+
 - Issue #6894: Fixed the issue urllib2 doesn't respect "no_proxy" environment 
 
 - Issue #7086: Added TCP support to SysLogHandler, and tidied up some


More information about the Python-checkins mailing list