Skip to content

Commit 0301510

Browse files
authored
Naming and inheritance for importlib (#12775)
This MR breaks out _frozen_importlib_external (which is the same thing as importlib._bootstrap_external) and _frozen_importlib (which is the same thing as importlib._bootstrap).
1 parent 53ee919 commit 0301510

File tree

10 files changed

+341
-207
lines changed

10 files changed

+341
-207
lines changed

stdlib/@tests/stubtest_allowlists/common.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ _collections_abc.ItemsView.__reversed__
1313
_collections_abc.KeysView.__reversed__
1414
_collections_abc.ValuesView.__reversed__
1515
_ctypes.CFuncPtr # stubtest erroneously thinks it can't be subclassed
16+
_frozen_importlib_external.ExtensionFileLoader.get_filename # Wrapped with _check_name decorator which changes runtime signature
17+
_frozen_importlib_external.FileLoader.get_filename # Wrapped with _check_name decorator which changes runtime signature
18+
_frozen_importlib_external.FileLoader.get_resource_reader # Wrapped with _check_name decorator which changes runtime signature
19+
_frozen_importlib_external.FileLoader.load_module # Wrapped with _check_name decorator which changes runtime signature
1620
_threading_local.local.__new__
1721
ast.Bytes.__new__
1822
ast.Ellipsis.__new__
@@ -45,6 +49,10 @@ hmac.new # Stub is a white lie; see comments in the stub
4549
http.HTTPStatus.description # set in __new__
4650
http.HTTPStatus.phrase # set in __new__
4751
http.client.HTTPConnection.response_class # the actual type at runtime is abc.ABCMeta
52+
importlib._bootstrap_external.ExtensionFileLoader.get_filename # Wrapped with _check_name decorator which changes runtime signature
53+
importlib._bootstrap_external.FileLoader.get_filename # Wrapped with _check_name decorator which changes runtime signature
54+
importlib._bootstrap_external.FileLoader.get_resource_reader # Wrapped with _check_name decorator which changes runtime signature
55+
importlib._bootstrap_external.FileLoader.load_module # Wrapped with _check_name decorator which changes runtime signature
4856
importlib.abc.FileLoader.get_filename # Wrapped with _check_name decorator which changes runtime signature
4957
importlib.abc.FileLoader.load_module # Wrapped with _check_name decorator which changes runtime signature
5058
importlib.abc.Loader.exec_module # See Lib/importlib/_abc.py. Might be defined for backwards compatibility
@@ -261,6 +269,12 @@ idlelib
261269
importlib.machinery.WindowsRegistryFinder.DEBUG_BUILD
262270
importlib.machinery.WindowsRegistryFinder.REGISTRY_KEY
263271
importlib.machinery.WindowsRegistryFinder.REGISTRY_KEY_DEBUG
272+
_frozen_importlib_external.WindowsRegistryFinder.DEBUG_BUILD
273+
_frozen_importlib_external.WindowsRegistryFinder.REGISTRY_KEY
274+
_frozen_importlib_external.WindowsRegistryFinder.REGISTRY_KEY_DEBUG
275+
importlib._bootstrap_external.WindowsRegistryFinder.DEBUG_BUILD
276+
importlib._bootstrap_external.WindowsRegistryFinder.REGISTRY_KEY
277+
importlib._bootstrap_external.WindowsRegistryFinder.REGISTRY_KEY_DEBUG
264278

265279
# Undocumented implementation details
266280
profile.Profile.dispatch

stdlib/VERSIONS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ _curses: 3.0-
3434
_decimal: 3.3-
3535
_dummy_thread: 3.0-3.8
3636
_dummy_threading: 3.0-3.8
37+
_frozen_importlib: 3.0-
38+
_frozen_importlib_external: 3.5-
3739
_heapq: 3.0-
3840
_imp: 3.0-
3941
_interpchannels: 3.13-
@@ -161,6 +163,8 @@ imghdr: 3.0-3.12
161163
imp: 3.0-3.11
162164
importlib: 3.0-
163165
importlib._abc: 3.10-
166+
importlib._bootstrap: 3.0-
167+
importlib._bootstrap_external: 3.5-
164168
importlib.metadata: 3.8-
165169
importlib.metadata._meta: 3.10-
166170
importlib.metadata.diagnose: 3.13-

stdlib/_frozen_importlib.pyi

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import importlib.abc
2+
import importlib.machinery
3+
import sys
4+
import types
5+
from _typeshed.importlib import LoaderProtocol
6+
from collections.abc import Mapping, Sequence
7+
from types import ModuleType
8+
from typing import Any
9+
10+
# Signature of `builtins.__import__` should be kept identical to `importlib.__import__`
11+
def __import__(
12+
name: str,
13+
globals: Mapping[str, object] | None = None,
14+
locals: Mapping[str, object] | None = None,
15+
fromlist: Sequence[str] = (),
16+
level: int = 0,
17+
) -> ModuleType: ...
18+
def spec_from_loader(
19+
name: str, loader: LoaderProtocol | None, *, origin: str | None = None, is_package: bool | None = None
20+
) -> importlib.machinery.ModuleSpec | None: ...
21+
def module_from_spec(spec: importlib.machinery.ModuleSpec) -> types.ModuleType: ...
22+
def _init_module_attrs(
23+
spec: importlib.machinery.ModuleSpec, module: types.ModuleType, *, override: bool = False
24+
) -> types.ModuleType: ...
25+
26+
class ModuleSpec:
27+
def __init__(
28+
self,
29+
name: str,
30+
loader: importlib.abc.Loader | None,
31+
*,
32+
origin: str | None = None,
33+
loader_state: Any = None,
34+
is_package: bool | None = None,
35+
) -> None: ...
36+
name: str
37+
loader: importlib.abc.Loader | None
38+
origin: str | None
39+
submodule_search_locations: list[str] | None
40+
loader_state: Any
41+
cached: str | None
42+
@property
43+
def parent(self) -> str | None: ...
44+
has_location: bool
45+
def __eq__(self, other: object) -> bool: ...
46+
47+
class BuiltinImporter(importlib.abc.MetaPathFinder, importlib.abc.InspectLoader):
48+
# MetaPathFinder
49+
if sys.version_info < (3, 12):
50+
@classmethod
51+
def find_module(cls, fullname: str, path: Sequence[str] | None = None) -> importlib.abc.Loader | None: ...
52+
53+
@classmethod
54+
def find_spec(
55+
cls, fullname: str, path: Sequence[str] | None = None, target: types.ModuleType | None = None
56+
) -> ModuleSpec | None: ...
57+
# InspectLoader
58+
@classmethod
59+
def is_package(cls, fullname: str) -> bool: ...
60+
@classmethod
61+
def load_module(cls, fullname: str) -> types.ModuleType: ...
62+
@classmethod
63+
def get_code(cls, fullname: str) -> None: ...
64+
@classmethod
65+
def get_source(cls, fullname: str) -> None: ...
66+
# Loader
67+
if sys.version_info < (3, 12):
68+
@staticmethod
69+
def module_repr(module: types.ModuleType) -> str: ...
70+
if sys.version_info >= (3, 10):
71+
@staticmethod
72+
def create_module(spec: ModuleSpec) -> types.ModuleType | None: ...
73+
@staticmethod
74+
def exec_module(module: types.ModuleType) -> None: ...
75+
else:
76+
@classmethod
77+
def create_module(cls, spec: ModuleSpec) -> types.ModuleType | None: ...
78+
@classmethod
79+
def exec_module(cls, module: types.ModuleType) -> None: ...
80+
81+
class FrozenImporter(importlib.abc.MetaPathFinder, importlib.abc.InspectLoader):
82+
# MetaPathFinder
83+
if sys.version_info < (3, 12):
84+
@classmethod
85+
def find_module(cls, fullname: str, path: Sequence[str] | None = None) -> importlib.abc.Loader | None: ...
86+
87+
@classmethod
88+
def find_spec(
89+
cls, fullname: str, path: Sequence[str] | None = None, target: types.ModuleType | None = None
90+
) -> ModuleSpec | None: ...
91+
# InspectLoader
92+
@classmethod
93+
def is_package(cls, fullname: str) -> bool: ...
94+
@classmethod
95+
def load_module(cls, fullname: str) -> types.ModuleType: ...
96+
@classmethod
97+
def get_code(cls, fullname: str) -> None: ...
98+
@classmethod
99+
def get_source(cls, fullname: str) -> None: ...
100+
# Loader
101+
if sys.version_info < (3, 12):
102+
@staticmethod
103+
def module_repr(m: types.ModuleType) -> str: ...
104+
if sys.version_info >= (3, 10):
105+
@staticmethod
106+
def create_module(spec: ModuleSpec) -> types.ModuleType | None: ...
107+
else:
108+
@classmethod
109+
def create_module(cls, spec: ModuleSpec) -> types.ModuleType | None: ...
110+
111+
@staticmethod
112+
def exec_module(module: types.ModuleType) -> None: ...

stdlib/_frozen_importlib_external.pyi

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
import _ast
2+
import _io
3+
import importlib.abc
4+
import importlib.machinery
5+
import sys
6+
import types
7+
from _typeshed import ReadableBuffer, StrOrBytesPath, StrPath
8+
from _typeshed.importlib import LoaderProtocol
9+
from collections.abc import Callable, Iterable, Iterator, Mapping, MutableSequence, Sequence
10+
from importlib.machinery import ModuleSpec
11+
from importlib.metadata import DistributionFinder, PathDistribution
12+
from typing import Any, Literal
13+
from typing_extensions import Self, deprecated
14+
15+
if sys.version_info >= (3, 10):
16+
import importlib.readers
17+
18+
if sys.platform == "win32":
19+
path_separators: Literal["\\/"]
20+
path_sep: Literal["\\"]
21+
path_sep_tuple: tuple[Literal["\\"], Literal["/"]]
22+
else:
23+
path_separators: Literal["/"]
24+
path_sep: Literal["/"]
25+
path_sep_tuple: tuple[Literal["/"]]
26+
27+
MAGIC_NUMBER: bytes
28+
29+
def cache_from_source(path: str, debug_override: bool | None = None, *, optimization: Any | None = None) -> str: ...
30+
def source_from_cache(path: str) -> str: ...
31+
def decode_source(source_bytes: ReadableBuffer) -> str: ...
32+
def spec_from_file_location(
33+
name: str,
34+
location: StrOrBytesPath | None = None,
35+
*,
36+
loader: LoaderProtocol | None = None,
37+
submodule_search_locations: list[str] | None = ...,
38+
) -> importlib.machinery.ModuleSpec | None: ...
39+
40+
class WindowsRegistryFinder(importlib.abc.MetaPathFinder):
41+
if sys.version_info < (3, 12):
42+
@classmethod
43+
def find_module(cls, fullname: str, path: Sequence[str] | None = None) -> importlib.abc.Loader | None: ...
44+
45+
@classmethod
46+
def find_spec(
47+
cls, fullname: str, path: Sequence[str] | None = None, target: types.ModuleType | None = None
48+
) -> ModuleSpec | None: ...
49+
50+
class PathFinder(importlib.abc.MetaPathFinder):
51+
if sys.version_info >= (3, 10):
52+
@staticmethod
53+
def invalidate_caches() -> None: ...
54+
else:
55+
@classmethod
56+
def invalidate_caches(cls) -> None: ...
57+
if sys.version_info >= (3, 10):
58+
@staticmethod
59+
def find_distributions(context: DistributionFinder.Context = ...) -> Iterable[PathDistribution]: ...
60+
else:
61+
@classmethod
62+
def find_distributions(cls, context: DistributionFinder.Context = ...) -> Iterable[PathDistribution]: ...
63+
64+
@classmethod
65+
def find_spec(
66+
cls, fullname: str, path: Sequence[str] | None = None, target: types.ModuleType | None = None
67+
) -> ModuleSpec | None: ...
68+
if sys.version_info < (3, 12):
69+
@classmethod
70+
def find_module(cls, fullname: str, path: Sequence[str] | None = None) -> importlib.abc.Loader | None: ...
71+
72+
SOURCE_SUFFIXES: list[str]
73+
DEBUG_BYTECODE_SUFFIXES: list[str]
74+
OPTIMIZED_BYTECODE_SUFFIXES: list[str]
75+
BYTECODE_SUFFIXES: list[str]
76+
EXTENSION_SUFFIXES: list[str]
77+
78+
class FileFinder(importlib.abc.PathEntryFinder):
79+
path: str
80+
def __init__(self, path: str, *loader_details: tuple[type[importlib.abc.Loader], list[str]]) -> None: ...
81+
@classmethod
82+
def path_hook(
83+
cls, *loader_details: tuple[type[importlib.abc.Loader], list[str]]
84+
) -> Callable[[str], importlib.abc.PathEntryFinder]: ...
85+
86+
class _LoaderBasics:
87+
def is_package(self, fullname: str) -> bool: ...
88+
def create_module(self, spec: ModuleSpec) -> types.ModuleType | None: ...
89+
def exec_module(self, module: types.ModuleType) -> None: ...
90+
def load_module(self, fullname: str) -> types.ModuleType: ...
91+
92+
class SourceLoader(_LoaderBasics):
93+
def path_mtime(self, path: str) -> float: ...
94+
def set_data(self, path: str, data: bytes) -> None: ...
95+
def get_source(self, fullname: str) -> str | None: ...
96+
def path_stats(self, path: str) -> Mapping[str, Any]: ...
97+
def source_to_code(
98+
self, data: ReadableBuffer | str | _ast.Module | _ast.Expression | _ast.Interactive, path: ReadableBuffer | StrPath
99+
) -> types.CodeType: ...
100+
def get_code(self, fullname: str) -> types.CodeType | None: ...
101+
102+
class FileLoader:
103+
name: str
104+
path: str
105+
def __init__(self, fullname: str, path: str) -> None: ...
106+
def get_data(self, path: str) -> bytes: ...
107+
def get_filename(self, name: str | None = None) -> str: ...
108+
def load_module(self, name: str | None = None) -> types.ModuleType: ...
109+
if sys.version_info >= (3, 10):
110+
def get_resource_reader(self, module: types.ModuleType) -> importlib.readers.FileReader: ...
111+
else:
112+
def get_resource_reader(self, module: types.ModuleType) -> Self | None: ...
113+
def open_resource(self, resource: str) -> _io.FileIO: ...
114+
def resource_path(self, resource: str) -> str: ...
115+
def is_resource(self, name: str) -> bool: ...
116+
def contents(self) -> Iterator[str]: ...
117+
118+
class SourceFileLoader(importlib.abc.FileLoader, FileLoader, importlib.abc.SourceLoader, SourceLoader): # type: ignore[misc] # incompatible method arguments in base classes
119+
def set_data(self, path: str, data: ReadableBuffer, *, _mode: int = 0o666) -> None: ...
120+
def path_stats(self, path: str) -> Mapping[str, Any]: ...
121+
122+
class SourcelessFileLoader(importlib.abc.FileLoader, FileLoader, _LoaderBasics):
123+
def get_code(self, fullname: str) -> types.CodeType | None: ...
124+
def get_source(self, fullname: str) -> None: ...
125+
126+
class ExtensionFileLoader(FileLoader, _LoaderBasics, importlib.abc.ExecutionLoader):
127+
def __init__(self, name: str, path: str) -> None: ...
128+
def get_filename(self, name: str | None = None) -> str: ...
129+
def get_source(self, fullname: str) -> None: ...
130+
def create_module(self, spec: ModuleSpec) -> types.ModuleType: ...
131+
def exec_module(self, module: types.ModuleType) -> None: ...
132+
def get_code(self, fullname: str) -> None: ...
133+
def __eq__(self, other: object) -> bool: ...
134+
def __hash__(self) -> int: ...
135+
136+
if sys.version_info >= (3, 11):
137+
class NamespaceLoader(importlib.abc.InspectLoader):
138+
def __init__(
139+
self, name: str, path: MutableSequence[str], path_finder: Callable[[str, tuple[str, ...]], ModuleSpec]
140+
) -> None: ...
141+
def is_package(self, fullname: str) -> Literal[True]: ...
142+
def get_source(self, fullname: str) -> Literal[""]: ...
143+
def get_code(self, fullname: str) -> types.CodeType: ...
144+
def create_module(self, spec: ModuleSpec) -> None: ...
145+
def exec_module(self, module: types.ModuleType) -> None: ...
146+
@deprecated("load_module() is deprecated; use exec_module() instead")
147+
def load_module(self, fullname: str) -> types.ModuleType: ...
148+
def get_resource_reader(self, module: types.ModuleType) -> importlib.readers.NamespaceReader: ...
149+
if sys.version_info < (3, 12):
150+
@staticmethod
151+
@deprecated("module_repr() is deprecated, and has been removed in Python 3.12")
152+
def module_repr(module: types.ModuleType) -> str: ...
153+
154+
_NamespaceLoader = NamespaceLoader
155+
else:
156+
class _NamespaceLoader:
157+
def __init__(
158+
self, name: str, path: MutableSequence[str], path_finder: Callable[[str, tuple[str, ...]], ModuleSpec]
159+
) -> None: ...
160+
def is_package(self, fullname: str) -> Literal[True]: ...
161+
def get_source(self, fullname: str) -> Literal[""]: ...
162+
def get_code(self, fullname: str) -> types.CodeType: ...
163+
def create_module(self, spec: ModuleSpec) -> None: ...
164+
def exec_module(self, module: types.ModuleType) -> None: ...
165+
@deprecated("load_module() is deprecated; use exec_module() instead")
166+
def load_module(self, fullname: str) -> types.ModuleType: ...
167+
if sys.version_info >= (3, 10):
168+
@staticmethod
169+
@deprecated("module_repr() is deprecated, and has been removed in Python 3.12")
170+
def module_repr(module: types.ModuleType) -> str: ...
171+
def get_resource_reader(self, module: types.ModuleType) -> importlib.readers.NamespaceReader: ...
172+
else:
173+
@classmethod
174+
@deprecated("module_repr() is deprecated, and has been removed in Python 3.12")
175+
def module_repr(cls, module: types.ModuleType) -> str: ...
176+
177+
if sys.version_info >= (3, 13):
178+
class AppleFrameworkLoader(ExtensionFileLoader, importlib.abc.ExecutionLoader): ...

stdlib/importlib/__init__.pyi

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,10 @@
11
import sys
2-
from collections.abc import Mapping, Sequence
2+
from importlib._bootstrap import __import__ as __import__
33
from importlib.abc import Loader
44
from types import ModuleType
55

66
__all__ = ["__import__", "import_module", "invalidate_caches", "reload"]
77

8-
# Signature of `builtins.__import__` should be kept identical to `importlib.__import__`
9-
def __import__(
10-
name: str,
11-
globals: Mapping[str, object] | None = None,
12-
locals: Mapping[str, object] | None = None,
13-
fromlist: Sequence[str] = (),
14-
level: int = 0,
15-
) -> ModuleType: ...
16-
178
# `importlib.import_module` return type should be kept the same as `builtins.__import__`
189
def import_module(name: str, package: str | None = None) -> ModuleType: ...
1910

stdlib/importlib/_bootstrap.pyi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from _frozen_importlib import *
2+
from _frozen_importlib import __import__ as __import__, _init_module_attrs as _init_module_attrs
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from _frozen_importlib_external import *
2+
from _frozen_importlib_external import _NamespaceLoader as _NamespaceLoader

stdlib/importlib/abc.pyi

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import types
44
from _typeshed import ReadableBuffer, StrPath
55
from abc import ABCMeta, abstractmethod
66
from collections.abc import Iterator, Mapping, Sequence
7+
from importlib import _bootstrap_external
78
from importlib.machinery import ModuleSpec
89
from io import BufferedReader
910
from typing import IO, Any, Literal, Protocol, overload, runtime_checkable
@@ -56,7 +57,7 @@ class ExecutionLoader(InspectLoader):
5657
@abstractmethod
5758
def get_filename(self, fullname: str) -> str: ...
5859

59-
class SourceLoader(ResourceLoader, ExecutionLoader, metaclass=ABCMeta):
60+
class SourceLoader(_bootstrap_external.SourceLoader, ResourceLoader, ExecutionLoader, metaclass=ABCMeta): # type: ignore[misc] # incompatible definitions of source_to_code in the base classes
6061
def path_mtime(self, path: str) -> float: ...
6162
def set_data(self, path: str, data: bytes) -> None: ...
6263
def get_source(self, fullname: str) -> str | None: ...
@@ -101,7 +102,7 @@ else:
101102
# Not defined on the actual class, but expected to exist.
102103
def find_spec(self, fullname: str, target: types.ModuleType | None = ...) -> ModuleSpec | None: ...
103104

104-
class FileLoader(ResourceLoader, ExecutionLoader, metaclass=ABCMeta):
105+
class FileLoader(_bootstrap_external.FileLoader, ResourceLoader, ExecutionLoader, metaclass=ABCMeta):
105106
name: str
106107
path: str
107108
def __init__(self, fullname: str, path: str) -> None: ...

0 commit comments

Comments
 (0)