Mercurial > public > mercurial-scm > hg
comparison mercurial/demandimport.py @ 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 | 4e554a7df1e9 |
children | ffb1ab1e4bba |
comparison
equal
deleted
inserted
replaced
27535:0d0f4070f6d7 | 27536:f7d890bc5e01 |
---|---|
130 self._load() | 130 self._load() |
131 return getattr(self._module, attr) | 131 return getattr(self._module, attr) |
132 def __setattr__(self, attr, val): | 132 def __setattr__(self, attr, val): |
133 self._load() | 133 self._load() |
134 setattr(self._module, attr, val) | 134 setattr(self._module, attr, val) |
135 | |
136 _pypy = '__pypy__' in sys.builtin_module_names | |
135 | 137 |
136 def _demandimport(name, globals=None, locals=None, fromlist=None, level=level): | 138 def _demandimport(name, globals=None, locals=None, fromlist=None, level=level): |
137 if not locals or name in ignore or fromlist == ('*',): | 139 if not locals or name in ignore or fromlist == ('*',): |
138 # these cases we can't really delay | 140 # these cases we can't really delay |
139 return _hgextimport(_import, name, globals, locals, fromlist, level) | 141 return _hgextimport(_import, name, globals, locals, fromlist, level) |
189 # much, work around the problems. | 191 # much, work around the problems. |
190 if name: | 192 if name: |
191 return _hgextimport(_origimport, name, globals, locals, | 193 return _hgextimport(_origimport, name, globals, locals, |
192 fromlist, level) | 194 fromlist, level) |
193 | 195 |
194 mod = _hgextimport(_origimport, name, globals, locals, level=level) | 196 if _pypy: |
197 # PyPy's __import__ throws an exception if invoked | |
198 # with an empty name and no fromlist. Recreate the | |
199 # desired behaviour by hand. | |
200 mn = globalname | |
201 mod = sys.modules[mn] | |
202 if getattr(mod, '__path__', nothing) is nothing: | |
203 mn = mn.rsplit('.', 1)[0] | |
204 mod = sys.modules[mn] | |
205 if level > 1: | |
206 mn = mn.rsplit('.', level - 1)[0] | |
207 mod = sys.modules[mn] | |
208 else: | |
209 mod = _hgextimport(_origimport, name, globals, locals, | |
210 level=level) | |
195 | 211 |
196 for x in fromlist: | 212 for x in fromlist: |
197 processfromitem(mod, x) | 213 processfromitem(mod, x) |
198 | 214 |
199 return mod | 215 return mod |
243 def isenabled(): | 259 def isenabled(): |
244 return builtins.__import__ == _demandimport | 260 return builtins.__import__ == _demandimport |
245 | 261 |
246 def enable(): | 262 def enable(): |
247 "enable global demand-loading of modules" | 263 "enable global demand-loading of modules" |
248 # PyPy doesn't work with demand import. | |
249 if '__pypy__' in sys.builtin_module_names: | |
250 return | |
251 | |
252 if os.environ.get('HGDEMANDIMPORT') != 'disable': | 264 if os.environ.get('HGDEMANDIMPORT') != 'disable': |
253 builtins.__import__ = _demandimport | 265 builtins.__import__ = _demandimport |
254 | 266 |
255 def disable(): | 267 def disable(): |
256 "disable global demand-loading of modules" | 268 "disable global demand-loading of modules" |