changeset 11942:50a4e55aa278

demandimport: store level argument on _demandmod instances The 'level' argument to __import__ was added in Python 2.6, and is specified for either relative or absolute imports. The fix introduced in e160f2312815 allowed such imports to proceed without failure, but effectively disabled demandimport for them. This is particularly unfortunate in Python 3.x, where *all* imports are either relative or absolute. The solution introduced here is to store the level argument on the demandimport instance, and propagate it to _origimport() when its value isn't None. Please note that this patch hasn't been tested in Python 3.x, and thus may not be complete. I'm worried about how sub-imports are handled; I don't know what they are, or whether the level argument should be modified for them. I've added 'TODO' notes to these cases; hopefully, someone more knowledgable of these issues will deal with them.
author Dan Villiom Podlaski Christiansen <danchr@gmail.com>
date Tue, 17 Aug 2010 17:46:10 +0200
parents 4532c44bb62d
children 2d3cbcace897
files mercurial/demandimport.py
diffstat 1 files changed, 27 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/demandimport.py	Fri Aug 13 13:59:26 2010 -0400
+++ b/mercurial/demandimport.py	Tue Aug 17 17:46:10 2010 +0200
@@ -29,29 +29,35 @@
 
 class _demandmod(object):
     """module demand-loader and proxy"""
-    def __init__(self, name, globals, locals):
+    def __init__(self, name, globals, locals, level):
         if '.' in name:
             head, rest = name.split('.', 1)
             after = [rest]
         else:
             head = name
             after = []
-        object.__setattr__(self, "_data", (head, globals, locals, after))
+        object.__setattr__(self, "_data", (head, globals, locals, after, level))
         object.__setattr__(self, "_module", None)
     def _extend(self, name):
         """add to the list of submodules to load"""
         self._data[3].append(name)
     def _load(self):
         if not self._module:
-            head, globals, locals, after = self._data
-            mod = _origimport(head, globals, locals)
+            head, globals, locals, after, level = self._data
+            if level is not None:
+                mod = _origimport(head, globals, locals, level)
+            else:
+                mod = _origimport(head, globals, locals)
             # load submodules
             def subload(mod, p):
                 h, t = p, None
                 if '.' in p:
                     h, t = p.split('.', 1)
                 if not hasattr(mod, h):
-                    setattr(mod, h, _demandmod(p, mod.__dict__, mod.__dict__))
+                    # TODO: should we adjust the level here?
+                    submod = _demandmod(p, mod.__dict__, mod.__dict__,
+                                        level=level)
+                    setattr(mod, h, submod)
                 elif t:
                     subload(getattr(mod, h), t)
 
@@ -91,28 +97,36 @@
             base, rest = name.split('.', 1)
             # email.__init__ loading email.mime
             if globals and globals.get('__name__', None) == base:
-                return _origimport(name, globals, locals, fromlist)
+                if level is not None:
+                    return _origimport(name, globals, locals, fromlist, level)
+                else:
+                    return _origimport(name, globals, locals, fromlist)
             # if a is already demand-loaded, add b to its submodule list
             if base in locals:
                 if isinstance(locals[base], _demandmod):
                     locals[base]._extend(rest)
                 return locals[base]
-        return _demandmod(name, globals, locals)
+        return _demandmod(name, globals, locals, level=level)
     else:
+        # from a import b,c,d
         if level is not None:
-            # from . import b,c,d or from .a import b,c,d
-            return _origimport(name, globals, locals, fromlist, level)
-        # from a import b,c,d
-        mod = _origimport(name, globals, locals)
+            mod = _origimport(name, globals, locals, level=level)
+        else:
+            mod = _origimport(name, globals, locals)
         # recurse down the module chain
         for comp in name.split('.')[1:]:
             if not hasattr(mod, comp):
-                setattr(mod, comp, _demandmod(comp, mod.__dict__, mod.__dict__))
+                # TODO: should we adjust the level here?
+                submod = _demandmod(comp, mod.__dict__, mod.__dict__,
+                                    level=level)
+                setattr(mod, comp, submod)
             mod = getattr(mod, comp)
         for x in fromlist:
             # set requested submodules for demand load
             if not(hasattr(mod, x)):
-                setattr(mod, x, _demandmod(x, mod.__dict__, locals))
+                # TODO: should we adjust the level here?
+                submod = _demandmod(x, mod.__dict__, locals, level=level)
+                setattr(mod, x, submod)
         return mod
 
 ignore = [