Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8e3926a

Browse files
author
Charles-François Natali
committed
Merge.
2 parents 4a72ebe + 7fab676 commit 8e3926a

1 file changed

Lines changed: 130 additions & 71 deletions

File tree

Lib/importlib/_bootstrap.py

Lines changed: 130 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -861,19 +861,50 @@ def __exit__(self, exc_type, exc_value, exc_traceback):
861861
imp.release_lock()
862862

863863

864-
_IMPLICIT_META_PATH = [BuiltinImporter, FrozenImporter, _DefaultPathFinder]
864+
def _resolve_name(name, package, level):
865+
"""Resolve a relative module name to an absolute one."""
866+
dot = len(package)
867+
for x in range(level, 1, -1):
868+
try:
869+
dot = package.rindex('.', 0, dot)
870+
except ValueError:
871+
raise ValueError("attempted relative import beyond "
872+
"top-level package")
873+
if name:
874+
return "{0}.{1}".format(package[:dot], name)
875+
else:
876+
return package[:dot]
877+
878+
879+
def _find_module(name, path):
880+
"""Find a module's loader."""
881+
meta_path = sys.meta_path + _IMPLICIT_META_PATH
882+
for finder in meta_path:
883+
loader = finder.find_module(name, path)
884+
if loader is not None:
885+
# The parent import may have already imported this module.
886+
if name not in sys.modules:
887+
return loader
888+
else:
889+
return sys.modules[name].__loader__
890+
else:
891+
return None
865892

866-
_ERR_MSG = 'No module named {!r}'
867893

868-
def _gcd_import(name, package=None, level=0):
869-
"""Import and return the module based on its name, the package the call is
870-
being made from, and the level adjustment.
894+
def _set___package__(module):
895+
"""Set __package__ on a module."""
896+
# Watch out for what comes out of sys.modules to not be a module,
897+
# e.g. an int.
898+
try:
899+
module.__package__ = module.__name__
900+
if not hasattr(module, '__path__'):
901+
module.__package__ = module.__package__.rpartition('.')[0]
902+
except AttributeError:
903+
pass
871904

872-
This function represents the greatest common denominator of functionality
873-
between import_module and __import__. This includes setting __package__ if
874-
the loader did not.
875905

876-
"""
906+
def _sanity_check(name, package, level):
907+
"""Verify arguments are "sane"."""
877908
if package:
878909
if not hasattr(package, 'rindex'):
879910
raise ValueError("__package__ not set to a string")
@@ -883,18 +914,47 @@ def _gcd_import(name, package=None, level=0):
883914
raise SystemError(msg.format(package))
884915
if not name and level == 0:
885916
raise ValueError("Empty module name")
917+
918+
919+
def _find_search_path(name, import_):
920+
"""Find the search path for a module.
921+
922+
import_ is expected to be a callable which takes the name of a module to
923+
import. It is required to decouple the function from importlib.
924+
925+
"""
926+
path = None
927+
parent = name.rpartition('.')[0]
928+
if parent:
929+
if parent not in sys.modules:
930+
import_(parent)
931+
# Backwards-compatibility; be nicer to skip the dict lookup.
932+
parent_module = sys.modules[parent]
933+
try:
934+
path = parent_module.__path__
935+
except AttributeError:
936+
msg = (_ERR_MSG + '; {} is not a package').format(name, parent)
937+
raise ImportError(msg)
938+
return parent, path
939+
940+
941+
942+
_IMPLICIT_META_PATH = [BuiltinImporter, FrozenImporter, _DefaultPathFinder]
943+
944+
_ERR_MSG = 'No module named {!r}'
945+
946+
def _gcd_import(name, package=None, level=0):
947+
"""Import and return the module based on its name, the package the call is
948+
being made from, and the level adjustment.
949+
950+
This function represents the greatest common denominator of functionality
951+
between import_module and __import__. This includes setting __package__ if
952+
the loader did not.
953+
954+
"""
955+
_sanity_check(name, package, level)
886956
if level > 0:
887-
dot = len(package)
888-
for x in range(level, 1, -1):
889-
try:
890-
dot = package.rindex('.', 0, dot)
891-
except ValueError:
892-
raise ValueError("attempted relative import beyond "
893-
"top-level package")
894-
if name:
895-
name = "{0}.{1}".format(package[:dot], name)
896-
else:
897-
name = package[:dot]
957+
name = _resolve_name(name, package, level)
898958
with _ImportLockContext():
899959
try:
900960
module = sys.modules[name]
@@ -905,70 +965,33 @@ def _gcd_import(name, package=None, level=0):
905965
return module
906966
except KeyError:
907967
pass
908-
parent = name.rpartition('.')[0]
909-
path = None
910-
if parent:
911-
if parent not in sys.modules:
912-
_gcd_import(parent)
913-
# Backwards-compatibility; be nicer to skip the dict lookup.
914-
parent_module = sys.modules[parent]
915-
try:
916-
path = parent_module.__path__
917-
except AttributeError:
918-
msg = (_ERR_MSG + '; {} is not a package').format(name, parent)
919-
raise ImportError(msg)
920-
meta_path = sys.meta_path + _IMPLICIT_META_PATH
921-
for finder in meta_path:
922-
loader = finder.find_module(name, path)
923-
if loader is not None:
924-
# The parent import may have already imported this module.
925-
if name not in sys.modules:
926-
loader.load_module(name)
927-
break
928-
else:
968+
parent, path = _find_search_path(name, _gcd_import)
969+
loader = _find_module(name, path)
970+
if loader is None:
929971
raise ImportError(_ERR_MSG.format(name))
972+
elif name not in sys.modules:
973+
# The parent import may have already imported this module.
974+
loader.load_module(name)
930975
# Backwards-compatibility; be nicer to skip the dict lookup.
931976
module = sys.modules[name]
932977
if parent:
933978
# Set the module as an attribute on its parent.
979+
parent_module = sys.modules[parent]
934980
setattr(parent_module, name.rpartition('.')[2], module)
935981
# Set __package__ if the loader did not.
936982
if not hasattr(module, '__package__') or module.__package__ is None:
937-
# Watch out for what comes out of sys.modules to not be a module,
938-
# e.g. an int.
939-
try:
940-
module.__package__ = module.__name__
941-
if not hasattr(module, '__path__'):
942-
module.__package__ = module.__package__.rpartition('.')[0]
943-
except AttributeError:
944-
pass
983+
_set___package__(module)
945984
return module
946985

947986

948-
def __import__(name, globals={}, locals={}, fromlist=[], level=0):
949-
"""Import a module.
987+
def _return_module(module, name, fromlist, level, import_):
988+
"""Figure out what __import__ should return.
950989
951-
The 'globals' argument is used to infer where the import is occuring from
952-
to handle relative imports. The 'locals' argument is ignored. The
953-
'fromlist' argument specifies what should exist as attributes on the module
954-
being imported (e.g. ``from module import <fromlist>``). The 'level'
955-
argument represents the package location to import from in a relative
956-
import (e.g. ``from ..pkg import mod`` would have a 'level' of 2).
990+
The import_ parameter is a callable which takes the name of module to
991+
import. It is required to decouple the function from assuming importlib's
992+
import implementation is desired.
957993
958994
"""
959-
if not hasattr(name, 'rpartition'):
960-
raise TypeError("module name must be str, not {}".format(type(name)))
961-
if level == 0:
962-
module = _gcd_import(name)
963-
else:
964-
# __package__ is not guaranteed to be defined or could be set to None
965-
# to represent that its proper value is unknown
966-
package = globals.get('__package__')
967-
if package is None:
968-
package = globals['__name__']
969-
if '__path__' not in globals:
970-
package = package.rpartition('.')[0]
971-
module = _gcd_import(name, package, level)
972995
# The hell that is fromlist ...
973996
if not fromlist:
974997
# Return up to the first dot in 'name'. This is complicated by the fact
@@ -989,12 +1012,48 @@ def __import__(name, globals={}, locals={}, fromlist=[], level=0):
9891012
fromlist.extend(module.__all__)
9901013
for x in (y for y in fromlist if not hasattr(module,y)):
9911014
try:
992-
_gcd_import('{0}.{1}'.format(module.__name__, x))
1015+
import_('{0}.{1}'.format(module.__name__, x))
9931016
except ImportError:
9941017
pass
9951018
return module
9961019

9971020

1021+
def _calc___package__(globals):
1022+
"""Calculate what __package__ should be.
1023+
1024+
__package__ is not guaranteed to be defined or could be set to None
1025+
to represent that its proper value is unknown.
1026+
1027+
"""
1028+
package = globals.get('__package__')
1029+
if package is None:
1030+
package = globals['__name__']
1031+
if '__path__' not in globals:
1032+
package = package.rpartition('.')[0]
1033+
return package
1034+
1035+
1036+
def __import__(name, globals={}, locals={}, fromlist=[], level=0):
1037+
"""Import a module.
1038+
1039+
The 'globals' argument is used to infer where the import is occuring from
1040+
to handle relative imports. The 'locals' argument is ignored. The
1041+
'fromlist' argument specifies what should exist as attributes on the module
1042+
being imported (e.g. ``from module import <fromlist>``). The 'level'
1043+
argument represents the package location to import from in a relative
1044+
import (e.g. ``from ..pkg import mod`` would have a 'level' of 2).
1045+
1046+
"""
1047+
if not hasattr(name, 'rpartition'):
1048+
raise TypeError("module name must be str, not {}".format(type(name)))
1049+
if level == 0:
1050+
module = _gcd_import(name)
1051+
else:
1052+
package = _calc___package__(globals)
1053+
module = _gcd_import(name, package, level)
1054+
return _return_module(module, name, fromlist, level, _gcd_import)
1055+
1056+
9981057
def _setup(sys_module, imp_module):
9991058
"""Setup importlib by importing needed built-in modules and injecting them
10001059
into the global namespace.

0 commit comments

Comments
 (0)