bpo-32946: Speed up "from ... import ..." from non-packages. (GH-5873)

This commit is contained in:
Serhiy Storchaka 2018-03-11 10:52:37 +02:00 committed by GitHub
parent b931bd0a2f
commit 4e2442505c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 302 additions and 288 deletions

View file

@ -1016,31 +1016,30 @@ def _handle_fromlist(module, fromlist, import_, *, recursive=False):
"""
# The hell that is fromlist ...
# If a package was imported, try to import stuff from fromlist.
if hasattr(module, '__path__'):
for x in fromlist:
if not isinstance(x, str):
if recursive:
where = module.__name__ + '.__all__'
else:
where = "``from list''"
raise TypeError(f"Item in {where} must be str, "
f"not {type(x).__name__}")
elif x == '*':
if not recursive and hasattr(module, '__all__'):
_handle_fromlist(module, module.__all__, import_,
recursive=True)
elif not hasattr(module, x):
from_name = '{}.{}'.format(module.__name__, x)
try:
_call_with_frames_removed(import_, from_name)
except ModuleNotFoundError as exc:
# Backwards-compatibility dictates we ignore failed
# imports triggered by fromlist for modules that don't
# exist.
if (exc.name == from_name and
sys.modules.get(from_name, _NEEDS_LOADING) is not None):
continue
raise
for x in fromlist:
if not isinstance(x, str):
if recursive:
where = module.__name__ + '.__all__'
else:
where = "``from list''"
raise TypeError(f"Item in {where} must be str, "
f"not {type(x).__name__}")
elif x == '*':
if not recursive and hasattr(module, '__all__'):
_handle_fromlist(module, module.__all__, import_,
recursive=True)
elif not hasattr(module, x):
from_name = '{}.{}'.format(module.__name__, x)
try:
_call_with_frames_removed(import_, from_name)
except ModuleNotFoundError as exc:
# Backwards-compatibility dictates we ignore failed
# imports triggered by fromlist for modules that don't
# exist.
if (exc.name == from_name and
sys.modules.get(from_name, _NEEDS_LOADING) is not None):
continue
raise
return module
@ -1102,8 +1101,10 @@ def __import__(name, globals=None, locals=None, fromlist=(), level=0):
# Slice end needs to be positive to alleviate need to special-case
# when ``'.' not in name``.
return sys.modules[module.__name__[:len(module.__name__)-cut_off]]
else:
elif hasattr(module, '__path__'):
return _handle_fromlist(module, fromlist, _gcd_import)
else:
return module
def _builtin_from_name(name):