Mercurial > hg
diff mercurial/demandimport.py @ 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 | 30553ac3e355 |
children | fe31f834a9ff |
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 = [