Mercurial > hg
changeset 29736:14f077f7519a
demandimport: import sub-module relatively as expected (issue5208)
Before this patch, importing sub-module might (1) fail or (2) success
but import incorrect module, because demandimport tries to import
sub-module with level=-1 (on Python 2.x) or level=0 (on Python 3.x),
which is default value of "level" argument at construction of
"_demandmod" proxy object.
(1) on Python 3.x, importing sub-module always fails to import
existing sub-module
(2) both on Python 2.x and 3.x, importing sub-module might import
same name module on root level unintentionally
On Python 2.x, existing sub-module is prior to this unexpected
module. Therefore, this problem hasn't appeared.
To import sub-module relatively as expected, this patch specifies "1"
as import level explicitly at construction of "_demandmod" proxy
object for sub-module.
author | FUJIWARA Katsunori <foozy@lares.dti.ne.jp> |
---|---|
date | Sat, 06 Aug 2016 22:24:33 +0900 |
parents | 919a4b7f531d |
children | ae9a4d6a8d51 |
files | mercurial/demandimport.py tests/test-extension.t |
diffstat | 2 files changed, 34 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/demandimport.py Sat Aug 06 15:00:34 2016 -0700 +++ b/mercurial/demandimport.py Sat Aug 06 22:24:33 2016 +0900 @@ -117,7 +117,8 @@ if '.' in p: h, t = p.split('.', 1) if getattr(mod, h, nothing) is nothing: - setattr(mod, h, _demandmod(p, mod.__dict__, mod.__dict__)) + setattr(mod, h, _demandmod(p, mod.__dict__, mod.__dict__, + level=1)) elif t: subload(getattr(mod, h), t) @@ -210,8 +211,8 @@ mod = rootmod for comp in modname.split('.')[1:]: if getattr(mod, comp, nothing) is nothing: - setattr(mod, comp, - _demandmod(comp, mod.__dict__, mod.__dict__)) + setattr(mod, comp, _demandmod(comp, mod.__dict__, + mod.__dict__, level=1)) mod = getattr(mod, comp) return mod
--- a/tests/test-extension.t Sat Aug 06 15:00:34 2016 -0700 +++ b/tests/test-extension.t Sat Aug 06 22:24:33 2016 +0900 @@ -432,6 +432,36 @@ REL: this is absextroot.xsub1.xsub2.called.func() REL: this relimporter imports 'this is absextroot.relimportee' +Examine whether sub-module is imported relatively as expected. + +See also issue5208 for detail about example case on Python 3.x. + + $ f -q $TESTTMP/extlibroot/lsub1/lsub2/notexist.py + $TESTTMP/extlibroot/lsub1/lsub2/notexist.py: file not found + + $ cat > $TESTTMP/notexist.py <<EOF + > text = 'notexist.py at root is loaded unintentionally\n' + > EOF + + $ cat > $TESTTMP/checkrelativity.py <<EOF + > from mercurial import cmdutil + > cmdtable = {} + > command = cmdutil.command(cmdtable) + > + > # demand import avoids failure of importing notexist here + > import extlibroot.lsub1.lsub2.notexist + > + > @command('checkrelativity', [], norepo=True) + > def checkrelativity(ui, *args, **opts): + > try: + > ui.write(extlibroot.lsub1.lsub2.notexist.text) + > return 1 # unintentional success + > except ImportError: + > pass # intentional failure + > EOF + + $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}; hg --config extensions.checkrelativity=$TESTTMP/checkrelativity.py checkrelativity) + #endif $ cd ..