[PATCH 3 of 4 V4] demandimport: support "absolute_import" for external libraries (issue4029)
FUJIWARA Katsunori
foozy at lares.dti.ne.jp
Fri Oct 4 16:19:07 UTC 2013
# HG changeset patch
# User FUJIWARA Katsunori <foozy at lares.dti.ne.jp>
# Date 1380902542 -32400
# Sat Oct 05 01:02:22 2013 +0900
# Node ID 9b9a9dccb19cf7eef9a39cbd505053df9a4aeab7
# Parent 8fb6dc24cd54553cfafe43d6c6d4b6c598340da5
demandimport: support "absolute_import" for external libraries (issue4029)
Before this patch, demandimport of Mercurial may fail to load external
libraries using "from __future__ import absolute_import": for example,
importing "foo" in "bar.baz" module will load "bar.foo" if it exists,
even though "absolute_import" is enabled in "bar.baz" module.
So, extensions for Mercurial can't use such external libraries.
This patch saves "level" of import request for on-demand module
loading in the future: default value of level is -1, and level is 0
when "absolute_import" is enabled.
"level" value is passed to built-in import function in
"_demandmod._load()" and it should load target module correctly.
This patch changes only one "_demandmod" construction case other than
cases below:
- construction in "_demandmod._load()"
this code path should be used only in relative sub-module
loading case
- constructions other than patched one in"_demandimport()"
these code paths shouldn't be used in "level != -1" case
diff --git a/mercurial/demandimport.py b/mercurial/demandimport.py
--- a/mercurial/demandimport.py
+++ b/mercurial/demandimport.py
@@ -40,22 +40,23 @@
class _demandmod(object):
"""module demand-loader and proxy"""
- def __init__(self, name, globals, locals):
+ def __init__(self, name, globals, locals, level=-1):
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
+ mod = _import(head, globals, locals, None, level)
# load submodules
def subload(mod, p):
h, t = p, None
@@ -105,7 +106,7 @@
if isinstance(locals[base], _demandmod):
locals[base]._extend(rest)
return locals[base]
- return _demandmod(name, globals, locals)
+ return _demandmod(name, globals, locals, level)
else:
if level != -1:
# from . import b,c,d or from .a import b,c,d
diff --git a/tests/test-extension.t b/tests/test-extension.t
--- a/tests/test-extension.t
+++ b/tests/test-extension.t
@@ -129,6 +129,45 @@
$ echo 'foo = !' >> $HGRCPATH
$ echo 'bar = !' >> $HGRCPATH
+Check "from __future__ import absolute_import" support for external libraries
+
+ $ mkdir $TESTTMP/libroot
+ $ echo "s = 'libroot/ambig.py'" > $TESTTMP/libroot/ambig.py
+ $ mkdir $TESTTMP/libroot/mod
+ $ touch $TESTTMP/libroot/mod/__init__.py
+ $ echo "s = 'libroot/mod/ambig.py'" > $TESTTMP/libroot/mod/ambig.py
+
+#if absimport
+ $ cat > $TESTTMP/libroot/mod/ambigabs.py <<EOF
+ > from __future__ import absolute_import
+ > import ambig # should load "libroot/ambig.py"
+ > s = ambig.s
+ > EOF
+ $ cat > loadabs.py <<EOF
+ > import mod.ambigabs as ambigabs
+ > def extsetup():
+ > print 'ambigabs.s=%s' % ambigabs.s
+ > EOF
+ $ (PYTHONPATH=$PYTHONPATH:$TESTTMP/libroot; hg --config extensions.loadabs=loadabs.py root)
+ ambigabs.s=libroot/ambig.py
+ $TESTTMP/a
+#endif
+
+#if no-py3k
+ $ cat > $TESTTMP/libroot/mod/ambigrel.py <<EOF
+ > import ambig # should load "libroot/mod/ambig.py"
+ > s = ambig.s
+ > EOF
+ $ cat > loadrel.py <<EOF
+ > import mod.ambigrel as ambigrel
+ > def extsetup():
+ > print 'ambigrel.s=%s' % ambigrel.s
+ > EOF
+ $ (PYTHONPATH=$PYTHONPATH:$TESTTMP/libroot; hg --config extensions.loadrel=loadrel.py root)
+ ambigrel.s=libroot/mod/ambig.py
+ $TESTTMP/a
+#endif
+
$ cd ..
hide outer repo
More information about the Mercurial-devel
mailing list