Skip to content

Add 3.14 Deprecations #14289

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 28 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
87447ec
Add 3.14 deprecations
max-muoto Jun 16, 2025
2e34041
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 16, 2025
c52f786
Fix
max-muoto Jun 16, 2025
7b92886
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 16, 2025
5c5315a
Fixes
max-muoto Jun 16, 2025
74badea
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 16, 2025
0f14bad
Revert
max-muoto Jun 16, 2025
da6d451
Fix
max-muoto Jun 16, 2025
6661c35
Revert
max-muoto Jun 17, 2025
1e2e617
Fix
max-muoto Jun 17, 2025
ed65903
Fix
max-muoto Jun 17, 2025
2bffae4
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 17, 2025
647bb88
Address comments
max-muoto Jun 18, 2025
d40fc6c
Fix
max-muoto Jun 18, 2025
83efd5d
revert
max-muoto Jun 18, 2025
90c97d4
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 18, 2025
7eccbac
Add override
max-muoto Jun 18, 2025
4f5c981
Fix tests
max-muoto Jun 18, 2025
28a1743
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 18, 2025
3de835b
Tweaks
max-muoto Jun 18, 2025
8c44563
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 18, 2025
94c49d6
3.13
max-muoto Jun 18, 2025
7d0fb15
Merge branch 'main' into add-3.14-deprecations
srittau Jul 7, 2025
8f97cb9
Merge branch 'main' of https://github.com/max-muoto/typeshed into add…
max-muoto Jul 12, 2025
5c89ea7
Tweak
max-muoto Jul 12, 2025
3034a9d
Add ignore
max-muoto Jul 12, 2025
4fbdb04
Tweak tests
max-muoto Jul 12, 2025
3e6d012
Fix
max-muoto Jul 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 16 additions & 14 deletions stdlib/@tests/test_cases/asyncio/check_coroutines.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
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(
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(
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]])
34 changes: 25 additions & 9 deletions stdlib/argparse.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,31 @@ 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: ...
Expand Down
34 changes: 25 additions & 9 deletions stdlib/asyncio/coroutines.pyi
Original file line number Diff line number Diff line change
@@ -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):
Expand All @@ -16,12 +16,28 @@ _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]]: ...
1 change: 1 addition & 0 deletions stdlib/asyncio/unix_events.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ if sys.platform != "win32":

if sys.version_info >= (3, 14):
_DefaultEventLoopPolicy = _UnixDefaultEventLoopPolicy

else:
DefaultEventLoopPolicy = _UnixDefaultEventLoopPolicy

Expand Down
1 change: 1 addition & 0 deletions stdlib/asyncio/windows_events.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ if sys.platform == "win32":

if sys.version_info >= (3, 14):
_DefaultEventLoopPolicy = _WindowsProactorEventLoopPolicy

else:
DefaultEventLoopPolicy = WindowsSelectorEventLoopPolicy
if sys.version_info >= (3, 13):
Expand Down
18 changes: 14 additions & 4 deletions stdlib/codecs.pyi
Original file line number Diff line number Diff line change
@@ -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",
Expand Down Expand Up @@ -149,9 +150,18 @@ 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]: ...
Expand Down
54 changes: 43 additions & 11 deletions stdlib/os/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -1387,17 +1387,38 @@ 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
Expand Down Expand Up @@ -1432,10 +1453,21 @@ 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):
Expand Down
7 changes: 6 additions & 1 deletion stdlib/pathlib/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,12 @@ 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.")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's confusing, it's the same method. Also, we don't have an override for Path.as_uri, so people will see this deprecation even if they call the method on a Path.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missed the fact that we didn't have an override: 7eccbac

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the exact snippet from the release notes: pathlib.PurePath.as_uri() is deprecated and will be removed in Python 3.19. Use pathlib.Path.as_uri() instead

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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):
Expand Down
9 changes: 7 additions & 2 deletions stdlib/pdb.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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
Expand Down