From 87447ecc69756beb6f3d9471ed0b6c8c7aa8148e Mon Sep 17 00:00:00 2001 From: Max Muoto Date: Mon, 16 Jun 2025 14:00:15 -0500 Subject: [PATCH 01/22] Add 3.14 deprecations --- stdlib/argparse.pyi | 37 ++++++++++++++++------ stdlib/asyncio/coroutines.pyi | 32 +++++++++++++------ stdlib/asyncio/unix_events.pyi | 2 ++ stdlib/asyncio/windows_events.pyi | 8 +++++ stdlib/builtins.pyi | 46 ++++++++++++++++++++++----- stdlib/codecs.pyi | 15 ++++++--- stdlib/os/__init__.pyi | 52 ++++++++++++++++++++++++------- stdlib/pathlib/__init__.pyi | 6 +++- stdlib/pdb.pyi | 9 ++++-- 9 files changed, 163 insertions(+), 44 deletions(-) diff --git a/stdlib/argparse.pyi b/stdlib/argparse.pyi index 312093c0aa55..568455fb1752 100644 --- a/stdlib/argparse.pyi +++ b/stdlib/argparse.pyi @@ -91,15 +91,34 @@ class _ActionsContainer: version: str = ..., **kwargs: Any, ) -> Action: ... - def add_argument_group( - self, - title: str | None = None, - description: str | None = None, - *, - prefix_chars: str = ..., - argument_default: Any = ..., - conflict_handler: str = ..., - ) -> _ArgumentGroup: ... + if sys.version_info >= (3, 14): + @overload + def add_argument_group( + self, + title: str | None = None, + description: str | None = None, + ) -> _ArgumentGroup: ... + @overload + @deprecated("Passing 'prefix_chars' to add_argument_group() is deprecated") + def add_argument_group( + self, + title: str | None = None, + description: str | None = None, + *, + prefix_chars: str = ..., + argument_default: Any = ..., + conflict_handler: str = ..., + ) -> _ArgumentGroup: ... + else: + def add_argument_group( + self, + title: str | None = None, + description: str | None = None, + *, + prefix_chars: str = ..., + argument_default: Any = ..., + conflict_handler: str = ..., + ) -> _ArgumentGroup: ... def add_mutually_exclusive_group(self, *, required: bool = False) -> _MutuallyExclusiveGroup: ... def _add_action(self, action: _ActionT) -> _ActionT: ... def _remove_action(self, action: Action) -> None: ... diff --git a/stdlib/asyncio/coroutines.pyi b/stdlib/asyncio/coroutines.pyi index 8ef30b3d3198..0bc190de3f36 100644 --- a/stdlib/asyncio/coroutines.pyi +++ b/stdlib/asyncio/coroutines.pyi @@ -1,7 +1,7 @@ import sys from collections.abc import Awaitable, Callable, Coroutine from typing import Any, TypeVar, overload -from typing_extensions import ParamSpec, TypeGuard, TypeIs +from typing_extensions import ParamSpec, TypeGuard, TypeIs, deprecated # Keep asyncio.__all__ updated with any changes to __all__ here if sys.version_info >= (3, 11): @@ -16,12 +16,26 @@ _P = ParamSpec("_P") if sys.version_info < (3, 11): def coroutine(func: _FunctionT) -> _FunctionT: ... -@overload -def iscoroutinefunction(func: Callable[..., Coroutine[Any, Any, Any]]) -> bool: ... -@overload -def iscoroutinefunction(func: Callable[_P, Awaitable[_T]]) -> TypeGuard[Callable[_P, Coroutine[Any, Any, _T]]]: ... -@overload -def iscoroutinefunction(func: Callable[_P, object]) -> TypeGuard[Callable[_P, Coroutine[Any, Any, Any]]]: ... -@overload -def iscoroutinefunction(func: object) -> TypeGuard[Callable[..., Coroutine[Any, Any, Any]]]: ... +if sys.version_info >= (3, 14): + @overload + @deprecated("Deprecated in Python 3.14; use inspect.iscoroutinefunction() instead") + def iscoroutinefunction(func: Callable[..., Coroutine[Any, Any, Any]]) -> bool: ... + @overload + @deprecated("Deprecated in Python 3.14; use inspect.iscoroutinefunction() instead") + def iscoroutinefunction(func: Callable[_P, Awaitable[_T]]) -> TypeGuard[Callable[_P, Coroutine[Any, Any, _T]]]: ... + @overload + @deprecated("Deprecated in Python 3.14; use inspect.iscoroutinefunction() instead") + def iscoroutinefunction(func: Callable[_P, object]) -> TypeGuard[Callable[_P, Coroutine[Any, Any, Any]]]: ... + @overload + @deprecated("Deprecated in Python 3.14; use inspect.iscoroutinefunction() instead") + def iscoroutinefunction(func: object) -> TypeGuard[Callable[..., Coroutine[Any, Any, Any]]]: ... +else: + @overload + def iscoroutinefunction(func: Callable[..., Coroutine[Any, Any, Any]]) -> bool: ... + @overload + def iscoroutinefunction(func: Callable[_P, Awaitable[_T]]) -> TypeGuard[Callable[_P, Coroutine[Any, Any, _T]]]: ... + @overload + def iscoroutinefunction(func: Callable[_P, object]) -> TypeGuard[Callable[_P, Coroutine[Any, Any, Any]]]: ... + @overload + def iscoroutinefunction(func: object) -> TypeGuard[Callable[..., Coroutine[Any, Any, Any]]]: ... def iscoroutine(obj: object) -> TypeIs[Coroutine[Any, Any, Any]]: ... diff --git a/stdlib/asyncio/unix_events.pyi b/stdlib/asyncio/unix_events.pyi index 49f200dcdcae..e9602072ebc8 100644 --- a/stdlib/asyncio/unix_events.pyi +++ b/stdlib/asyncio/unix_events.pyi @@ -183,6 +183,8 @@ if sys.platform != "win32": if sys.version_info >= (3, 14): _DefaultEventLoopPolicy = _UnixDefaultEventLoopPolicy + @deprecated("Deprecated as of Python 3.14; will be removed in Python 3.16") + class DefaultEventLoopPolicy(_UnixDefaultEventLoopPolicy): ... else: DefaultEventLoopPolicy = _UnixDefaultEventLoopPolicy diff --git a/stdlib/asyncio/windows_events.pyi b/stdlib/asyncio/windows_events.pyi index b454aca1f262..88f5576c8701 100644 --- a/stdlib/asyncio/windows_events.pyi +++ b/stdlib/asyncio/windows_events.pyi @@ -3,6 +3,7 @@ import sys from _typeshed import Incomplete, ReadableBuffer, WriteableBuffer from collections.abc import Callable from typing import IO, Any, ClassVar, Final, NoReturn +from typing_extensions import deprecated from . import events, futures, proactor_events, selector_events, streams, windows_utils @@ -115,6 +116,13 @@ if sys.platform == "win32": if sys.version_info >= (3, 14): _DefaultEventLoopPolicy = _WindowsProactorEventLoopPolicy + + @deprecated("Deprecated as of Python 3.14; will be removed in Python 3.16") + class DefaultEventLoopPolicy(_WindowsProactorEventLoopPolicy): ... + @deprecated("Deprecated as of Python 3.14; will be removed in Python 3.16") + class WindowsSelectorEventLoopPolicy(_WindowsSelectorEventLoopPolicy): ... + @deprecated("Deprecated as of Python 3.14; will be removed in Python 3.16") + class WindowsProactorEventLoopPolicy(_WindowsProactorEventLoopPolicy): ... else: DefaultEventLoopPolicy = WindowsSelectorEventLoopPolicy if sys.version_info >= (3, 13): diff --git a/stdlib/builtins.pyi b/stdlib/builtins.pyi index 8de58f1a3d43..45ae0b16b0f4 100644 --- a/stdlib/builtins.pyi +++ b/stdlib/builtins.pyi @@ -416,14 +416,44 @@ class float: class complex: # Python doesn't currently accept SupportsComplex for the second argument - @overload - def __new__( - cls, - real: complex | SupportsComplex | SupportsFloat | SupportsIndex = ..., - imag: complex | SupportsFloat | SupportsIndex = ..., - ) -> Self: ... - @overload - def __new__(cls, real: str | SupportsComplex | SupportsFloat | SupportsIndex | complex) -> Self: ... + if sys.version_info >= (3, 14): + @overload + def __new__( + cls, + real: SupportsComplex | SupportsFloat | SupportsIndex = ..., + imag: SupportsFloat | SupportsIndex = ..., + ) -> Self: ... + @overload + def __new__(cls, real: str | SupportsComplex | SupportsFloat | SupportsIndex) -> Self: ... + @overload + @deprecated( + "Passing a complex number as the 'real' or 'imag' argument is deprecated. " + "Use the single-argument form instead." + ) + def __new__( + cls, + real: complex, + imag: complex | SupportsFloat | SupportsIndex = ..., + ) -> Self: ... + @overload + @deprecated( + "Passing a complex number as the 'real' or 'imag' argument is deprecated. " + "Use the single-argument form instead." + ) + def __new__( + cls, + real: SupportsComplex | SupportsFloat | SupportsIndex | complex = ..., + imag: complex, + ) -> Self: ... + else: + @overload + def __new__( + cls, + real: complex | SupportsComplex | SupportsFloat | SupportsIndex = ..., + imag: complex | SupportsFloat | SupportsIndex = ..., + ) -> Self: ... + @overload + def __new__(cls, real: str | SupportsComplex | SupportsFloat | SupportsIndex | complex) -> Self: ... @property def real(self) -> float: ... @property diff --git a/stdlib/codecs.pyi b/stdlib/codecs.pyi index 579d09c66a1b..b0a5b373ccb8 100644 --- a/stdlib/codecs.pyi +++ b/stdlib/codecs.pyi @@ -1,10 +1,11 @@ +import sys import types from _codecs import * from _typeshed import ReadableBuffer from abc import abstractmethod from collections.abc import Callable, Generator, Iterable from typing import Any, BinaryIO, ClassVar, Final, Literal, Protocol, TextIO, overload -from typing_extensions import Self, TypeAlias +from typing_extensions import Self, TypeAlias, deprecated __all__ = [ "register", @@ -149,9 +150,15 @@ def getincrementaldecoder(encoding: _BufferedEncoding) -> _BufferedIncrementalDe def getincrementaldecoder(encoding: str) -> _IncrementalDecoder: ... def getreader(encoding: str) -> _StreamReader: ... def getwriter(encoding: str) -> _StreamWriter: ... -def open( - filename: str, mode: str = "r", encoding: str | None = None, errors: str = "strict", buffering: int = -1 -) -> StreamReaderWriter: ... +if sys.version_info >= (3, 14): + @deprecated("codecs.open() is deprecated. Use open() instead.") + def open( + filename: str, mode: str = "r", encoding: str | None = None, errors: str = "strict", buffering: int = -1 + ) -> StreamReaderWriter: ... +else: + def open( + filename: str, mode: str = "r", encoding: str | None = None, errors: str = "strict", buffering: int = -1 + ) -> StreamReaderWriter: ... def EncodedFile(file: _Stream, data_encoding: str, file_encoding: str | None = None, errors: str = "strict") -> StreamRecoder: ... def iterencode(iterator: Iterable[str], encoding: str, errors: str = "strict") -> Generator[bytes, None, None]: ... def iterdecode(iterator: Iterable[bytes], encoding: str, errors: str = "strict") -> Generator[str, None, None]: ... diff --git a/stdlib/os/__init__.pyi b/stdlib/os/__init__.pyi index 5286c76d1b06..1254ba643c61 100644 --- a/stdlib/os/__init__.pyi +++ b/stdlib/os/__init__.pyi @@ -1387,17 +1387,37 @@ class _wrap_close: def write(self, s: str, /) -> int: ... def writelines(self, lines: Iterable[str], /) -> None: ... -def popen(cmd: str, mode: str = "r", buffering: int = -1) -> _wrap_close: ... -def spawnl(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: StrOrBytesPath) -> int: ... -def spawnle(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: Any) -> int: ... # Imprecise sig +if sys.version_info >= (3, 14): + @deprecated("os.popen is soft deprecated. Use subprocess instead.") + def popen(cmd: str, mode: str = "r", buffering: int = -1) -> _wrap_close: ... + @deprecated("os.spawnl is soft deprecated. Use subprocess instead.") + def spawnl(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: StrOrBytesPath) -> int: ... + @deprecated("os.spawnle is soft deprecated. Use subprocess instead.") + def spawnle(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: Any) -> int: ... # Imprecise sig +else: + def popen(cmd: str, mode: str = "r", buffering: int = -1) -> _wrap_close: ... + def spawnl(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: StrOrBytesPath) -> int: ... + def spawnle(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: Any) -> int: ... # Imprecise sig if sys.platform != "win32": - def spawnv(mode: int, file: StrOrBytesPath, args: _ExecVArgs) -> int: ... - def spawnve(mode: int, file: StrOrBytesPath, args: _ExecVArgs, env: _ExecEnv) -> int: ... + if sys.version_info >= (3, 14): + @deprecated("os.spawnv is soft deprecated. Use subprocess instead.") + def spawnv(mode: int, file: StrOrBytesPath, args: _ExecVArgs) -> int: ... + @deprecated("os.spawnve is soft deprecated. Use subprocess instead.") + def spawnve(mode: int, file: StrOrBytesPath, args: _ExecVArgs, env: _ExecEnv) -> int: ... + else: + def spawnv(mode: int, file: StrOrBytesPath, args: _ExecVArgs) -> int: ... + def spawnve(mode: int, file: StrOrBytesPath, args: _ExecVArgs, env: _ExecEnv) -> int: ... else: - def spawnv(mode: int, path: StrOrBytesPath, argv: _ExecVArgs, /) -> int: ... - def spawnve(mode: int, path: StrOrBytesPath, argv: _ExecVArgs, env: _ExecEnv, /) -> int: ... + if sys.version_info >= (3, 14): + @deprecated("os.spawnv is soft deprecated. Use subprocess instead.") + def spawnv(mode: int, path: StrOrBytesPath, argv: _ExecVArgs, /) -> int: ... + @deprecated("os.spawnve is soft deprecated. Use subprocess instead.") + def spawnve(mode: int, path: StrOrBytesPath, argv: _ExecVArgs, env: _ExecEnv, /) -> int: ... + else: + def spawnv(mode: int, path: StrOrBytesPath, argv: _ExecVArgs, /) -> int: ... + def spawnve(mode: int, path: StrOrBytesPath, argv: _ExecVArgs, env: _ExecEnv, /) -> int: ... def system(command: StrOrBytesPath) -> int: ... @final @@ -1432,10 +1452,20 @@ if sys.platform == "win32": def startfile(filepath: StrOrBytesPath, operation: str = ...) -> None: ... else: - def spawnlp(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: StrOrBytesPath) -> int: ... - def spawnlpe(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: Any) -> int: ... # Imprecise signature - def spawnvp(mode: int, file: StrOrBytesPath, args: _ExecVArgs) -> int: ... - def spawnvpe(mode: int, file: StrOrBytesPath, args: _ExecVArgs, env: _ExecEnv) -> int: ... + if sys.version_info >= (3, 14): + @deprecated("os.spawnlp is soft deprecated. Use subprocess instead.") + def spawnlp(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: StrOrBytesPath) -> int: ... + @deprecated("os.spawnlpe is soft deprecated. Use subprocess instead.") + def spawnlpe(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: Any) -> int: ... # Imprecise signature + @deprecated("os.spawnvp is soft deprecated. Use subprocess instead.") + def spawnvp(mode: int, file: StrOrBytesPath, args: _ExecVArgs) -> int: ... + @deprecated("os.spawnvpe is soft deprecated. Use subprocess instead.") + def spawnvpe(mode: int, file: StrOrBytesPath, args: _ExecVArgs, env: _ExecEnv) -> int: ... + else: + def spawnlp(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: StrOrBytesPath) -> int: ... + def spawnlpe(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: Any) -> int: ... # Imprecise signature + def spawnvp(mode: int, file: StrOrBytesPath, args: _ExecVArgs) -> int: ... + def spawnvpe(mode: int, file: StrOrBytesPath, args: _ExecVArgs, env: _ExecEnv) -> int: ... def wait() -> tuple[int, int]: ... # Unix only # Added to MacOS in 3.13 if sys.platform != "darwin" or sys.version_info >= (3, 13): diff --git a/stdlib/pathlib/__init__.pyi b/stdlib/pathlib/__init__.pyi index b84fc69313a1..39aaee958425 100644 --- a/stdlib/pathlib/__init__.pyi +++ b/stdlib/pathlib/__init__.pyi @@ -65,7 +65,11 @@ class PurePath(PathLike[str]): def __rtruediv__(self, key: StrPath) -> Self: ... def __bytes__(self) -> bytes: ... def as_posix(self) -> str: ... - def as_uri(self) -> str: ... + if sys.version_info >= (3, 14): + @deprecated("PurePath.as_uri() is deprecated. Use Path.as_uri() instead.") + def as_uri(self) -> str: ... + else: + def as_uri(self) -> str: ... def is_absolute(self) -> bool: ... def is_reserved(self) -> bool: ... if sys.version_info >= (3, 14): diff --git a/stdlib/pdb.pyi b/stdlib/pdb.pyi index ad69fcab16de..4025c0e4d5fa 100644 --- a/stdlib/pdb.pyi +++ b/stdlib/pdb.pyi @@ -7,7 +7,7 @@ from inspect import _SourceObjectType from linecache import _ModuleGlobals from types import CodeType, FrameType, TracebackType from typing import IO, Any, ClassVar, Final, Literal, TypeVar -from typing_extensions import ParamSpec, Self, TypeAlias +from typing_extensions import ParamSpec, Self, TypeAlias, deprecated __all__ = ["run", "pm", "Pdb", "runeval", "runctx", "runcall", "set_trace", "post_mortem", "help"] if sys.version_info >= (3, 14): @@ -59,7 +59,12 @@ class Pdb(Bdb, Cmd): stack: list[tuple[FrameType, int]] curindex: int curframe: FrameType | None - curframe_locals: Mapping[str, Any] + if sys.version_info >= (3, 14): + @property + @deprecated("curframe_locals is deprecated. Use get_frame_locals() instead.") + def curframe_locals(self) -> Mapping[str, Any]: ... + else: + curframe_locals: Mapping[str, Any] if sys.version_info >= (3, 14): mode: _Mode | None colorize: bool From 2e340410cfd5cf9ea5c5806299f9bd27051405b6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 16 Jun 2025 19:02:15 +0000 Subject: [PATCH 02/22] [pre-commit.ci] auto fixes from pre-commit.com hooks --- stdlib/argparse.pyi | 7 ++----- stdlib/asyncio/coroutines.pyi | 2 ++ stdlib/asyncio/unix_events.pyi | 1 + stdlib/asyncio/windows_events.pyi | 5 ++++- stdlib/codecs.pyi | 3 +++ stdlib/os/__init__.pyi | 2 ++ stdlib/pathlib/__init__.pyi | 1 + 7 files changed, 15 insertions(+), 6 deletions(-) diff --git a/stdlib/argparse.pyi b/stdlib/argparse.pyi index 568455fb1752..58ad3eb2b91d 100644 --- a/stdlib/argparse.pyi +++ b/stdlib/argparse.pyi @@ -93,11 +93,7 @@ class _ActionsContainer: ) -> Action: ... if sys.version_info >= (3, 14): @overload - def add_argument_group( - self, - title: str | None = None, - description: str | None = None, - ) -> _ArgumentGroup: ... + def add_argument_group(self, title: str | None = None, description: str | None = None) -> _ArgumentGroup: ... @overload @deprecated("Passing 'prefix_chars' to add_argument_group() is deprecated") def add_argument_group( @@ -119,6 +115,7 @@ class _ActionsContainer: argument_default: Any = ..., conflict_handler: str = ..., ) -> _ArgumentGroup: ... + def add_mutually_exclusive_group(self, *, required: bool = False) -> _MutuallyExclusiveGroup: ... def _add_action(self, action: _ActionT) -> _ActionT: ... def _remove_action(self, action: Action) -> None: ... diff --git a/stdlib/asyncio/coroutines.pyi b/stdlib/asyncio/coroutines.pyi index 0bc190de3f36..c4136aec5ff2 100644 --- a/stdlib/asyncio/coroutines.pyi +++ b/stdlib/asyncio/coroutines.pyi @@ -29,6 +29,7 @@ if sys.version_info >= (3, 14): @overload @deprecated("Deprecated in Python 3.14; use inspect.iscoroutinefunction() instead") def iscoroutinefunction(func: object) -> TypeGuard[Callable[..., Coroutine[Any, Any, Any]]]: ... + else: @overload def iscoroutinefunction(func: Callable[..., Coroutine[Any, Any, Any]]) -> bool: ... @@ -38,4 +39,5 @@ else: def iscoroutinefunction(func: Callable[_P, object]) -> TypeGuard[Callable[_P, Coroutine[Any, Any, Any]]]: ... @overload def iscoroutinefunction(func: object) -> TypeGuard[Callable[..., Coroutine[Any, Any, Any]]]: ... + def iscoroutine(obj: object) -> TypeIs[Coroutine[Any, Any, Any]]: ... diff --git a/stdlib/asyncio/unix_events.pyi b/stdlib/asyncio/unix_events.pyi index e9602072ebc8..a91b1de20a96 100644 --- a/stdlib/asyncio/unix_events.pyi +++ b/stdlib/asyncio/unix_events.pyi @@ -185,6 +185,7 @@ if sys.platform != "win32": _DefaultEventLoopPolicy = _UnixDefaultEventLoopPolicy @deprecated("Deprecated as of Python 3.14; will be removed in Python 3.16") class DefaultEventLoopPolicy(_UnixDefaultEventLoopPolicy): ... + else: DefaultEventLoopPolicy = _UnixDefaultEventLoopPolicy diff --git a/stdlib/asyncio/windows_events.pyi b/stdlib/asyncio/windows_events.pyi index 88f5576c8701..7899ddad224f 100644 --- a/stdlib/asyncio/windows_events.pyi +++ b/stdlib/asyncio/windows_events.pyi @@ -116,13 +116,16 @@ if sys.platform == "win32": if sys.version_info >= (3, 14): _DefaultEventLoopPolicy = _WindowsProactorEventLoopPolicy - + @deprecated("Deprecated as of Python 3.14; will be removed in Python 3.16") class DefaultEventLoopPolicy(_WindowsProactorEventLoopPolicy): ... + @deprecated("Deprecated as of Python 3.14; will be removed in Python 3.16") class WindowsSelectorEventLoopPolicy(_WindowsSelectorEventLoopPolicy): ... + @deprecated("Deprecated as of Python 3.14; will be removed in Python 3.16") class WindowsProactorEventLoopPolicy(_WindowsProactorEventLoopPolicy): ... + else: DefaultEventLoopPolicy = WindowsSelectorEventLoopPolicy if sys.version_info >= (3, 13): diff --git a/stdlib/codecs.pyi b/stdlib/codecs.pyi index b0a5b373ccb8..a40efb4b87cb 100644 --- a/stdlib/codecs.pyi +++ b/stdlib/codecs.pyi @@ -150,15 +150,18 @@ def getincrementaldecoder(encoding: _BufferedEncoding) -> _BufferedIncrementalDe def getincrementaldecoder(encoding: str) -> _IncrementalDecoder: ... def getreader(encoding: str) -> _StreamReader: ... def getwriter(encoding: str) -> _StreamWriter: ... + if sys.version_info >= (3, 14): @deprecated("codecs.open() is deprecated. Use open() instead.") def open( filename: str, mode: str = "r", encoding: str | None = None, errors: str = "strict", buffering: int = -1 ) -> StreamReaderWriter: ... + else: def open( filename: str, mode: str = "r", encoding: str | None = None, errors: str = "strict", buffering: int = -1 ) -> StreamReaderWriter: ... + def EncodedFile(file: _Stream, data_encoding: str, file_encoding: str | None = None, errors: str = "strict") -> StreamRecoder: ... def iterencode(iterator: Iterable[str], encoding: str, errors: str = "strict") -> Generator[bytes, None, None]: ... def iterdecode(iterator: Iterable[bytes], encoding: str, errors: str = "strict") -> Generator[str, None, None]: ... diff --git a/stdlib/os/__init__.pyi b/stdlib/os/__init__.pyi index 1254ba643c61..6c9e07835fc1 100644 --- a/stdlib/os/__init__.pyi +++ b/stdlib/os/__init__.pyi @@ -1394,6 +1394,7 @@ if sys.version_info >= (3, 14): def spawnl(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: StrOrBytesPath) -> int: ... @deprecated("os.spawnle is soft deprecated. Use subprocess instead.") def spawnle(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: Any) -> int: ... # Imprecise sig + else: def popen(cmd: str, mode: str = "r", buffering: int = -1) -> _wrap_close: ... def spawnl(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: StrOrBytesPath) -> int: ... @@ -1466,6 +1467,7 @@ else: def spawnlpe(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: Any) -> int: ... # Imprecise signature def spawnvp(mode: int, file: StrOrBytesPath, args: _ExecVArgs) -> int: ... def spawnvpe(mode: int, file: StrOrBytesPath, args: _ExecVArgs, env: _ExecEnv) -> int: ... + def wait() -> tuple[int, int]: ... # Unix only # Added to MacOS in 3.13 if sys.platform != "darwin" or sys.version_info >= (3, 13): diff --git a/stdlib/pathlib/__init__.pyi b/stdlib/pathlib/__init__.pyi index 39aaee958425..3cfdb6c6fbb9 100644 --- a/stdlib/pathlib/__init__.pyi +++ b/stdlib/pathlib/__init__.pyi @@ -70,6 +70,7 @@ class PurePath(PathLike[str]): def as_uri(self) -> str: ... else: def as_uri(self) -> str: ... + def is_absolute(self) -> bool: ... def is_reserved(self) -> bool: ... if sys.version_info >= (3, 14): From c52f7868d0001a3598dbd0f15fd74bb16bd3ba59 Mon Sep 17 00:00:00 2001 From: Max Muoto Date: Mon, 16 Jun 2025 14:11:04 -0500 Subject: [PATCH 03/22] Fix --- stdlib/builtins.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/builtins.pyi b/stdlib/builtins.pyi index 45ae0b16b0f4..911817e602c3 100644 --- a/stdlib/builtins.pyi +++ b/stdlib/builtins.pyi @@ -442,7 +442,7 @@ class complex: ) def __new__( cls, - real: SupportsComplex | SupportsFloat | SupportsIndex | complex = ..., + real: SupportsComplex | SupportsFloat | SupportsIndex | complex, imag: complex, ) -> Self: ... else: From 7b9288653cb6105e2a355fcdfc7efbe2e4eeb2b2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 16 Jun 2025 19:12:46 +0000 Subject: [PATCH 04/22] [pre-commit.ci] auto fixes from pre-commit.com hooks --- stdlib/builtins.pyi | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/stdlib/builtins.pyi b/stdlib/builtins.pyi index 911817e602c3..e26e86544106 100644 --- a/stdlib/builtins.pyi +++ b/stdlib/builtins.pyi @@ -419,32 +419,20 @@ class complex: if sys.version_info >= (3, 14): @overload def __new__( - cls, - real: SupportsComplex | SupportsFloat | SupportsIndex = ..., - imag: SupportsFloat | SupportsIndex = ..., + cls, real: SupportsComplex | SupportsFloat | SupportsIndex = ..., imag: SupportsFloat | SupportsIndex = ... ) -> Self: ... @overload def __new__(cls, real: str | SupportsComplex | SupportsFloat | SupportsIndex) -> Self: ... @overload @deprecated( - "Passing a complex number as the 'real' or 'imag' argument is deprecated. " - "Use the single-argument form instead." + "Passing a complex number as the 'real' or 'imag' argument is deprecated. " "Use the single-argument form instead." ) - def __new__( - cls, - real: complex, - imag: complex | SupportsFloat | SupportsIndex = ..., - ) -> Self: ... + def __new__(cls, real: complex, imag: complex | SupportsFloat | SupportsIndex = ...) -> Self: ... @overload @deprecated( - "Passing a complex number as the 'real' or 'imag' argument is deprecated. " - "Use the single-argument form instead." + "Passing a complex number as the 'real' or 'imag' argument is deprecated. " "Use the single-argument form instead." ) - def __new__( - cls, - real: SupportsComplex | SupportsFloat | SupportsIndex | complex, - imag: complex, - ) -> Self: ... + def __new__(cls, real: SupportsComplex | SupportsFloat | SupportsIndex | complex, imag: complex) -> Self: ... else: @overload def __new__( @@ -454,6 +442,7 @@ class complex: ) -> Self: ... @overload def __new__(cls, real: str | SupportsComplex | SupportsFloat | SupportsIndex | complex) -> Self: ... + @property def real(self) -> float: ... @property From 5c5315a5dbbe625009589bce6415428df3cb9136 Mon Sep 17 00:00:00 2001 From: Max Muoto Date: Mon, 16 Jun 2025 14:17:41 -0500 Subject: [PATCH 05/22] Fixes --- stdlib/asyncio/unix_events.pyi | 3 +-- stdlib/asyncio/windows_events.pyi | 9 --------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/stdlib/asyncio/unix_events.pyi b/stdlib/asyncio/unix_events.pyi index a91b1de20a96..941cd9f39333 100644 --- a/stdlib/asyncio/unix_events.pyi +++ b/stdlib/asyncio/unix_events.pyi @@ -168,6 +168,7 @@ if sys.platform != "win32": if sys.version_info >= (3, 14): class _UnixDefaultEventLoopPolicy(events._BaseDefaultEventLoopPolicy): ... + else: class _UnixDefaultEventLoopPolicy(events.BaseDefaultEventLoopPolicy): if sys.version_info >= (3, 12): @@ -183,8 +184,6 @@ if sys.platform != "win32": if sys.version_info >= (3, 14): _DefaultEventLoopPolicy = _UnixDefaultEventLoopPolicy - @deprecated("Deprecated as of Python 3.14; will be removed in Python 3.16") - class DefaultEventLoopPolicy(_UnixDefaultEventLoopPolicy): ... else: DefaultEventLoopPolicy = _UnixDefaultEventLoopPolicy diff --git a/stdlib/asyncio/windows_events.pyi b/stdlib/asyncio/windows_events.pyi index 7899ddad224f..658fbf690965 100644 --- a/stdlib/asyncio/windows_events.pyi +++ b/stdlib/asyncio/windows_events.pyi @@ -117,15 +117,6 @@ if sys.platform == "win32": if sys.version_info >= (3, 14): _DefaultEventLoopPolicy = _WindowsProactorEventLoopPolicy - @deprecated("Deprecated as of Python 3.14; will be removed in Python 3.16") - class DefaultEventLoopPolicy(_WindowsProactorEventLoopPolicy): ... - - @deprecated("Deprecated as of Python 3.14; will be removed in Python 3.16") - class WindowsSelectorEventLoopPolicy(_WindowsSelectorEventLoopPolicy): ... - - @deprecated("Deprecated as of Python 3.14; will be removed in Python 3.16") - class WindowsProactorEventLoopPolicy(_WindowsProactorEventLoopPolicy): ... - else: DefaultEventLoopPolicy = WindowsSelectorEventLoopPolicy if sys.version_info >= (3, 13): From 74badea1147dab5abbd290d42b3c74fc67a35f51 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 16 Jun 2025 19:19:23 +0000 Subject: [PATCH 06/22] [pre-commit.ci] auto fixes from pre-commit.com hooks --- stdlib/asyncio/unix_events.pyi | 1 - stdlib/asyncio/windows_events.pyi | 1 - 2 files changed, 2 deletions(-) diff --git a/stdlib/asyncio/unix_events.pyi b/stdlib/asyncio/unix_events.pyi index 941cd9f39333..a980c62b04d6 100644 --- a/stdlib/asyncio/unix_events.pyi +++ b/stdlib/asyncio/unix_events.pyi @@ -168,7 +168,6 @@ if sys.platform != "win32": if sys.version_info >= (3, 14): class _UnixDefaultEventLoopPolicy(events._BaseDefaultEventLoopPolicy): ... - else: class _UnixDefaultEventLoopPolicy(events.BaseDefaultEventLoopPolicy): if sys.version_info >= (3, 12): diff --git a/stdlib/asyncio/windows_events.pyi b/stdlib/asyncio/windows_events.pyi index 658fbf690965..98ef9208c8cb 100644 --- a/stdlib/asyncio/windows_events.pyi +++ b/stdlib/asyncio/windows_events.pyi @@ -3,7 +3,6 @@ import sys from _typeshed import Incomplete, ReadableBuffer, WriteableBuffer from collections.abc import Callable from typing import IO, Any, ClassVar, Final, NoReturn -from typing_extensions import deprecated from . import events, futures, proactor_events, selector_events, streams, windows_utils From 0f14bad848c374e03c56bd137d047949bb084ec9 Mon Sep 17 00:00:00 2001 From: Max Muoto Date: Mon, 16 Jun 2025 14:39:06 -0500 Subject: [PATCH 07/22] Revert --- stdlib/@tests/test_cases/check_complex.py | 32 +++++++++++++++++++++++ stdlib/builtins.pyi | 21 ++++++++------- 2 files changed, 44 insertions(+), 9 deletions(-) create mode 100644 stdlib/@tests/test_cases/check_complex.py diff --git a/stdlib/@tests/test_cases/check_complex.py b/stdlib/@tests/test_cases/check_complex.py new file mode 100644 index 000000000000..0102c8c0ca11 --- /dev/null +++ b/stdlib/@tests/test_cases/check_complex.py @@ -0,0 +1,32 @@ +import sys + + +class WithComplex: + def __init__(self, value: complex) -> None: + self.value = value + + def __complex__(self) -> complex: + return self.value + + +complex() +complex(10) +complex(4.0) +# Complex is only supported for the single argument form. +complex(4.25 + 0j) +complex(4.25 + 0j, 0) +# Str should also work +complex("1+2j") +complex("1+2j", 0) + +# Second argument must be a concrete complex number. +complex(0, WithComplex(4.25 + 0j)) # type: ignore +# Str isn't supported as a key-word argument. +complex(real="1+2j", imag=0) # type: ignore + + +if sys.version_info >= (3, 14): + # All deprecated in 3.14. + complex(real=34 + 0j) # type: ignore + complex(real=34 + 0j, imag=34 + 0j) # type: ignore + complex(real=3, imag=34 + 0j) # type: ignore diff --git a/stdlib/builtins.pyi b/stdlib/builtins.pyi index e26e86544106..5f4a6bfe0c36 100644 --- a/stdlib/builtins.pyi +++ b/stdlib/builtins.pyi @@ -415,24 +415,27 @@ class float: def from_number(cls, number: float | SupportsIndex | SupportsFloat, /) -> Self: ... class complex: - # Python doesn't currently accept SupportsComplex for the second argument if sys.version_info >= (3, 14): @overload def __new__( - cls, real: SupportsComplex | SupportsFloat | SupportsIndex = ..., imag: SupportsFloat | SupportsIndex = ... + cls, + real: complex | SupportsComplex | SupportsFloat | SupportsIndex | str, + /, + imag: complex | SupportsFloat | SupportsIndex = ..., ) -> Self: ... @overload - def __new__(cls, real: str | SupportsComplex | SupportsFloat | SupportsIndex) -> Self: ... + def __new__(cls, real: SupportsFloat | SupportsIndex = ..., imag: SupportsFloat | SupportsIndex = ...) -> Self: ... @overload - @deprecated( - "Passing a complex number as the 'real' or 'imag' argument is deprecated. " "Use the single-argument form instead." - ) - def __new__(cls, real: complex, imag: complex | SupportsFloat | SupportsIndex = ...) -> Self: ... + def __new__(cls, real: SupportsFloat | SupportsIndex) -> Self: ... @overload @deprecated( - "Passing a complex number as the 'real' or 'imag' argument is deprecated. " "Use the single-argument form instead." + "Passing a complex number as the 'real' or 'imag' argument is deprecated. Use the single-argument form instead." ) - def __new__(cls, real: SupportsComplex | SupportsFloat | SupportsIndex | complex, imag: complex) -> Self: ... + def __new__( + cls, + real: complex | SupportsComplex | SupportsFloat | SupportsIndex = ..., + imag: complex | SupportsFloat | SupportsIndex = ..., + ) -> Self: ... else: @overload def __new__( From da6d451d72e9349b070fd303ec9022e6ed96c576 Mon Sep 17 00:00:00 2001 From: Max Muoto Date: Mon, 16 Jun 2025 14:43:06 -0500 Subject: [PATCH 08/22] Fix --- stdlib/builtins.pyi | 2 -- 1 file changed, 2 deletions(-) diff --git a/stdlib/builtins.pyi b/stdlib/builtins.pyi index 5f4a6bfe0c36..fa34cb047ad2 100644 --- a/stdlib/builtins.pyi +++ b/stdlib/builtins.pyi @@ -426,8 +426,6 @@ class complex: @overload def __new__(cls, real: SupportsFloat | SupportsIndex = ..., imag: SupportsFloat | SupportsIndex = ...) -> Self: ... @overload - def __new__(cls, real: SupportsFloat | SupportsIndex) -> Self: ... - @overload @deprecated( "Passing a complex number as the 'real' or 'imag' argument is deprecated. Use the single-argument form instead." ) From 6661c3585c54973c379583d654620dcd4256aa24 Mon Sep 17 00:00:00 2001 From: Max Muoto Date: Mon, 16 Jun 2025 20:17:31 -0500 Subject: [PATCH 09/22] Revert --- stdlib/builtins.pyi | 38 +++++++++----------------------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/stdlib/builtins.pyi b/stdlib/builtins.pyi index fa34cb047ad2..8de58f1a3d43 100644 --- a/stdlib/builtins.pyi +++ b/stdlib/builtins.pyi @@ -415,35 +415,15 @@ class float: def from_number(cls, number: float | SupportsIndex | SupportsFloat, /) -> Self: ... class complex: - if sys.version_info >= (3, 14): - @overload - def __new__( - cls, - real: complex | SupportsComplex | SupportsFloat | SupportsIndex | str, - /, - imag: complex | SupportsFloat | SupportsIndex = ..., - ) -> Self: ... - @overload - def __new__(cls, real: SupportsFloat | SupportsIndex = ..., imag: SupportsFloat | SupportsIndex = ...) -> Self: ... - @overload - @deprecated( - "Passing a complex number as the 'real' or 'imag' argument is deprecated. Use the single-argument form instead." - ) - def __new__( - cls, - real: complex | SupportsComplex | SupportsFloat | SupportsIndex = ..., - imag: complex | SupportsFloat | SupportsIndex = ..., - ) -> Self: ... - else: - @overload - def __new__( - cls, - real: complex | SupportsComplex | SupportsFloat | SupportsIndex = ..., - imag: complex | SupportsFloat | SupportsIndex = ..., - ) -> Self: ... - @overload - def __new__(cls, real: str | SupportsComplex | SupportsFloat | SupportsIndex | complex) -> Self: ... - + # Python doesn't currently accept SupportsComplex for the second argument + @overload + def __new__( + cls, + real: complex | SupportsComplex | SupportsFloat | SupportsIndex = ..., + imag: complex | SupportsFloat | SupportsIndex = ..., + ) -> Self: ... + @overload + def __new__(cls, real: str | SupportsComplex | SupportsFloat | SupportsIndex | complex) -> Self: ... @property def real(self) -> float: ... @property From 1e2e61732cf25d2e8d8ac576a1d4b6affc5faf7d Mon Sep 17 00:00:00 2001 From: Max Muoto Date: Mon, 16 Jun 2025 20:21:41 -0500 Subject: [PATCH 10/22] Fix --- stdlib/@tests/test_cases/check_complex.py | 32 ----------------------- 1 file changed, 32 deletions(-) delete mode 100644 stdlib/@tests/test_cases/check_complex.py diff --git a/stdlib/@tests/test_cases/check_complex.py b/stdlib/@tests/test_cases/check_complex.py deleted file mode 100644 index 0102c8c0ca11..000000000000 --- a/stdlib/@tests/test_cases/check_complex.py +++ /dev/null @@ -1,32 +0,0 @@ -import sys - - -class WithComplex: - def __init__(self, value: complex) -> None: - self.value = value - - def __complex__(self) -> complex: - return self.value - - -complex() -complex(10) -complex(4.0) -# Complex is only supported for the single argument form. -complex(4.25 + 0j) -complex(4.25 + 0j, 0) -# Str should also work -complex("1+2j") -complex("1+2j", 0) - -# Second argument must be a concrete complex number. -complex(0, WithComplex(4.25 + 0j)) # type: ignore -# Str isn't supported as a key-word argument. -complex(real="1+2j", imag=0) # type: ignore - - -if sys.version_info >= (3, 14): - # All deprecated in 3.14. - complex(real=34 + 0j) # type: ignore - complex(real=34 + 0j, imag=34 + 0j) # type: ignore - complex(real=3, imag=34 + 0j) # type: ignore From ed659034e556d3012c5ad67bb069ff202b2b74ed Mon Sep 17 00:00:00 2001 From: Max Muoto Date: Mon, 16 Jun 2025 20:39:29 -0500 Subject: [PATCH 11/22] Fix --- .../test_cases/asyncio/check_coroutines.py | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/stdlib/@tests/test_cases/asyncio/check_coroutines.py b/stdlib/@tests/test_cases/asyncio/check_coroutines.py index 160bd896469e..9b7d025f9c0a 100644 --- a/stdlib/@tests/test_cases/asyncio/check_coroutines.py +++ b/stdlib/@tests/test_cases/asyncio/check_coroutines.py @@ -1,25 +1,30 @@ from __future__ import annotations + +import sys + from asyncio import iscoroutinefunction from collections.abc import Awaitable, Callable, Coroutine from typing import Any from typing_extensions import assert_type -def test_iscoroutinefunction( - x: Callable[[str, int], Coroutine[str, int, bytes]], - y: Callable[[str, int], Awaitable[bytes]], - z: Callable[[str, int], str | Awaitable[bytes]], - xx: object, -) -> None: - if iscoroutinefunction(x): - assert_type(x, Callable[[str, int], Coroutine[str, int, bytes]]) +if sys.version_info < (3, 14): + + def test_iscoroutinefunction( + x: Callable[[str, int], Coroutine[str, int, bytes]], + y: Callable[[str, int], Awaitable[bytes]], + z: Callable[[str, int], str | Awaitable[bytes]], + xx: object, + ) -> None: + if iscoroutinefunction(x): + assert_type(x, Callable[[str, int], Coroutine[str, int, bytes]]) - if iscoroutinefunction(y): - assert_type(y, Callable[[str, int], Coroutine[Any, Any, bytes]]) + if iscoroutinefunction(y): + assert_type(y, Callable[[str, int], Coroutine[Any, Any, bytes]]) - if iscoroutinefunction(z): - assert_type(z, Callable[[str, int], Coroutine[Any, Any, Any]]) + if iscoroutinefunction(z): + assert_type(z, Callable[[str, int], Coroutine[Any, Any, Any]]) - if iscoroutinefunction(xx): - assert_type(xx, Callable[..., Coroutine[Any, Any, Any]]) + if iscoroutinefunction(xx): + assert_type(xx, Callable[..., Coroutine[Any, Any, Any]]) From 2bffae42dde48b804bc6efc78694f95fba9454fa Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 17 Jun 2025 01:41:09 +0000 Subject: [PATCH 12/22] [pre-commit.ci] auto fixes from pre-commit.com hooks --- stdlib/@tests/test_cases/asyncio/check_coroutines.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/stdlib/@tests/test_cases/asyncio/check_coroutines.py b/stdlib/@tests/test_cases/asyncio/check_coroutines.py index 9b7d025f9c0a..5f87ed2c8679 100644 --- a/stdlib/@tests/test_cases/asyncio/check_coroutines.py +++ b/stdlib/@tests/test_cases/asyncio/check_coroutines.py @@ -1,14 +1,11 @@ from __future__ import annotations - import sys - from asyncio import iscoroutinefunction from collections.abc import Awaitable, Callable, Coroutine from typing import Any from typing_extensions import assert_type - if sys.version_info < (3, 14): def test_iscoroutinefunction( From 647bb882a733f8ddb7270a3b592cea2539b60532 Mon Sep 17 00:00:00 2001 From: Max Muoto Date: Wed, 18 Jun 2025 16:18:47 -0500 Subject: [PATCH 13/22] Address comments --- stdlib/argparse.pyi | 9 +++++- stdlib/asyncio/coroutines.pyi | 35 ++++++++--------------- stdlib/codecs.pyi | 14 +++------ stdlib/os/__init__.pyi | 53 ++++++++--------------------------- stdlib/pathlib/__init__.pyi | 7 ----- stdlib/pdb.pyi | 2 +- 6 files changed, 36 insertions(+), 84 deletions(-) diff --git a/stdlib/argparse.pyi b/stdlib/argparse.pyi index 58ad3eb2b91d..d358378a989c 100644 --- a/stdlib/argparse.pyi +++ b/stdlib/argparse.pyi @@ -93,7 +93,14 @@ class _ActionsContainer: ) -> Action: ... if sys.version_info >= (3, 14): @overload - def add_argument_group(self, title: str | None = None, description: str | None = None) -> _ArgumentGroup: ... + def add_argument_group( + self, + title: str | None = None, + description: str | None = None, + *, + argument_default: Any = ..., + conflict_handler: str = ..., + ) -> _ArgumentGroup: ... @overload @deprecated("Passing 'prefix_chars' to add_argument_group() is deprecated") def add_argument_group( diff --git a/stdlib/asyncio/coroutines.pyi b/stdlib/asyncio/coroutines.pyi index c4136aec5ff2..acb2f29edd31 100644 --- a/stdlib/asyncio/coroutines.pyi +++ b/stdlib/asyncio/coroutines.pyi @@ -16,28 +16,17 @@ _P = ParamSpec("_P") if sys.version_info < (3, 11): def coroutine(func: _FunctionT) -> _FunctionT: ... -if sys.version_info >= (3, 14): - @overload - @deprecated("Deprecated in Python 3.14; use inspect.iscoroutinefunction() instead") - def iscoroutinefunction(func: Callable[..., Coroutine[Any, Any, Any]]) -> bool: ... - @overload - @deprecated("Deprecated in Python 3.14; use inspect.iscoroutinefunction() instead") - def iscoroutinefunction(func: Callable[_P, Awaitable[_T]]) -> TypeGuard[Callable[_P, Coroutine[Any, Any, _T]]]: ... - @overload - @deprecated("Deprecated in Python 3.14; use inspect.iscoroutinefunction() instead") - def iscoroutinefunction(func: Callable[_P, object]) -> TypeGuard[Callable[_P, Coroutine[Any, Any, Any]]]: ... - @overload - @deprecated("Deprecated in Python 3.14; use inspect.iscoroutinefunction() instead") - def iscoroutinefunction(func: object) -> TypeGuard[Callable[..., Coroutine[Any, Any, Any]]]: ... - -else: - @overload - def iscoroutinefunction(func: Callable[..., Coroutine[Any, Any, Any]]) -> bool: ... - @overload - def iscoroutinefunction(func: Callable[_P, Awaitable[_T]]) -> TypeGuard[Callable[_P, Coroutine[Any, Any, _T]]]: ... - @overload - def iscoroutinefunction(func: Callable[_P, object]) -> TypeGuard[Callable[_P, Coroutine[Any, Any, Any]]]: ... - @overload - def iscoroutinefunction(func: object) -> TypeGuard[Callable[..., Coroutine[Any, Any, Any]]]: ... +@overload +@deprecated("Deprecated in Python 3.14; use inspect.iscoroutinefunction() instead") +def iscoroutinefunction(func: Callable[..., Coroutine[Any, Any, Any]]) -> bool: ... +@overload +@deprecated("Deprecated in Python 3.14; use inspect.iscoroutinefunction() instead") +def iscoroutinefunction(func: Callable[_P, Awaitable[_T]]) -> TypeGuard[Callable[_P, Coroutine[Any, Any, _T]]]: ... +@overload +@deprecated("Deprecated in Python 3.14; use inspect.iscoroutinefunction() instead") +def iscoroutinefunction(func: Callable[_P, object]) -> TypeGuard[Callable[_P, Coroutine[Any, Any, Any]]]: ... +@overload +@deprecated("Deprecated in Python 3.14; use inspect.iscoroutinefunction() instead") +def iscoroutinefunction(func: object) -> TypeGuard[Callable[..., Coroutine[Any, Any, Any]]]: ... def iscoroutine(obj: object) -> TypeIs[Coroutine[Any, Any, Any]]: ... diff --git a/stdlib/codecs.pyi b/stdlib/codecs.pyi index a40efb4b87cb..e57f2e21d607 100644 --- a/stdlib/codecs.pyi +++ b/stdlib/codecs.pyi @@ -151,16 +151,10 @@ def getincrementaldecoder(encoding: str) -> _IncrementalDecoder: ... def getreader(encoding: str) -> _StreamReader: ... def getwriter(encoding: str) -> _StreamWriter: ... -if sys.version_info >= (3, 14): - @deprecated("codecs.open() is deprecated. Use open() instead.") - def open( - filename: str, mode: str = "r", encoding: str | None = None, errors: str = "strict", buffering: int = -1 - ) -> StreamReaderWriter: ... - -else: - def open( - filename: str, mode: str = "r", encoding: str | None = None, errors: str = "strict", buffering: int = -1 - ) -> StreamReaderWriter: ... +@deprecated("codecs.open() is deprecated. Use open() instead.") +def open( + filename: str, mode: str = "r", encoding: str | None = None, errors: str = "strict", buffering: int = -1 +) -> StreamReaderWriter: ... def EncodedFile(file: _Stream, data_encoding: str, file_encoding: str | None = None, errors: str = "strict") -> StreamRecoder: ... def iterencode(iterator: Iterable[str], encoding: str, errors: str = "strict") -> Generator[bytes, None, None]: ... diff --git a/stdlib/os/__init__.pyi b/stdlib/os/__init__.pyi index 6c9e07835fc1..aca90f7c4059 100644 --- a/stdlib/os/__init__.pyi +++ b/stdlib/os/__init__.pyi @@ -1387,38 +1387,17 @@ class _wrap_close: def write(self, s: str, /) -> int: ... def writelines(self, lines: Iterable[str], /) -> None: ... -if sys.version_info >= (3, 14): - @deprecated("os.popen is soft deprecated. Use subprocess instead.") - def popen(cmd: str, mode: str = "r", buffering: int = -1) -> _wrap_close: ... - @deprecated("os.spawnl is soft deprecated. Use subprocess instead.") - def spawnl(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: StrOrBytesPath) -> int: ... - @deprecated("os.spawnle is soft deprecated. Use subprocess instead.") - def spawnle(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: Any) -> int: ... # Imprecise sig - -else: - def popen(cmd: str, mode: str = "r", buffering: int = -1) -> _wrap_close: ... - def spawnl(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: StrOrBytesPath) -> int: ... - def spawnle(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: Any) -> int: ... # Imprecise sig +def popen(cmd: str, mode: str = "r", buffering: int = -1) -> _wrap_close: ... +def spawnl(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: StrOrBytesPath) -> int: ... +def spawnle(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: Any) -> int: ... # Imprecise sig if sys.platform != "win32": - if sys.version_info >= (3, 14): - @deprecated("os.spawnv is soft deprecated. Use subprocess instead.") - def spawnv(mode: int, file: StrOrBytesPath, args: _ExecVArgs) -> int: ... - @deprecated("os.spawnve is soft deprecated. Use subprocess instead.") - def spawnve(mode: int, file: StrOrBytesPath, args: _ExecVArgs, env: _ExecEnv) -> int: ... - else: - def spawnv(mode: int, file: StrOrBytesPath, args: _ExecVArgs) -> int: ... - def spawnve(mode: int, file: StrOrBytesPath, args: _ExecVArgs, env: _ExecEnv) -> int: ... + def spawnv(mode: int, file: StrOrBytesPath, args: _ExecVArgs) -> int: ... + def spawnve(mode: int, file: StrOrBytesPath, args: _ExecVArgs, env: _ExecEnv) -> int: ... else: - if sys.version_info >= (3, 14): - @deprecated("os.spawnv is soft deprecated. Use subprocess instead.") - def spawnv(mode: int, path: StrOrBytesPath, argv: _ExecVArgs, /) -> int: ... - @deprecated("os.spawnve is soft deprecated. Use subprocess instead.") - def spawnve(mode: int, path: StrOrBytesPath, argv: _ExecVArgs, env: _ExecEnv, /) -> int: ... - else: - def spawnv(mode: int, path: StrOrBytesPath, argv: _ExecVArgs, /) -> int: ... - def spawnve(mode: int, path: StrOrBytesPath, argv: _ExecVArgs, env: _ExecEnv, /) -> int: ... + def spawnv(mode: int, path: StrOrBytesPath, argv: _ExecVArgs, /) -> int: ... + def spawnve(mode: int, path: StrOrBytesPath, argv: _ExecVArgs, env: _ExecEnv, /) -> int: ... def system(command: StrOrBytesPath) -> int: ... @final @@ -1453,20 +1432,10 @@ if sys.platform == "win32": def startfile(filepath: StrOrBytesPath, operation: str = ...) -> None: ... else: - if sys.version_info >= (3, 14): - @deprecated("os.spawnlp is soft deprecated. Use subprocess instead.") - def spawnlp(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: StrOrBytesPath) -> int: ... - @deprecated("os.spawnlpe is soft deprecated. Use subprocess instead.") - def spawnlpe(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: Any) -> int: ... # Imprecise signature - @deprecated("os.spawnvp is soft deprecated. Use subprocess instead.") - def spawnvp(mode: int, file: StrOrBytesPath, args: _ExecVArgs) -> int: ... - @deprecated("os.spawnvpe is soft deprecated. Use subprocess instead.") - def spawnvpe(mode: int, file: StrOrBytesPath, args: _ExecVArgs, env: _ExecEnv) -> int: ... - else: - def spawnlp(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: StrOrBytesPath) -> int: ... - def spawnlpe(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: Any) -> int: ... # Imprecise signature - def spawnvp(mode: int, file: StrOrBytesPath, args: _ExecVArgs) -> int: ... - def spawnvpe(mode: int, file: StrOrBytesPath, args: _ExecVArgs, env: _ExecEnv) -> int: ... + def spawnlp(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: StrOrBytesPath) -> int: ... + def spawnlpe(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: Any) -> int: ... # Imprecise signature + def spawnvp(mode: int, file: StrOrBytesPath, args: _ExecVArgs) -> int: ... + def spawnvpe(mode: int, file: StrOrBytesPath, args: _ExecVArgs, env: _ExecEnv) -> int: ... def wait() -> tuple[int, int]: ... # Unix only # Added to MacOS in 3.13 diff --git a/stdlib/pathlib/__init__.pyi b/stdlib/pathlib/__init__.pyi index 3cfdb6c6fbb9..feeb1c97f49b 100644 --- a/stdlib/pathlib/__init__.pyi +++ b/stdlib/pathlib/__init__.pyi @@ -65,12 +65,6 @@ class PurePath(PathLike[str]): def __rtruediv__(self, key: StrPath) -> Self: ... def __bytes__(self) -> bytes: ... def as_posix(self) -> str: ... - if sys.version_info >= (3, 14): - @deprecated("PurePath.as_uri() is deprecated. Use Path.as_uri() instead.") - def as_uri(self) -> str: ... - else: - def as_uri(self) -> str: ... - def is_absolute(self) -> bool: ... def is_reserved(self) -> bool: ... if sys.version_info >= (3, 14): @@ -168,7 +162,6 @@ class Path(PurePath): def mkdir(self, mode: int = 0o777, parents: bool = False, exist_ok: bool = False) -> None: ... if sys.version_info >= (3, 14): - @property def info(self) -> PathInfo: ... @overload diff --git a/stdlib/pdb.pyi b/stdlib/pdb.pyi index 4025c0e4d5fa..9438740cb21a 100644 --- a/stdlib/pdb.pyi +++ b/stdlib/pdb.pyi @@ -61,7 +61,7 @@ class Pdb(Bdb, Cmd): curframe: FrameType | None if sys.version_info >= (3, 14): @property - @deprecated("curframe_locals is deprecated. Use get_frame_locals() instead.") + @deprecated("curframe_locals is deprecated. Derived debuggers should access pdb.Pdb.curframe.f_locals instead.") def curframe_locals(self) -> Mapping[str, Any]: ... else: curframe_locals: Mapping[str, Any] From d40fc6c8e30b39d9a28afd8d8b6172b751e315a9 Mon Sep 17 00:00:00 2001 From: Max Muoto Date: Wed, 18 Jun 2025 16:21:33 -0500 Subject: [PATCH 14/22] Fix --- stdlib/codecs.pyi | 3 --- 1 file changed, 3 deletions(-) diff --git a/stdlib/codecs.pyi b/stdlib/codecs.pyi index e57f2e21d607..45c4111289b4 100644 --- a/stdlib/codecs.pyi +++ b/stdlib/codecs.pyi @@ -1,4 +1,3 @@ -import sys import types from _codecs import * from _typeshed import ReadableBuffer @@ -150,12 +149,10 @@ def getincrementaldecoder(encoding: _BufferedEncoding) -> _BufferedIncrementalDe def getincrementaldecoder(encoding: str) -> _IncrementalDecoder: ... def getreader(encoding: str) -> _StreamReader: ... def getwriter(encoding: str) -> _StreamWriter: ... - @deprecated("codecs.open() is deprecated. Use open() instead.") def open( filename: str, mode: str = "r", encoding: str | None = None, errors: str = "strict", buffering: int = -1 ) -> StreamReaderWriter: ... - def EncodedFile(file: _Stream, data_encoding: str, file_encoding: str | None = None, errors: str = "strict") -> StreamRecoder: ... def iterencode(iterator: Iterable[str], encoding: str, errors: str = "strict") -> Generator[bytes, None, None]: ... def iterdecode(iterator: Iterable[bytes], encoding: str, errors: str = "strict") -> Generator[str, None, None]: ... From 83efd5dabb3486d66b1c894b112ffe2f4a192f7d Mon Sep 17 00:00:00 2001 From: Max Muoto Date: Wed, 18 Jun 2025 16:22:26 -0500 Subject: [PATCH 15/22] revert --- stdlib/pathlib/__init__.pyi | 1 + 1 file changed, 1 insertion(+) diff --git a/stdlib/pathlib/__init__.pyi b/stdlib/pathlib/__init__.pyi index feeb1c97f49b..7319176f372a 100644 --- a/stdlib/pathlib/__init__.pyi +++ b/stdlib/pathlib/__init__.pyi @@ -65,6 +65,7 @@ class PurePath(PathLike[str]): def __rtruediv__(self, key: StrPath) -> Self: ... def __bytes__(self) -> bytes: ... def as_posix(self) -> str: ... + def as_uri(self) -> str: ... def is_absolute(self) -> bool: ... def is_reserved(self) -> bool: ... if sys.version_info >= (3, 14): From 90c97d4681758e623a32be45bcfec07b217be8a8 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 18 Jun 2025 21:22:54 +0000 Subject: [PATCH 16/22] [pre-commit.ci] auto fixes from pre-commit.com hooks --- stdlib/asyncio/coroutines.pyi | 1 - stdlib/os/__init__.pyi | 1 - 2 files changed, 2 deletions(-) diff --git a/stdlib/asyncio/coroutines.pyi b/stdlib/asyncio/coroutines.pyi index acb2f29edd31..23e5fcdb2741 100644 --- a/stdlib/asyncio/coroutines.pyi +++ b/stdlib/asyncio/coroutines.pyi @@ -28,5 +28,4 @@ def iscoroutinefunction(func: Callable[_P, object]) -> TypeGuard[Callable[_P, Co @overload @deprecated("Deprecated in Python 3.14; use inspect.iscoroutinefunction() instead") def iscoroutinefunction(func: object) -> TypeGuard[Callable[..., Coroutine[Any, Any, Any]]]: ... - def iscoroutine(obj: object) -> TypeIs[Coroutine[Any, Any, Any]]: ... diff --git a/stdlib/os/__init__.pyi b/stdlib/os/__init__.pyi index aca90f7c4059..5286c76d1b06 100644 --- a/stdlib/os/__init__.pyi +++ b/stdlib/os/__init__.pyi @@ -1436,7 +1436,6 @@ else: def spawnlpe(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: Any) -> int: ... # Imprecise signature def spawnvp(mode: int, file: StrOrBytesPath, args: _ExecVArgs) -> int: ... def spawnvpe(mode: int, file: StrOrBytesPath, args: _ExecVArgs, env: _ExecEnv) -> int: ... - def wait() -> tuple[int, int]: ... # Unix only # Added to MacOS in 3.13 if sys.platform != "darwin" or sys.version_info >= (3, 13): From 7eccbacbde88edcfd4ce69e60d58920bb0149d10 Mon Sep 17 00:00:00 2001 From: Max Muoto Date: Wed, 18 Jun 2025 16:23:55 -0500 Subject: [PATCH 17/22] Add override --- stdlib/pathlib/__init__.pyi | 3 +++ 1 file changed, 3 insertions(+) diff --git a/stdlib/pathlib/__init__.pyi b/stdlib/pathlib/__init__.pyi index 7319176f372a..dde13c42363d 100644 --- a/stdlib/pathlib/__init__.pyi +++ b/stdlib/pathlib/__init__.pyi @@ -65,6 +65,7 @@ class PurePath(PathLike[str]): def __rtruediv__(self, key: StrPath) -> Self: ... def __bytes__(self) -> bytes: ... def as_posix(self) -> str: ... + @deprecated("PurePath.as_uri() is deprecated. Use Path.as_uri() instead.") def as_uri(self) -> str: ... def is_absolute(self) -> bool: ... def is_reserved(self) -> bool: ... @@ -299,6 +300,8 @@ class Path(PurePath): self, top_down: bool = ..., on_error: Callable[[OSError], object] | None = ..., follow_symlinks: bool = ... ) -> Iterator[tuple[Self, list[str], list[str]]]: ... + def as_uri(self) -> str: ... + class PosixPath(Path, PurePosixPath): ... class WindowsPath(Path, PureWindowsPath): ... From 4f5c981d06d33f88d7a48585f22b7751786ab7f6 Mon Sep 17 00:00:00 2001 From: Max Muoto Date: Wed, 18 Jun 2025 16:27:49 -0500 Subject: [PATCH 18/22] Fix tests --- .../test_cases/asyncio/check_coroutines.py | 52 +++++++++++++------ 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/stdlib/@tests/test_cases/asyncio/check_coroutines.py b/stdlib/@tests/test_cases/asyncio/check_coroutines.py index 5f87ed2c8679..b3751a7b10a0 100644 --- a/stdlib/@tests/test_cases/asyncio/check_coroutines.py +++ b/stdlib/@tests/test_cases/asyncio/check_coroutines.py @@ -1,27 +1,47 @@ from __future__ import annotations -import sys from asyncio import iscoroutinefunction +import inspect + from collections.abc import Awaitable, Callable, Coroutine from typing import Any from typing_extensions import assert_type -if sys.version_info < (3, 14): - def test_iscoroutinefunction( - x: Callable[[str, int], Coroutine[str, int, bytes]], - y: Callable[[str, int], Awaitable[bytes]], - z: Callable[[str, int], str | Awaitable[bytes]], - xx: object, - ) -> None: - if iscoroutinefunction(x): - assert_type(x, Callable[[str, int], Coroutine[str, int, bytes]]) +def test_iscoroutinefunction_asyncio( + x: Callable[[str, int], Coroutine[str, int, bytes]], + y: Callable[[str, int], Awaitable[bytes]], + z: Callable[[str, int], str | Awaitable[bytes]], + xx: object, +) -> None: + # Type ignores are neeeded due to deprecation of iscoroutinefunction in 3.14 + if iscoroutinefunction(x): # type: ignore + assert_type(x, Callable[[str, int], Coroutine[str, int, bytes]]) + + if iscoroutinefunction(y): # type: ignore + assert_type(y, Callable[[str, int], Coroutine[Any, Any, bytes]]) + + if iscoroutinefunction(z): # type: ignore + assert_type(z, Callable[[str, int], Coroutine[Any, Any, Any]]) + + if iscoroutinefunction(xx): # type: ignore + assert_type(xx, Callable[..., Coroutine[Any, Any, Any]]) + + +def test_iscoroutinefunction_inspect( + x: Callable[[str, int], Coroutine[str, int, bytes]], + y: Callable[[str, int], Awaitable[bytes]], + z: Callable[[str, int], str | Awaitable[bytes]], + xx: object, +) -> None: + if inspect.iscoroutinefunction(x): + assert_type(x, Callable[[str, int], Coroutine[str, int, bytes]]) - if iscoroutinefunction(y): - assert_type(y, Callable[[str, int], Coroutine[Any, Any, bytes]]) + if inspect.iscoroutinefunction(y): + assert_type(y, Callable[[str, int], Coroutine[Any, Any, bytes]]) - if iscoroutinefunction(z): - assert_type(z, Callable[[str, int], Coroutine[Any, Any, Any]]) + if inspect.iscoroutinefunction(z): + assert_type(z, Callable[[str, int], Coroutine[Any, Any, Any]]) - if iscoroutinefunction(xx): - assert_type(xx, Callable[..., Coroutine[Any, Any, Any]]) + if inspect.iscoroutinefunction(xx): + assert_type(xx, Callable[..., Coroutine[Any, Any, Any]]) From 28a1743320806442aed5248910ab30e7bad28a19 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 18 Jun 2025 21:30:41 +0000 Subject: [PATCH 19/22] [pre-commit.ci] auto fixes from pre-commit.com hooks --- stdlib/@tests/test_cases/asyncio/check_coroutines.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/stdlib/@tests/test_cases/asyncio/check_coroutines.py b/stdlib/@tests/test_cases/asyncio/check_coroutines.py index b3751a7b10a0..da65197bc6db 100644 --- a/stdlib/@tests/test_cases/asyncio/check_coroutines.py +++ b/stdlib/@tests/test_cases/asyncio/check_coroutines.py @@ -1,8 +1,7 @@ from __future__ import annotations -from asyncio import iscoroutinefunction import inspect - +from asyncio import iscoroutinefunction from collections.abc import Awaitable, Callable, Coroutine from typing import Any from typing_extensions import assert_type From 3de835bfbfdfe052664982089a5113426d57e6d3 Mon Sep 17 00:00:00 2001 From: Max Muoto Date: Wed, 18 Jun 2025 16:36:42 -0500 Subject: [PATCH 20/22] Tweaks --- stdlib/@tests/test_cases/asyncio/check_coroutines.py | 7 ++++--- stdlib/asyncio/windows_events.pyi | 1 - 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/stdlib/@tests/test_cases/asyncio/check_coroutines.py b/stdlib/@tests/test_cases/asyncio/check_coroutines.py index da65197bc6db..a87ce5807596 100644 --- a/stdlib/@tests/test_cases/asyncio/check_coroutines.py +++ b/stdlib/@tests/test_cases/asyncio/check_coroutines.py @@ -4,6 +4,7 @@ from asyncio import iscoroutinefunction from collections.abc import Awaitable, Callable, Coroutine from typing import Any +from types import CoroutineType from typing_extensions import assert_type @@ -37,10 +38,10 @@ def test_iscoroutinefunction_inspect( assert_type(x, Callable[[str, int], Coroutine[str, int, bytes]]) if inspect.iscoroutinefunction(y): - assert_type(y, Callable[[str, int], Coroutine[Any, Any, bytes]]) + assert_type(y, Callable[[str, int], CoroutineType[Any, Any, bytes]]) if inspect.iscoroutinefunction(z): - assert_type(z, Callable[[str, int], Coroutine[Any, Any, Any]]) + assert_type(z, Callable[[str, int], CoroutineType[Any, Any, Any]]) if inspect.iscoroutinefunction(xx): - assert_type(xx, Callable[..., Coroutine[Any, Any, Any]]) + assert_type(xx, Callable[..., CoroutineType[Any, Any, Any]]) diff --git a/stdlib/asyncio/windows_events.pyi b/stdlib/asyncio/windows_events.pyi index 98ef9208c8cb..b454aca1f262 100644 --- a/stdlib/asyncio/windows_events.pyi +++ b/stdlib/asyncio/windows_events.pyi @@ -115,7 +115,6 @@ if sys.platform == "win32": if sys.version_info >= (3, 14): _DefaultEventLoopPolicy = _WindowsProactorEventLoopPolicy - else: DefaultEventLoopPolicy = WindowsSelectorEventLoopPolicy if sys.version_info >= (3, 13): From 8c4456302747a43339d0bc9fb173addc37598d57 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 18 Jun 2025 21:38:23 +0000 Subject: [PATCH 21/22] [pre-commit.ci] auto fixes from pre-commit.com hooks --- stdlib/@tests/test_cases/asyncio/check_coroutines.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/@tests/test_cases/asyncio/check_coroutines.py b/stdlib/@tests/test_cases/asyncio/check_coroutines.py index a87ce5807596..52377950de58 100644 --- a/stdlib/@tests/test_cases/asyncio/check_coroutines.py +++ b/stdlib/@tests/test_cases/asyncio/check_coroutines.py @@ -3,8 +3,8 @@ import inspect from asyncio import iscoroutinefunction from collections.abc import Awaitable, Callable, Coroutine -from typing import Any from types import CoroutineType +from typing import Any from typing_extensions import assert_type From 94c49d6accaf2873f3af4ed26a37eac15049faa4 Mon Sep 17 00:00:00 2001 From: Max Muoto Date: Wed, 18 Jun 2025 16:40:12 -0500 Subject: [PATCH 22/22] 3.13 --- stdlib/pdb.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/pdb.pyi b/stdlib/pdb.pyi index 9438740cb21a..ebccf4140a02 100644 --- a/stdlib/pdb.pyi +++ b/stdlib/pdb.pyi @@ -59,7 +59,7 @@ class Pdb(Bdb, Cmd): stack: list[tuple[FrameType, int]] curindex: int curframe: FrameType | None - if sys.version_info >= (3, 14): + if sys.version_info >= (3, 13): @property @deprecated("curframe_locals is deprecated. Derived debuggers should access pdb.Pdb.curframe.f_locals instead.") def curframe_locals(self) -> Mapping[str, Any]: ...