MCPcopy Index your code
hub / github.com/python/cpython / NamespacePath

Class NamespacePath

Lib/importlib/_bootstrap_external.py:1057–1136  ·  view source on GitHub ↗

Represents a namespace package's path. It uses the module *name* to find its parent module, and from there it looks up the parent's __path__. When this changes, the module's own path is recomputed, using *path_finder*. The initial value is set to *path*. For top-level modules, the

Source from the content-addressed store, hash-verified

1055
1056
1057class NamespacePath:
1058 """Represents a namespace package's path.
1059
1060 It uses the module *name* to find its parent module, and from there it looks
1061 up the parent's __path__. When this changes, the module's own path is
1062 recomputed, using *path_finder*. The initial value is set to *path*.
1063
1064 For top-level modules, the parent module's path is sys.path.
1065
1066 *path_finder* should be a callable with the same signature as
1067 MetaPathFinder.find_spec((fullname, path, target=None) -> spec).
1068 """
1069
1070 # When invalidate_caches() is called, this epoch is incremented
1071 # https://bugs.python.org/issue45703
1072 _epoch = 0
1073
1074 def __init__(self, name, path, path_finder):
1075 self._name = name
1076 self._path = path
1077 self._last_parent_path = tuple(self._get_parent_path())
1078 self._last_epoch = self._epoch
1079 self._path_finder = path_finder
1080
1081 def _find_parent_path_names(self):
1082 """Returns a tuple of (parent-module-name, parent-path-attr-name)"""
1083 parent, dot, me = self._name.rpartition('.')
1084 if dot == '':
1085 # This is a top-level module. sys.path contains the parent path.
1086 return 'sys', 'path'
1087 # Not a top-level module. parent-module.__path__ contains the
1088 # parent path.
1089 return parent, '__path__'
1090
1091 def _get_parent_path(self):
1092 parent_module_name, path_attr_name = self._find_parent_path_names()
1093 try:
1094 module = sys.modules[parent_module_name]
1095 except KeyError as e:
1096 raise ModuleNotFoundError(
1097 f"{parent_module_name!r} must be imported before finding {self._name!r}.",
1098 name=parent_module_name,
1099 ) from e
1100 else:
1101 return getattr(module, path_attr_name)
1102
1103 def _recalculate(self):
1104 # If the parent's path has changed, recalculate _path
1105 parent_path = tuple(self._get_parent_path()) # Make a copy
1106 if parent_path != self._last_parent_path or self._epoch != self._last_epoch:
1107 spec = self._path_finder(self._name, parent_path)
1108 # Note that no changes are made if a loader is returned, but we
1109 # do remember the new parent path
1110 if spec is not None and spec.loader is None:
1111 if spec.submodule_search_locations:
1112 self._path = spec.submodule_search_locations
1113 self._last_parent_path = parent_path # Save the copy
1114 self._last_epoch = self._epoch

Callers 2

__init__Method · 0.85
find_specMethod · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…