Patchwork demandimport: fix level passed to loader of sub-modules

mail settings
Submitter Pierre-Yves David
Date Nov. 7, 2015, 4:12 p.m.
Message ID <>
Download mbox | patch
Permalink /patch/11319/
State Accepted
Headers show


Pierre-Yves David - Nov. 7, 2015, 4:12 p.m.
# HG changeset patch
# User Yuya Nishihara <>
# Date 1446380349 -32400
#      Sun Nov 01 21:19:09 2015 +0900
# Node ID 72cc3d5bfdaa086fe184b2ceb2cb7766434fc144
# Parent  1cbf144fd8a170b2a5e2a7f68357368c5793d7a4
# Available At
#              hg pull -r 72cc3d5bfdaa
demandimport: fix level passed to loader of sub-modules

As the fromlist gives the names of sub-modules, they should be searched in
the parent directory of the package's, which is level=1.

I got the following error by rewriting hgweb to use absolute_import, where
the "mercurial" package is referenced as ".." (level=2):

  ValueError: Attempted relative import beyond toplevel package

I know little about the import mechanism, but this change seems correct.
Before this patch, the following code did import the os module with no error:

  from mercurial import demandimport
  from mercurial import os


diff --git a/mercurial/ b/mercurial/
--- a/mercurial/
+++ b/mercurial/
@@ -162,19 +162,19 @@  def _demandimport(name, globals=None, lo
         # so modern Mercurial code will have level >= 0.
         # The name of the module the import statement is located in.
         globalname = globals.get('__name__')
-        def processfromitem(mod, attr, **kwargs):
+        def processfromitem(mod, attr):
             """Process an imported symbol in the import statement.
             If the symbol doesn't exist in the parent module, it must be a
             module. We set missing modules up as _demandmod instances.
             symbol = getattr(mod, attr, nothing)
             if symbol is nothing:
-                symbol = _demandmod(attr, mod.__dict__, locals, **kwargs)
+                symbol = _demandmod(attr, mod.__dict__, locals, level=1)
                 setattr(mod, attr, symbol)
             # Record the importing module references this symbol so we can
             # replace the symbol with the actual module instance at load
             # time.
@@ -192,11 +192,11 @@  def _demandimport(name, globals=None, lo
                                     fromlist, level)
             mod = _hgextimport(_origimport, name, globals, locals, level=level)
             for x in fromlist:
-                processfromitem(mod, x, level=level)
+                processfromitem(mod, x)
             return mod
         # But, we still need to support lazy loading of standard library and 3rd
         # party modules. So handle level == -1.