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"