We don't use util.safehasattr() here to avoid adding new dependencies
for demandimport. This change may expose previously-silenced
deprecation warnings to appear, as hasattr silently hides warnings
that occur during module import when using demandimport.
The Python default for this function is -1, indicating both relative
and absolute imports should be used.[1] Previously, we relied on the
Python VM not passing level when such semantics were
requisted. This is not the case for PyPy, however, where a level of -1
is always passed to __import__.
[1] <http://docs.python.org/library/functions.html#__import__>
Python's __import__() function has 'level' as the fourth argument, not the
third. The code path in question probably never worked.
(This was seen trying to run Mercurial in PyPy. Fixing this made it
die somewhere else...)
The 'level' argument to __import__ was added in Python 2.6, and is
specified for either relative or absolute imports. The fix introduced
in 5b0fda8ff209 allowed such imports to proceed without failure, but
effectively disabled demandimport for them. This is particularly
unfortunate in Python 3.x, where *all* imports are either relative or
absolute.
The solution introduced here is to store the level argument on the
demandimport instance, and propagate it to _origimport() when its
value isn't None.
Please note that this patch hasn't been tested in Python 3.x, and thus
may not be complete. I'm worried about how sub-imports are handled; I
don't know what they are, or whether the level argument should be
modified for them. I've added 'TODO' notes to these cases; hopefully,
someone more knowledgable of these issues will deal with them.
Demandimport breaks gtk. You get a meaningless error about
'failed loading gobject\_gobject.pyd'. Mercurial does not use gtk,
but this trips up many extension writers.
I wanted to check if mercurial.demandimport could speed up the loading of
PyObjC, and ran into this: the level argument for __import__, available in
Python 2.5 and later, is silently dropped when doing an 'import *'. I have no
idea what these arguments mean, but this minor change made it work.
(Oh, and because of that 'from ... import *', PyObjC still took about 2s...)
Mercurial does not work on python2.6 because __import__ takes an
additional argument called level. This patch merely calls the
built-in __import__ when level is passed.