Mercurial > hg-stable
changeset 27536:f7d890bc5e01
demandimport: add support for PyPy
PyPy's implementation of __import__ differs subtly from that of CPython.
If invoked without a name or fromlist, it throws an ImportError,
whereas CPython returns a reference to the level-appropriate importing
package.
Here, we achieve the same behaviour by hand.
author | Bryan O'Sullivan <bos@serpentine.com> |
---|---|
date | Wed, 23 Dec 2015 16:22:20 -0800 |
parents | 0d0f4070f6d7 |
children | ffb1ab1e4bba |
files | mercurial/demandimport.py |
diffstat | 1 files changed, 17 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/demandimport.py Wed Dec 23 16:22:20 2015 -0800 +++ b/mercurial/demandimport.py Wed Dec 23 16:22:20 2015 -0800 @@ -133,6 +133,8 @@ self._load() setattr(self._module, attr, val) +_pypy = '__pypy__' in sys.builtin_module_names + def _demandimport(name, globals=None, locals=None, fromlist=None, level=level): if not locals or name in ignore or fromlist == ('*',): # these cases we can't really delay @@ -191,7 +193,21 @@ return _hgextimport(_origimport, name, globals, locals, fromlist, level) - mod = _hgextimport(_origimport, name, globals, locals, level=level) + if _pypy: + # PyPy's __import__ throws an exception if invoked + # with an empty name and no fromlist. Recreate the + # desired behaviour by hand. + mn = globalname + mod = sys.modules[mn] + if getattr(mod, '__path__', nothing) is nothing: + mn = mn.rsplit('.', 1)[0] + mod = sys.modules[mn] + if level > 1: + mn = mn.rsplit('.', level - 1)[0] + mod = sys.modules[mn] + else: + mod = _hgextimport(_origimport, name, globals, locals, + level=level) for x in fromlist: processfromitem(mod, x) @@ -245,10 +261,6 @@ def enable(): "enable global demand-loading of modules" - # PyPy doesn't work with demand import. - if '__pypy__' in sys.builtin_module_names: - return - if os.environ.get('HGDEMANDIMPORT') != 'disable': builtins.__import__ = _demandimport