Comments
Patch
@@ -199,8 +199,11 @@ def _demandimport(name, globals=None, lo
nonpkg = getattr(mod, '__path__', nothing) is nothing
if symbol is nothing:
if nonpkg:
- # do not try relative import, which would raise ValueError
- raise ImportError('cannot import name %s' % attr)
+ # do not try relative import, which would raise ValueError,
+ # and leave unknown attribute as the default __import__()
+ # would do. the missing attribute will be detected later
+ # while processing the import statement.
+ return
mn = '%s.%s' % (mod.__name__, attr)
if mn in ignore:
importfunc = _origimport
@@ -70,7 +70,16 @@ try:
print('no demandmod should be created for attribute of non-package '
'module:\ncontextlib.unknownattr =', f(unknownattr))
except ImportError as inst:
- print('contextlib.unknownattr = ImportError: %s' % inst)
+ print('contextlib.unknownattr = ImportError: %s'
+ % rsub(r"'", '', str(inst)))
+
+# Unlike the import statement, __import__() function should not raise
+# ImportError even if fromlist has an unknown item
+# (see Python/import.c:import_module_level() and ensure_fromlist())
+contextlibimp = __import__('contextlib', globals(), locals(), ['unknownattr'])
+print("__import__('contextlib', ..., ['unknownattr']) =", f(contextlibimp))
+print("hasattr(contextlibimp, 'unknownattr') =",
+ util.safehasattr(contextlibimp, 'unknownattr'))
demandimport.disable()
os.environ['HGDEMANDIMPORT'] = 'disable'
@@ -18,4 +18,6 @@ re.stderr = <open file '<whatever>', mod
re = <proxied module 'sys'>
contextlib = <unloaded module 'contextlib'>
contextlib.unknownattr = ImportError: cannot import name unknownattr
+__import__('contextlib', ..., ['unknownattr']) = <module 'contextlib' from '?'>
+hasattr(contextlibimp, 'unknownattr') = False
node = <module 'mercurial.node' from '?'>