From 60dee785238693151567f5d69f929c150b9206d5 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sun, 10 May 2026 15:18:43 -0700 Subject: [PATCH 1/3] Add more Python 3.15 stdlib updates --- stdlib/@tests/stubtest_allowlists/py315.txt | 18 --- stdlib/ctypes/__init__.pyi | 18 ++- stdlib/glob.pyi | 17 +-- stdlib/gzip.pyi | 5 +- stdlib/marshal.pyi | 6 +- stdlib/multiprocessing/context.pyi | 8 +- stdlib/multiprocessing/forkserver.pyi | 10 +- stdlib/pdb.pyi | 6 +- stdlib/pkgutil.pyi | 7 +- stdlib/pprint.pyi | 135 ++++++++++++++------ stdlib/site.pyi | 21 ++- stdlib/symtable.pyi | 6 +- 12 files changed, 178 insertions(+), 79 deletions(-) diff --git a/stdlib/@tests/stubtest_allowlists/py315.txt b/stdlib/@tests/stubtest_allowlists/py315.txt index 910f72b6ae56..8fe8a6874cde 100644 --- a/stdlib/@tests/stubtest_allowlists/py315.txt +++ b/stdlib/@tests/stubtest_allowlists/py315.txt @@ -72,7 +72,6 @@ concurrent.interpreters._crossinterp.classonly.__isabstractmethod__ concurrent.interpreters._crossinterp.classonly.__set_name__ concurrent.interpreters._crossinterp.classonly.__wrapped__ copy.deepcopy -ctypes.SetPointerType dataclasses._MISSING_TYPE dataclasses.MISSING dataclasses.field @@ -90,9 +89,6 @@ genericpath.getmtime genericpath.getsize genericpath.samefile genericpath.samestat -glob.glob0 -glob.glob1 -gzip.compress http.HTTPMethod.description http.client.HTTPConnection.__init__ http.client.HTTPSConnection.__init__ @@ -124,10 +120,6 @@ io.Writer.write mailbox.Mailbox.__enter__ mailbox.Mailbox.__exit__ mailbox._ProxyFile.__class_getitem__ -marshal.dump -marshal.dumps -multiprocessing.context.BaseContext.set_forkserver_preload -multiprocessing.forkserver.ForkServer.set_forkserver_preload multiprocessing.managers.BaseListProxy.clear multiprocessing.managers.BaseListProxy.copy multiprocessing.managers._BaseDictProxy.__iter__ @@ -152,8 +144,6 @@ os.path.ALL_BUT_LAST os.path.__all__ pathlib.PurePath.__vfspath__ pathlib.PurePath.is_reserved -pdb.Pdb.print_stack_entry -pkgutil.resolve_name posixpath.ALL_BUT_LAST posixpath.__all__ posixpath.basename @@ -165,17 +155,9 @@ posixpath.split posixpath.splitdrive posixpath.splitext posixpath.splitroot -pprint.PrettyPrinter.__init__ -pprint.pformat -pprint.pprint -site.addsitedir -site.addsitepackages -site.addusersitepackages -site.process_startup_files sre_compile sre_constants sre_parse -symtable.symtable sys.__jit sys._monitoring sys.last_exc diff --git a/stdlib/ctypes/__init__.pyi b/stdlib/ctypes/__init__.pyi index 9bb8bb0edc29..a2471dc96061 100644 --- a/stdlib/ctypes/__init__.pyi +++ b/stdlib/ctypes/__init__.pyi @@ -165,10 +165,20 @@ def create_string_buffer(init: int | bytes, size: int | None = None) -> Array[c_ c_buffer = create_string_buffer def create_unicode_buffer(init: int | str, size: int | None = None) -> Array[c_wchar]: ... -@deprecated("Deprecated since Python 3.13; will be removed in Python 3.15.") -def SetPointerType(pointer: type[_Pointer[Any]], cls: _CTypeBaseType) -> None: ... -@deprecated("Soft deprecated since Python 3.13. Use multiplication instead.") -def ARRAY(typ: _CT, len: int) -> Array[_CT]: ... + +if sys.version_info < (3, 15): + if sys.version_info >= (3, 13): + @deprecated("Deprecated since Python 3.13; will be removed in Python 3.15.") + def SetPointerType(pointer: type[_Pointer[Any]], cls: _CTypeBaseType) -> None: ... + else: + def SetPointerType(pointer: type[_Pointer[Any]], cls: _CTypeBaseType) -> None: ... + +if sys.version_info >= (3, 13): + @deprecated("Soft deprecated since Python 3.13. Use multiplication instead.") + def ARRAY(typ: _CT, len: int) -> Array[_CT]: ... + +else: + def ARRAY(typ: _CT, len: int) -> Array[_CT]: ... if sys.platform == "win32": def DllCanUnloadNow() -> int: ... diff --git a/stdlib/glob.pyi b/stdlib/glob.pyi index 07455acaefc6..bdfb2cfbcfed 100644 --- a/stdlib/glob.pyi +++ b/stdlib/glob.pyi @@ -9,14 +9,15 @@ __all__ = ["escape", "glob", "iglob"] if sys.version_info >= (3, 13): __all__ += ["translate"] -@deprecated( - "Deprecated since Python 3.10; will be removed in Python 3.15. Use `glob.glob()` with the *root_dir* argument instead." -) -def glob0(dirname: AnyStr, pattern: AnyStr) -> list[AnyStr]: ... -@deprecated( - "Deprecated since Python 3.10; will be removed in Python 3.15. Use `glob.glob()` with the *root_dir* argument instead." -) -def glob1(dirname: AnyStr, pattern: AnyStr) -> list[AnyStr]: ... +if sys.version_info < (3, 15): + @deprecated( + "Deprecated since Python 3.10; will be removed in Python 3.15. Use `glob.glob()` with the *root_dir* argument instead." + ) + def glob0(dirname: AnyStr, pattern: AnyStr) -> list[AnyStr]: ... + @deprecated( + "Deprecated since Python 3.10; will be removed in Python 3.15. Use `glob.glob()` with the *root_dir* argument instead." + ) + def glob1(dirname: AnyStr, pattern: AnyStr) -> list[AnyStr]: ... if sys.version_info >= (3, 11): def glob( diff --git a/stdlib/gzip.pyi b/stdlib/gzip.pyi index de22625e403f..0202a927c806 100644 --- a/stdlib/gzip.pyi +++ b/stdlib/gzip.pyi @@ -167,7 +167,10 @@ class GzipFile(BaseStream): class _GzipReader(DecompressReader): def __init__(self, fp: _ReadableFileobj) -> None: ... -if sys.version_info >= (3, 14): +if sys.version_info >= (3, 15): + def compress(data: SizedBuffer, compresslevel: int = 6, *, mtime: float = 0) -> bytes: ... + +elif sys.version_info >= (3, 14): def compress(data: SizedBuffer, compresslevel: int = 9, *, mtime: float = 0) -> bytes: ... else: diff --git a/stdlib/marshal.pyi b/stdlib/marshal.pyi index ad0c4cb40ded..d72abe7758b7 100644 --- a/stdlib/marshal.pyi +++ b/stdlib/marshal.pyi @@ -27,7 +27,11 @@ _Marshallable: TypeAlias = ( | ReadableBuffer ) -if sys.version_info >= (3, 14): +if sys.version_info >= (3, 15): + def dump(value: _Marshallable, file: SupportsWrite[bytes], version: int = 6, /, *, allow_code: bool = True) -> None: ... + def dumps(value: _Marshallable, version: int = 6, /, *, allow_code: bool = True) -> bytes: ... + +elif sys.version_info >= (3, 14): def dump(value: _Marshallable, file: SupportsWrite[bytes], version: int = 5, /, *, allow_code: bool = True) -> None: ... def dumps(value: _Marshallable, version: int = 5, /, *, allow_code: bool = True) -> bytes: ... diff --git a/stdlib/multiprocessing/context.pyi b/stdlib/multiprocessing/context.pyi index 903acf158e55..c919774582d5 100644 --- a/stdlib/multiprocessing/context.pyi +++ b/stdlib/multiprocessing/context.pyi @@ -123,7 +123,13 @@ class BaseContext: def log_to_stderr(self, level: _LoggingLevel | None = None) -> Logger: ... def allow_connection_pickling(self) -> None: ... def set_executable(self, executable: str) -> None: ... - def set_forkserver_preload(self, module_names: list[str]) -> None: ... + if sys.version_info >= (3, 15): + def set_forkserver_preload( + self, module_names: list[str], *, on_error: Literal["ignore", "warn", "fail"] = "ignore" + ) -> None: ... + else: + def set_forkserver_preload(self, module_names: list[str]) -> None: ... + @overload def get_context(self, method: None = None) -> DefaultContext: ... @overload diff --git a/stdlib/multiprocessing/forkserver.pyi b/stdlib/multiprocessing/forkserver.pyi index f0af1ce7a827..e48be5f07949 100644 --- a/stdlib/multiprocessing/forkserver.pyi +++ b/stdlib/multiprocessing/forkserver.pyi @@ -2,7 +2,7 @@ import sys from _typeshed import FileDescriptorLike, Unused from collections.abc import Sequence from struct import Struct -from typing import Any, Final +from typing import Any, Final, Literal __all__ = ["ensure_running", "get_inherited_fds", "connect_to_new_process", "set_forkserver_preload"] @@ -10,7 +10,13 @@ MAXFDS_TO_SEND: Final = 256 SIGNED_STRUCT: Final[Struct] class ForkServer: - def set_forkserver_preload(self, modules_names: list[str]) -> None: ... + if sys.version_info >= (3, 15): + def set_forkserver_preload( + self, modules_names: list[str], *, on_error: Literal["ignore", "warn", "fail"] = "ignore" + ) -> None: ... + else: + def set_forkserver_preload(self, modules_names: list[str]) -> None: ... + def get_inherited_fds(self) -> list[int] | None: ... def connect_to_new_process(self, fds: Sequence[int]) -> tuple[int, int]: ... def ensure_running(self) -> None: ... diff --git a/stdlib/pdb.pyi b/stdlib/pdb.pyi index dda5cad3b679..289637cb5f04 100644 --- a/stdlib/pdb.pyi +++ b/stdlib/pdb.pyi @@ -136,7 +136,11 @@ class Pdb(Bdb, Cmd): else: def print_stack_trace(self) -> None: ... - def print_stack_entry(self, frame_lineno: tuple[FrameType, int], prompt_prefix: str = "\n-> ") -> None: ... + if sys.version_info >= (3, 15): + def print_stack_entry(self, frame_lineno: tuple[FrameType, int], prompt_prefix: str | None = None) -> None: ... + else: + def print_stack_entry(self, frame_lineno: tuple[FrameType, int], prompt_prefix: str = "\n-> ") -> None: ... + def lookupmodule(self, filename: str) -> str | None: ... if sys.version_info < (3, 11): def _runscript(self, filename: str) -> None: ... diff --git a/stdlib/pkgutil.pyi b/stdlib/pkgutil.pyi index 723f670e1619..365792bed952 100644 --- a/stdlib/pkgutil.pyi +++ b/stdlib/pkgutil.pyi @@ -52,4 +52,9 @@ def walk_packages( path: Iterable[StrOrBytesPath] | None = None, prefix: str = "", onerror: Callable[[str], object] | None = None ) -> Iterator[ModuleInfo]: ... def get_data(package: str, resource: str) -> bytes | None: ... -def resolve_name(name: str) -> Any: ... + +if sys.version_info >= (3, 15): + def resolve_name(name: str, *, strict: bool = False) -> Any: ... + +else: + def resolve_name(name: str) -> Any: ... diff --git a/stdlib/pprint.pyi b/stdlib/pprint.pyi index 4085731a2a05..1d3705ec6ff6 100644 --- a/stdlib/pprint.pyi +++ b/stdlib/pprint.pyi @@ -1,57 +1,116 @@ +import sys from _typeshed import SupportsWrite from collections import deque from typing import IO __all__ = ["pprint", "pformat", "isreadable", "isrecursive", "saferepr", "PrettyPrinter", "pp"] -def pformat( - object: object, - indent: int = 1, - width: int = 80, - depth: int | None = None, - *, - compact: bool = False, - sort_dicts: bool = True, - underscore_numbers: bool = False, -) -> str: ... -def pp( - object: object, - stream: IO[str] | None = None, - indent: int = 1, - width: int = 80, - depth: int | None = None, - *, - compact: bool = False, - sort_dicts: bool = False, - underscore_numbers: bool = False, -) -> None: ... -def pprint( - object: object, - stream: IO[str] | None = None, - indent: int = 1, - width: int = 80, - depth: int | None = None, - *, - compact: bool = False, - sort_dicts: bool = True, - underscore_numbers: bool = False, -) -> None: ... -def isreadable(object: object) -> bool: ... -def isrecursive(object: object) -> bool: ... -def saferepr(object: object) -> str: ... +if sys.version_info >= (3, 15): + def pformat( + object: object, + indent: int = 4, + width: int = 88, + depth: int | None = None, + *, + compact: bool = False, + sort_dicts: bool = True, + underscore_numbers: bool = False, + ) -> str: ... -class PrettyPrinter: - def __init__( - self, +else: + def pformat( + object: object, indent: int = 1, width: int = 80, depth: int | None = None, + *, + compact: bool = False, + sort_dicts: bool = True, + underscore_numbers: bool = False, + ) -> str: ... + +if sys.version_info >= (3, 15): + def pp( + object: object, + stream: IO[str] | None = None, + indent: int = 4, + width: int = 88, + depth: int | None = None, + *, + compact: bool = False, + sort_dicts: bool = False, + underscore_numbers: bool = False, + ) -> None: ... + +else: + def pp( + object: object, stream: IO[str] | None = None, + indent: int = 1, + width: int = 80, + depth: int | None = None, + *, + compact: bool = False, + sort_dicts: bool = False, + underscore_numbers: bool = False, + ) -> None: ... + +if sys.version_info >= (3, 15): + def pprint( + object: object, + stream: IO[str] | None = None, + indent: int = 4, + width: int = 88, + depth: int | None = None, + *, + compact: bool = False, + sort_dicts: bool = True, + underscore_numbers: bool = False, + ) -> None: ... + +else: + def pprint( + object: object, + stream: IO[str] | None = None, + indent: int = 1, + width: int = 80, + depth: int | None = None, *, compact: bool = False, sort_dicts: bool = True, underscore_numbers: bool = False, ) -> None: ... + +def isreadable(object: object) -> bool: ... +def isrecursive(object: object) -> bool: ... +def saferepr(object: object) -> str: ... + +class PrettyPrinter: + if sys.version_info >= (3, 15): + def __init__( + self, + indent: int = 4, + width: int = 88, + depth: int | None = None, + stream: IO[str] | None = None, + *, + compact: bool = False, + sort_dicts: bool = True, + underscore_numbers: bool = False, + ) -> None: ... + else: + def __init__( + self, + indent: int = 1, + width: int = 80, + depth: int | None = None, + stream: IO[str] | None = None, + *, + compact: bool = False, + sort_dicts: bool = True, + underscore_numbers: bool = False, + ) -> None: ... + def pformat(self, object: object) -> str: ... def pprint(self, object: object) -> None: ... def isreadable(self, object: object) -> bool: ... diff --git a/stdlib/site.pyi b/stdlib/site.pyi index 6e39677aaea0..da046ee510ad 100644 --- a/stdlib/site.pyi +++ b/stdlib/site.pyi @@ -10,9 +10,24 @@ USER_BASE: str | None def main() -> None: ... def abs_paths() -> None: ... # undocumented def addpackage(sitedir: StrPath, name: StrPath, known_paths: set[str] | None) -> set[str] | None: ... # undocumented -def addsitedir(sitedir: str, known_paths: set[str] | None = None) -> None: ... -def addsitepackages(known_paths: set[str] | None, prefixes: Iterable[str] | None = None) -> set[str] | None: ... # undocumented -def addusersitepackages(known_paths: set[str] | None) -> set[str] | None: ... # undocumented + +if sys.version_info >= (3, 15): + def process_startup_files() -> None: ... # undocumented + def addsitedir(sitedir: str, known_paths: set[str] | None = None, *, defer_processing_start_files: bool = False) -> None: ... + def addsitepackages( + known_paths: set[str] | None, prefixes: Iterable[str] | None = None, *, defer_processing_start_files: bool = False + ) -> set[str] | None: ... # undocumented + def addusersitepackages( + known_paths: set[str] | None, *, defer_processing_start_files: bool = False + ) -> set[str] | None: ... # undocumented + +else: + def addsitedir(sitedir: str, known_paths: set[str] | None = None) -> None: ... + def addsitepackages( + known_paths: set[str] | None, prefixes: Iterable[str] | None = None + ) -> set[str] | None: ... # undocumented + def addusersitepackages(known_paths: set[str] | None) -> set[str] | None: ... # undocumented + def check_enableusersite() -> bool | None: ... # undocumented if sys.version_info >= (3, 13): diff --git a/stdlib/symtable.pyi b/stdlib/symtable.pyi index d915d2e97dc8..d41ef8419dec 100644 --- a/stdlib/symtable.pyi +++ b/stdlib/symtable.pyi @@ -9,7 +9,11 @@ __all__ = ["symtable", "SymbolTable", "Class", "Function", "Symbol"] if sys.version_info >= (3, 13): __all__ += ["SymbolTableType"] -def symtable(code: str, filename: str, compile_type: str) -> SymbolTable: ... +if sys.version_info >= (3, 15): + def symtable(code: str, filename: str, compile_type: str, *, module: str | None = None) -> SymbolTable: ... + +else: + def symtable(code: str, filename: str, compile_type: str) -> SymbolTable: ... if sys.version_info >= (3, 13): from enum import StrEnum From cf3a5e8df393756cee3d9985e4a0077cacd784de Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sun, 10 May 2026 15:27:53 -0700 Subject: [PATCH 2/3] Keep ctypes time-travel deprecation --- stdlib/ctypes/__init__.pyi | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/stdlib/ctypes/__init__.pyi b/stdlib/ctypes/__init__.pyi index a2471dc96061..db45a33ec948 100644 --- a/stdlib/ctypes/__init__.pyi +++ b/stdlib/ctypes/__init__.pyi @@ -167,11 +167,8 @@ c_buffer = create_string_buffer def create_unicode_buffer(init: int | str, size: int | None = None) -> Array[c_wchar]: ... if sys.version_info < (3, 15): - if sys.version_info >= (3, 13): - @deprecated("Deprecated since Python 3.13; will be removed in Python 3.15.") - def SetPointerType(pointer: type[_Pointer[Any]], cls: _CTypeBaseType) -> None: ... - else: - def SetPointerType(pointer: type[_Pointer[Any]], cls: _CTypeBaseType) -> None: ... + @deprecated("Deprecated since Python 3.13; will be removed in Python 3.15.") + def SetPointerType(pointer: type[_Pointer[Any]], cls: _CTypeBaseType) -> None: ... if sys.version_info >= (3, 13): @deprecated("Soft deprecated since Python 3.13. Use multiplication instead.") From 2e7802f51c3a425b7f01ad86cd1e54f5493ed205 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sun, 10 May 2026 15:31:39 -0700 Subject: [PATCH 3/3] Keep ctypes ARRAY time-travel deprecation --- stdlib/ctypes/__init__.pyi | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/stdlib/ctypes/__init__.pyi b/stdlib/ctypes/__init__.pyi index db45a33ec948..9899a4068d59 100644 --- a/stdlib/ctypes/__init__.pyi +++ b/stdlib/ctypes/__init__.pyi @@ -170,12 +170,8 @@ if sys.version_info < (3, 15): @deprecated("Deprecated since Python 3.13; will be removed in Python 3.15.") def SetPointerType(pointer: type[_Pointer[Any]], cls: _CTypeBaseType) -> None: ... -if sys.version_info >= (3, 13): - @deprecated("Soft deprecated since Python 3.13. Use multiplication instead.") - def ARRAY(typ: _CT, len: int) -> Array[_CT]: ... - -else: - def ARRAY(typ: _CT, len: int) -> Array[_CT]: ... +@deprecated("Soft deprecated since Python 3.13. Use multiplication instead.") +def ARRAY(typ: _CT, len: int) -> Array[_CT]: ... if sys.platform == "win32": def DllCanUnloadNow() -> int: ...