[PATCH 2 of 3 v2] demandimport: suppport rejecting modules based on requested properties
timeless
timeless at fmr.im
Wed Sep 21 14:09:41 EDT 2016
# HG changeset patch
# User timeless <timeless at mozdev.org>
# Date 1474429655 0
# Wed Sep 21 03:47:35 2016 +0000
# Node ID 20111b4d031e63596b93e162af9b8ca3ff1c98af
# Parent 32a4cb17f935c570817249721401e0d62033987d
# Available At https://bitbucket.org/timeless/mercurial-crew
# hg pull https://bitbucket.org/timeless/mercurial-crew -r 20111b4d031e
demandimport: suppport rejecting modules based on requested properties
Some code uses:
try:
from Foo import Bar
except ImportError:
from Foo import Bar2
demandimport exposes Bar as an unloaded module without checking to
see whether or not it really exists this enables it to improve loading
speed.
Unfortunately, any code that expects to get an ImportError won't get
one.
This code enables callers to tell demandimport about the shape of some
libraries to enable it to replicate the exception that callers expect.
without demandimport:
>>> from contextlib import _GeneratorContextManager
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: cannot import name _GeneratorContextManager
with demandimport without reject:
>>> from __future__ import absolute_import
>>> from mercurial import demandimport
>>> demandimport.enable()
>>> from contextlib import _GeneratorContextManager
>>> _GeneratorContextManager
<unloaded module '_GeneratorContextManager'>
with demandimport and reject:
>>> from __future__ import absolute_import
>>> from mercurial import demandimport
>>> demandimport.enable()
>>> demandimport.reject("contextlib", "_GeneratorContextManager", ImportError, "cannot import name _GeneratorContextManager")
>>> from contextlib import _GeneratorContextManager
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "mercurial/demandimport.py", line 260, in _demandimport
processfromlist(mod, name, fromlist)
File "mercurial/demandimport.py", line 235, in processfromlist
raise cls(msg)
ImportError: cannot import name _GeneratorContextManager
diff -r 32a4cb17f935 -r 20111b4d031e mercurial/demandimport.py
--- a/mercurial/demandimport.py Wed Sep 21 03:40:51 2016 +0000
+++ b/mercurial/demandimport.py Wed Sep 21 03:47:35 2016 +0000
@@ -222,9 +222,18 @@
def processfromlist(mod, name, fromlist):
# call processfromitem for each item in fromlist
- if True:
+ # if a module property is registered for rejection,
+ # raise the specified exception
+ if not name in rejects:
for x in fromlist:
processfromitem(mod, x)
+ else:
+ reject = rejects[name]
+ for x in fromlist:
+ if x in reject:
+ cls, msg = reject[x]
+ raise cls(msg)
+ processfromitem(mod, x)
if level >= 0:
if name:
@@ -290,6 +299,16 @@
'distutils.msvc9compiler',
]
+rejects = {}
+
+def reject(mod, prop, cls, msg):
+ """inform demandimport that a module does not have a property
+
+ arguments are the class and message to raise when code tries to
+ import it."""
+ if not mod in rejects:
+ rejects[mod] = {}
+ rejects[mod][prop] = [cls, msg]
def isenabled():
return builtins.__import__ == _demandimport
diff -r 32a4cb17f935 -r 20111b4d031e tests/test-demandimport.py
--- a/tests/test-demandimport.py Wed Sep 21 03:40:51 2016 +0000
+++ b/tests/test-demandimport.py Wed Sep 21 03:47:35 2016 +0000
@@ -63,6 +63,14 @@
print("re.stderr =", f(re.stderr))
print("re =", f(re))
+demandimport.reject('chunk', 'Chunk', ImportError, 'boo')
+try:
+ from chunk import Chunk
+ print('reject should prevent chunk from loading for Chunk')
+ Chunk.getname
+except ImportError:
+ pass
+
demandimport.disable()
os.environ['HGDEMANDIMPORT'] = 'disable'
# this enable call should not actually enable demandimport!
More information about the Mercurial-devel
mailing list