@@ -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+
9981057def _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