From 620109c5a09f061a6cc99624f06e99ac72dc9173 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Thu, 9 Nov 2023 19:09:27 -0800 Subject: [PATCH 1/8] stdlib: more deprecations --- stdlib/argparse.pyi | 30 +++++++++++++++++++++++++++--- stdlib/asyncio/events.pyi | 6 +++++- stdlib/asyncio/unix_events.pyi | 8 +++++++- stdlib/builtins.pyi | 3 +++ stdlib/datetime.pyi | 4 +++- stdlib/email/utils.pyi | 6 +++++- stdlib/os/__init__.pyi | 11 ++++++++--- stdlib/pkgutil.pyi | 3 +++ stdlib/shutil.pyi | 13 ++++++++++--- stdlib/tarfile.pyi | 29 ++++++++++++++++++++++++++--- stdlib/types.pyi | 11 ++++++++--- stdlib/xml/etree/ElementTree.pyi | 4 +++- 12 files changed, 108 insertions(+), 20 deletions(-) diff --git a/stdlib/argparse.pyi b/stdlib/argparse.pyi index e947f67edd55..dca363f66b6b 100644 --- a/stdlib/argparse.pyi +++ b/stdlib/argparse.pyi @@ -3,7 +3,7 @@ from _typeshed import sentinel from collections.abc import Callable, Generator, Iterable, Sequence from re import Pattern from typing import IO, Any, Generic, NewType, NoReturn, Protocol, TypeVar, overload -from typing_extensions import Literal, Self, TypeAlias +from typing_extensions import Literal, Self, TypeAlias, deprecated __all__ = [ "ArgumentParser", @@ -337,11 +337,23 @@ class Action(_AttributeHolder): if sys.version_info >= (3, 12): class BooleanOptionalAction(Action): + @overload def __init__( self, option_strings: Sequence[str], dest: str, - default: _T | str | None = None, + default: bool | None = None, + *, + required: bool = False, + help: str | None = None, + ) -> None: ... + @overload + @deprecated("The `type`, `choices`, and `metavar` parameters are ignored and will be removed in Python 3.14.") + def __init__( + self, + option_strings: Sequence[str], + dest: str, + default: _T | bool | None = None, type: Callable[[str], _T] | FileType | None = sentinel, choices: Iterable[_T] | None = sentinel, required: bool = False, @@ -351,11 +363,23 @@ if sys.version_info >= (3, 12): elif sys.version_info >= (3, 9): class BooleanOptionalAction(Action): + @overload + def __init__( + self, + option_strings: Sequence[str], + dest: str, + default: bool | None = None, + *, + required: bool = False, + help: str | None = None, + ) -> None: ... + @overload + @deprecated("The `type`, `choices`, and `metavar` parameters are ignored and will be removed in Python 3.14.") def __init__( self, option_strings: Sequence[str], dest: str, - default: _T | str | None = None, + default: _T | bool | None = None, type: Callable[[str], _T] | FileType | None = None, choices: Iterable[_T] | None = None, required: bool = False, diff --git a/stdlib/asyncio/events.pyi b/stdlib/asyncio/events.pyi index 4c62043875ba..41bb63b32a67 100644 --- a/stdlib/asyncio/events.pyi +++ b/stdlib/asyncio/events.pyi @@ -6,7 +6,7 @@ from collections.abc import Callable, Coroutine, Generator, Sequence from contextvars import Context from socket import AddressFamily, SocketKind, _Address, _RetAddress, socket from typing import IO, Any, Protocol, TypeVar, overload -from typing_extensions import Literal, Self, TypeAlias +from typing_extensions import Literal, Self, TypeAlias, deprecated from . import _AwaitableLike, _CoroutineLike from .base_events import Server @@ -599,8 +599,10 @@ class AbstractEventLoopPolicy: def new_event_loop(self) -> AbstractEventLoop: ... # Child processes handling (Unix only). @abstractmethod + @deprecated("Deprecated as of Python 3.12; will be removed in Python 3.14") def get_child_watcher(self) -> AbstractChildWatcher: ... @abstractmethod + @deprecated("Deprecated as of Python 3.12; will be removed in Python 3.14") def set_child_watcher(self, watcher: AbstractChildWatcher) -> None: ... class BaseDefaultEventLoopPolicy(AbstractEventLoopPolicy, metaclass=ABCMeta): @@ -613,7 +615,9 @@ def set_event_loop_policy(policy: AbstractEventLoopPolicy | None) -> None: ... def get_event_loop() -> AbstractEventLoop: ... def set_event_loop(loop: AbstractEventLoop | None) -> None: ... def new_event_loop() -> AbstractEventLoop: ... +@deprecated("Deprecated as of Python 3.12; will be removed in Python 3.14") def get_child_watcher() -> AbstractChildWatcher: ... +@deprecated("Deprecated as of Python 3.12; will be removed in Python 3.14") def set_child_watcher(watcher: AbstractChildWatcher) -> None: ... def _set_running_loop(__loop: AbstractEventLoop | None) -> None: ... def _get_running_loop() -> AbstractEventLoop: ... diff --git a/stdlib/asyncio/unix_events.pyi b/stdlib/asyncio/unix_events.pyi index dc3d3496ae55..792566c9bd21 100644 --- a/stdlib/asyncio/unix_events.pyi +++ b/stdlib/asyncio/unix_events.pyi @@ -3,7 +3,7 @@ import types from abc import ABCMeta, abstractmethod from collections.abc import Callable from typing import Any -from typing_extensions import Literal, Self +from typing_extensions import Literal, Self, deprecated from .events import AbstractEventLoop, BaseDefaultEventLoopPolicy from .selector_events import BaseSelectorEventLoop @@ -11,6 +11,7 @@ from .selector_events import BaseSelectorEventLoop # This is also technically not available on Win, # but other parts of typeshed need this definition. # So, it is special cased. +@deprecated("Deprecated as of Python 3.12; will be removed in Python 3.14") class AbstractChildWatcher: @abstractmethod def add_child_handler(self, pid: int, callback: Callable[..., object], *args: Any) -> None: ... @@ -62,12 +63,14 @@ if sys.platform != "win32": def attach_loop(self, loop: AbstractEventLoop | None) -> None: ... + @deprecated("Deprecated as of Python 3.12; will be removed in Python 3.14") class SafeChildWatcher(BaseChildWatcher): def __enter__(self) -> Self: ... def __exit__(self, a: type[BaseException] | None, b: BaseException | None, c: types.TracebackType | None) -> None: ... def add_child_handler(self, pid: int, callback: Callable[..., object], *args: Any) -> None: ... def remove_child_handler(self, pid: int) -> bool: ... + @deprecated("Deprecated as of Python 3.12; will be removed in Python 3.14") class FastChildWatcher(BaseChildWatcher): def __enter__(self) -> Self: ... def __exit__(self, a: type[BaseException] | None, b: BaseException | None, c: types.TracebackType | None) -> None: ... @@ -77,13 +80,16 @@ if sys.platform != "win32": class _UnixSelectorEventLoop(BaseSelectorEventLoop): ... class _UnixDefaultEventLoopPolicy(BaseDefaultEventLoopPolicy): + @deprecated("Deprecated as of Python 3.12; will be removed in Python 3.14") def get_child_watcher(self) -> AbstractChildWatcher: ... + @deprecated("Deprecated as of Python 3.12; will be removed in Python 3.14") def set_child_watcher(self, watcher: AbstractChildWatcher | None) -> None: ... SelectorEventLoop = _UnixSelectorEventLoop DefaultEventLoopPolicy = _UnixDefaultEventLoopPolicy if sys.version_info >= (3, 8): + @deprecated("Deprecated as of Python 3.12; will be removed in Python 3.14") class MultiLoopChildWatcher(AbstractChildWatcher): def is_active(self) -> bool: ... def close(self) -> None: ... diff --git a/stdlib/builtins.pyi b/stdlib/builtins.pyi index f06820f496d8..565f12d530b1 100644 --- a/stdlib/builtins.pyi +++ b/stdlib/builtins.pyi @@ -64,6 +64,7 @@ from typing_extensions import ( TypeAlias, TypeGuard, TypeVarTuple, + deprecated, final, ) @@ -937,6 +938,8 @@ class bool(int): @overload def __rxor__(self, __value: int) -> int: ... def __getnewargs__(self) -> tuple[int]: ... + @deprecated("Will throw an error in Python 3.14. Use `not` for logical negation of bools instead.") + def __invert__(self) -> int: ... @final class slice: diff --git a/stdlib/datetime.pyi b/stdlib/datetime.pyi index 36577c5b7e1b..a14de8e30fdf 100644 --- a/stdlib/datetime.pyi +++ b/stdlib/datetime.pyi @@ -2,7 +2,7 @@ import sys from abc import abstractmethod from time import struct_time from typing import ClassVar, NamedTuple, NoReturn, TypeVar, overload -from typing_extensions import Literal, Self, SupportsIndex, TypeAlias, final +from typing_extensions import Literal, Self, SupportsIndex, TypeAlias, deprecated, final if sys.version_info >= (3, 11): __all__ = ("date", "datetime", "time", "timedelta", "timezone", "tzinfo", "MINYEAR", "MAXYEAR", "UTC") @@ -265,6 +265,7 @@ class datetime(date): def fromtimestamp(cls, __timestamp: float, tz: _TzInfo | None = ...) -> Self: ... @classmethod + @deprecated("Use timezone-aware objects to represent datetimes in UTC; e.g. by calling .fromtimestamp(datetime.UTC)") def utcfromtimestamp(cls, __t: float) -> Self: ... if sys.version_info >= (3, 8): @classmethod @@ -278,6 +279,7 @@ class datetime(date): def now(cls, tz: _TzInfo) -> datetime: ... @classmethod + @deprecated("Use timezone-aware objects to represent datetimes in UTC; e.g. by calling .now(datetime.UTC)") def utcnow(cls) -> Self: ... @classmethod def combine(cls, date: _Date, time: _Time, tzinfo: _TzInfo | None = ...) -> Self: ... diff --git a/stdlib/email/utils.pyi b/stdlib/email/utils.pyi index 186e768050be..0b62647532db 100644 --- a/stdlib/email/utils.pyi +++ b/stdlib/email/utils.pyi @@ -4,7 +4,7 @@ from _typeshed import Unused from email import _ParamType from email.charset import Charset from typing import overload -from typing_extensions import TypeAlias +from typing_extensions import TypeAlias, deprecated __all__ = [ "collapse_rfc2231_value", @@ -54,6 +54,10 @@ def formatdate(timeval: float | None = None, localtime: bool = False, usegmt: bo def format_datetime(dt: datetime.datetime, usegmt: bool = False) -> str: ... if sys.version_info >= (3, 12): + @overload + def localtime(dt: datetime.datetime | None = None) -> datetime.datetime: ... + @overload + @deprecated("The `isdst` parameter does nothing and will be removed in Python 3.14.") def localtime(dt: datetime.datetime | None = None, isdst: Unused = None) -> datetime.datetime: ... else: diff --git a/stdlib/os/__init__.pyi b/stdlib/os/__init__.pyi index 2810d086ae49..26fa6fb821d2 100644 --- a/stdlib/os/__init__.pyi +++ b/stdlib/os/__init__.pyi @@ -26,7 +26,7 @@ from contextlib import AbstractContextManager from io import BufferedRandom, BufferedReader, BufferedWriter, FileIO, TextIOWrapper as _TextIOWrapper from subprocess import Popen from typing import IO, Any, AnyStr, BinaryIO, Generic, NoReturn, Protocol, TypeVar, overload, runtime_checkable -from typing_extensions import Final, Literal, Self, TypeAlias, final +from typing_extensions import Final, Literal, Self, TypeAlias, deprecated, final from . import path as _path @@ -346,8 +346,13 @@ class stat_result(structseq[float], tuple[int, int, int, int, int, int, int, flo @property def st_mtime(self) -> float: ... # time of most recent content modification, # platform dependent (time of most recent metadata change on Unix, or the time of creation on Windows) - @property - def st_ctime(self) -> float: ... + if sys.version_info >= (3, 12) and sys.platform == "win32": + @property + @deprecated("Use st_birthtime instead to retrieve the file creation time. In the future, this property will contain the last metadata change time.") + def st_ctime(self) -> float: ... + else: + @property + def st_ctime(self) -> float: ... @property def st_atime_ns(self) -> int: ... # time of most recent access, in nanoseconds @property diff --git a/stdlib/pkgutil.pyi b/stdlib/pkgutil.pyi index 59f1f734cf90..4a0c8d101b7a 100644 --- a/stdlib/pkgutil.pyi +++ b/stdlib/pkgutil.pyi @@ -3,6 +3,7 @@ from _typeshed import SupportsRead from collections.abc import Callable, Iterable, Iterator from importlib.abc import Loader, MetaPathFinder, PathEntryFinder from typing import IO, Any, NamedTuple, TypeVar +from typing_extensions import deprecated __all__ = [ "get_importer", @@ -35,8 +36,10 @@ if sys.version_info < (3, 12): class ImpLoader: def __init__(self, fullname: str, file: IO[str], filename: str, etc: tuple[str, str, int]) -> None: ... +@deprecated("Use importlib.util.find_spec() instead. Will be removed in Python 3.14.") def find_loader(fullname: str) -> Loader | None: ... def get_importer(path_item: str) -> PathEntryFinder | None: ... +@deprecated("Use importlib.util.find_spec() instead. Will be removed in Python 3.14.") def get_loader(module_or_name: str) -> Loader | None: ... def iter_importers(fullname: str = "") -> Iterator[MetaPathFinder | PathEntryFinder]: ... def iter_modules(path: Iterable[str] | None = None, prefix: str = "") -> Iterator[ModuleInfo]: ... diff --git a/stdlib/shutil.pyi b/stdlib/shutil.pyi index 38c50d51b129..196c5bba164e 100644 --- a/stdlib/shutil.pyi +++ b/stdlib/shutil.pyi @@ -4,7 +4,7 @@ from _typeshed import BytesPath, FileDescriptorOrPath, StrOrBytesPath, StrPath, from collections.abc import Callable, Iterable, Sequence from tarfile import _TarfileFilter from typing import Any, AnyStr, NamedTuple, Protocol, TypeVar, overload -from typing_extensions import TypeAlias +from typing_extensions import TypeAlias, deprecated __all__ = [ "copyfileobj", @@ -95,13 +95,21 @@ class _RmtreeType(Protocol): avoids_symlink_attacks: bool if sys.version_info >= (3, 12): @overload + def __call__( + self, + path: StrOrBytesPath, + ignore_errors: bool = False, + *, + dir_fd: int | None = None, + ) -> None: ... + @overload + @deprecated("The `onerror` parameter is deprecated and will be removed in Python 3.14. Use `onexc` instead.") def __call__( self, path: StrOrBytesPath, ignore_errors: bool = False, onerror: _OnErrorCallback | None = None, *, - onexc: None = None, dir_fd: int | None = None, ) -> None: ... @overload @@ -109,7 +117,6 @@ class _RmtreeType(Protocol): self, path: StrOrBytesPath, ignore_errors: bool = False, - onerror: None = None, *, onexc: _OnExcCallback, dir_fd: int | None = None, diff --git a/stdlib/tarfile.pyi b/stdlib/tarfile.pyi index d9d9641ac698..8e6876fd9a38 100644 --- a/stdlib/tarfile.pyi +++ b/stdlib/tarfile.pyi @@ -7,7 +7,7 @@ from collections.abc import Callable, Iterable, Iterator, Mapping from gzip import _ReadableFileobj as _GzipReadableFileobj, _WritableFileobj as _GzipWritableFileobj from types import TracebackType from typing import IO, ClassVar, Protocol, overload -from typing_extensions import Literal, Self, TypeAlias +from typing_extensions import Literal, Self, TypeAlias, deprecated __all__ = [ "TarFile", @@ -292,14 +292,37 @@ class TarFile: def list(self, verbose: bool = True, *, members: _list[TarInfo] | None = None) -> None: ... def next(self) -> TarInfo | None: ... if sys.version_info >= (3, 8): + @overload + @deprecated("Extracting tar archives without specifying `filter` is deprecated until Python 3.14, when 'data' filter will become the default.") def extractall( self, path: StrOrBytesPath = ".", members: Iterable[TarInfo] | None = None, *, numeric_owner: bool = False, - filter: _TarfileFilter | None = ..., + filter: None = ..., ) -> None: ... + @overload + def extractall( + self, + path: StrOrBytesPath = ".", + members: Iterable[TarInfo] | None = None, + *, + numeric_owner: bool = False, + filter: _TarfileFilter + ) -> None: ... + @overload + @deprecated("Extracting tar archives without specifying `filter` is deprecated until Python 3.14, when 'data' filter will become the default.") + def extract( + self, + member: str | TarInfo, + path: StrOrBytesPath = "", + set_attrs: bool = True, + *, + numeric_owner: bool = False, + filter: None = ..., + ) -> None: ... + @overload def extract( self, member: str | TarInfo, @@ -307,7 +330,7 @@ class TarFile: set_attrs: bool = True, *, numeric_owner: bool = False, - filter: _TarfileFilter | None = ..., + filter: _TarfileFilter, ) -> None: ... else: def extractall( diff --git a/stdlib/types.pyi b/stdlib/types.pyi index fcaf5264c5e3..1f740d9b9675 100644 --- a/stdlib/types.pyi +++ b/stdlib/types.pyi @@ -17,7 +17,7 @@ from importlib.machinery import ModuleSpec # pytype crashes if types.MappingProxyType inherits from collections.abc.Mapping instead of typing.Mapping from typing import Any, ClassVar, Mapping, Protocol, TypeVar, overload # noqa: Y022 -from typing_extensions import Literal, ParamSpec, Self, TypeVarTuple, final +from typing_extensions import Literal, ParamSpec, Self, TypeVarTuple, deprecated, final __all__ = [ "FunctionType", @@ -144,8 +144,13 @@ class CodeType: def co_name(self) -> str: ... @property def co_firstlineno(self) -> int: ... - @property - def co_lnotab(self) -> bytes: ... + if sys.version_info >= (3, 10): + @property + @deprecated("Will be removed in Python 3.14. Use the co_lines() method instead.") + def co_lnotab(self) -> bytes: ... + else: + @property + def co_lnotab(self) -> bytes: ... @property def co_freevars(self) -> tuple[str, ...]: ... @property diff --git a/stdlib/xml/etree/ElementTree.pyi b/stdlib/xml/etree/ElementTree.pyi index b08ca88e7e97..9dfef30b6606 100644 --- a/stdlib/xml/etree/ElementTree.pyi +++ b/stdlib/xml/etree/ElementTree.pyi @@ -3,7 +3,7 @@ from _collections_abc import dict_keys from _typeshed import FileDescriptorOrPath, ReadableBuffer, SupportsRead, SupportsWrite from collections.abc import Callable, Generator, ItemsView, Iterable, Iterator, Mapping, Sequence from typing import Any, TypeVar, overload -from typing_extensions import Literal, SupportsIndex, TypeAlias, TypeGuard +from typing_extensions import Literal, SupportsIndex, TypeAlias, TypeGuard, deprecated __all__ = [ "Comment", @@ -124,6 +124,8 @@ class Element: def __setitem__(self, __key: SupportsIndex, __value: Element) -> None: ... @overload def __setitem__(self, __key: slice, __value: Iterable[Element]) -> None: ... + @deprecated("Testing an element's truth value is deprecated.") + def __bool__(self) -> bool: ... if sys.version_info < (3, 9): def getchildren(self) -> list[Element]: ... def getiterator(self, tag: str | None = None) -> list[Element]: ... From 60119d659c1a3f0c8e0f98523d7502ad1f8bdf5a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 10 Nov 2023 03:12:05 +0000 Subject: [PATCH 2/8] [pre-commit.ci] auto fixes from pre-commit.com hooks --- stdlib/os/__init__.pyi | 5 ++++- stdlib/shutil.pyi | 15 ++------------- stdlib/tarfile.pyi | 10 +++++++--- stdlib/types.pyi | 1 + 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/stdlib/os/__init__.pyi b/stdlib/os/__init__.pyi index 26fa6fb821d2..59bb3df5b09c 100644 --- a/stdlib/os/__init__.pyi +++ b/stdlib/os/__init__.pyi @@ -348,11 +348,14 @@ class stat_result(structseq[float], tuple[int, int, int, int, int, int, int, flo # platform dependent (time of most recent metadata change on Unix, or the time of creation on Windows) if sys.version_info >= (3, 12) and sys.platform == "win32": @property - @deprecated("Use st_birthtime instead to retrieve the file creation time. In the future, this property will contain the last metadata change time.") + @deprecated( + "Use st_birthtime instead to retrieve the file creation time. In the future, this property will contain the last metadata change time." + ) def st_ctime(self) -> float: ... else: @property def st_ctime(self) -> float: ... + @property def st_atime_ns(self) -> int: ... # time of most recent access, in nanoseconds @property diff --git a/stdlib/shutil.pyi b/stdlib/shutil.pyi index 196c5bba164e..ceab295a1c72 100644 --- a/stdlib/shutil.pyi +++ b/stdlib/shutil.pyi @@ -95,13 +95,7 @@ class _RmtreeType(Protocol): avoids_symlink_attacks: bool if sys.version_info >= (3, 12): @overload - def __call__( - self, - path: StrOrBytesPath, - ignore_errors: bool = False, - *, - dir_fd: int | None = None, - ) -> None: ... + def __call__(self, path: StrOrBytesPath, ignore_errors: bool = False, *, dir_fd: int | None = None) -> None: ... @overload @deprecated("The `onerror` parameter is deprecated and will be removed in Python 3.14. Use `onexc` instead.") def __call__( @@ -114,12 +108,7 @@ class _RmtreeType(Protocol): ) -> None: ... @overload def __call__( - self, - path: StrOrBytesPath, - ignore_errors: bool = False, - *, - onexc: _OnExcCallback, - dir_fd: int | None = None, + self, path: StrOrBytesPath, ignore_errors: bool = False, *, onexc: _OnExcCallback, dir_fd: int | None = None ) -> None: ... elif sys.version_info >= (3, 11): def __call__( diff --git a/stdlib/tarfile.pyi b/stdlib/tarfile.pyi index 8e6876fd9a38..671c2f0e0ede 100644 --- a/stdlib/tarfile.pyi +++ b/stdlib/tarfile.pyi @@ -293,7 +293,9 @@ class TarFile: def next(self) -> TarInfo | None: ... if sys.version_info >= (3, 8): @overload - @deprecated("Extracting tar archives without specifying `filter` is deprecated until Python 3.14, when 'data' filter will become the default.") + @deprecated( + "Extracting tar archives without specifying `filter` is deprecated until Python 3.14, when 'data' filter will become the default." + ) def extractall( self, path: StrOrBytesPath = ".", @@ -309,10 +311,12 @@ class TarFile: members: Iterable[TarInfo] | None = None, *, numeric_owner: bool = False, - filter: _TarfileFilter + filter: _TarfileFilter, ) -> None: ... @overload - @deprecated("Extracting tar archives without specifying `filter` is deprecated until Python 3.14, when 'data' filter will become the default.") + @deprecated( + "Extracting tar archives without specifying `filter` is deprecated until Python 3.14, when 'data' filter will become the default." + ) def extract( self, member: str | TarInfo, diff --git a/stdlib/types.pyi b/stdlib/types.pyi index 1f740d9b9675..d66e9d0416b7 100644 --- a/stdlib/types.pyi +++ b/stdlib/types.pyi @@ -151,6 +151,7 @@ class CodeType: else: @property def co_lnotab(self) -> bytes: ... + @property def co_freevars(self) -> tuple[str, ...]: ... @property From c23c8766d195d9bb13572e437b28622780b306a9 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sat, 18 Nov 2023 12:12:54 -0800 Subject: [PATCH 3/8] Make asyncio deprecation conditional --- stdlib/asyncio/events.pyi | 33 ++++++--- stdlib/asyncio/unix_events.pyi | 118 ++++++++++++++++++++++++--------- 2 files changed, 108 insertions(+), 43 deletions(-) diff --git a/stdlib/asyncio/events.pyi b/stdlib/asyncio/events.pyi index 41bb63b32a67..7c44d96855d5 100644 --- a/stdlib/asyncio/events.pyi +++ b/stdlib/asyncio/events.pyi @@ -598,12 +598,18 @@ class AbstractEventLoopPolicy: @abstractmethod def new_event_loop(self) -> AbstractEventLoop: ... # Child processes handling (Unix only). - @abstractmethod - @deprecated("Deprecated as of Python 3.12; will be removed in Python 3.14") - def get_child_watcher(self) -> AbstractChildWatcher: ... - @abstractmethod - @deprecated("Deprecated as of Python 3.12; will be removed in Python 3.14") - def set_child_watcher(self, watcher: AbstractChildWatcher) -> None: ... + if sys.version_info >= (3, 12): + @abstractmethod + @deprecated("Deprecated as of Python 3.12; will be removed in Python 3.14") + def get_child_watcher(self) -> AbstractChildWatcher: ... + @abstractmethod + @deprecated("Deprecated as of Python 3.12; will be removed in Python 3.14") + def set_child_watcher(self, watcher: AbstractChildWatcher) -> None: ... + else: + @abstractmethod + def get_child_watcher(self) -> AbstractChildWatcher: ... + @abstractmethod + def set_child_watcher(self, watcher: AbstractChildWatcher) -> None: ... class BaseDefaultEventLoopPolicy(AbstractEventLoopPolicy, metaclass=ABCMeta): def get_event_loop(self) -> AbstractEventLoop: ... @@ -615,10 +621,17 @@ def set_event_loop_policy(policy: AbstractEventLoopPolicy | None) -> None: ... def get_event_loop() -> AbstractEventLoop: ... def set_event_loop(loop: AbstractEventLoop | None) -> None: ... def new_event_loop() -> AbstractEventLoop: ... -@deprecated("Deprecated as of Python 3.12; will be removed in Python 3.14") -def get_child_watcher() -> AbstractChildWatcher: ... -@deprecated("Deprecated as of Python 3.12; will be removed in Python 3.14") -def set_child_watcher(watcher: AbstractChildWatcher) -> None: ... + +if sys.version_info >= (3, 12): + @deprecated("Deprecated as of Python 3.12; will be removed in Python 3.14") + def get_child_watcher() -> AbstractChildWatcher: ... + @deprecated("Deprecated as of Python 3.12; will be removed in Python 3.14") + def set_child_watcher(watcher: AbstractChildWatcher) -> None: ... + +else: + def get_child_watcher() -> AbstractChildWatcher: ... + def set_child_watcher(watcher: AbstractChildWatcher) -> None: ... + def _set_running_loop(__loop: AbstractEventLoop | None) -> None: ... def _get_running_loop() -> AbstractEventLoop: ... def get_running_loop() -> AbstractEventLoop: ... diff --git a/stdlib/asyncio/unix_events.pyi b/stdlib/asyncio/unix_events.pyi index 792566c9bd21..d440206aa0b9 100644 --- a/stdlib/asyncio/unix_events.pyi +++ b/stdlib/asyncio/unix_events.pyi @@ -11,23 +11,46 @@ from .selector_events import BaseSelectorEventLoop # This is also technically not available on Win, # but other parts of typeshed need this definition. # So, it is special cased. -@deprecated("Deprecated as of Python 3.12; will be removed in Python 3.14") -class AbstractChildWatcher: - @abstractmethod - def add_child_handler(self, pid: int, callback: Callable[..., object], *args: Any) -> None: ... - @abstractmethod - def remove_child_handler(self, pid: int) -> bool: ... - @abstractmethod - def attach_loop(self, loop: AbstractEventLoop | None) -> None: ... - @abstractmethod - def close(self) -> None: ... - @abstractmethod - def __enter__(self) -> Self: ... - @abstractmethod - def __exit__(self, typ: type[BaseException] | None, exc: BaseException | None, tb: types.TracebackType | None) -> None: ... - if sys.version_info >= (3, 8): +if sys.version_info >= (3, 12): + @deprecated("Deprecated as of Python 3.12; will be removed in Python 3.14") + class AbstractChildWatcher: + @abstractmethod + def add_child_handler(self, pid: int, callback: Callable[..., object], *args: Any) -> None: ... + @abstractmethod + def remove_child_handler(self, pid: int) -> bool: ... + @abstractmethod + def attach_loop(self, loop: AbstractEventLoop | None) -> None: ... + @abstractmethod + def close(self) -> None: ... + @abstractmethod + def __enter__(self) -> Self: ... + @abstractmethod + def __exit__( + self, typ: type[BaseException] | None, exc: BaseException | None, tb: types.TracebackType | None + ) -> None: ... + if sys.version_info >= (3, 8): + @abstractmethod + def is_active(self) -> bool: ... + +else: + class AbstractChildWatcher: + @abstractmethod + def add_child_handler(self, pid: int, callback: Callable[..., object], *args: Any) -> None: ... + @abstractmethod + def remove_child_handler(self, pid: int) -> bool: ... + @abstractmethod + def attach_loop(self, loop: AbstractEventLoop | None) -> None: ... + @abstractmethod + def close(self) -> None: ... + @abstractmethod + def __enter__(self) -> Self: ... @abstractmethod - def is_active(self) -> bool: ... + def __exit__( + self, typ: type[BaseException] | None, exc: BaseException | None, tb: types.TracebackType | None + ) -> None: ... + if sys.version_info >= (3, 8): + @abstractmethod + def is_active(self) -> bool: ... if sys.platform != "win32": if sys.version_info >= (3, 9): @@ -63,32 +86,49 @@ if sys.platform != "win32": def attach_loop(self, loop: AbstractEventLoop | None) -> None: ... - @deprecated("Deprecated as of Python 3.12; will be removed in Python 3.14") - class SafeChildWatcher(BaseChildWatcher): - def __enter__(self) -> Self: ... - def __exit__(self, a: type[BaseException] | None, b: BaseException | None, c: types.TracebackType | None) -> None: ... - def add_child_handler(self, pid: int, callback: Callable[..., object], *args: Any) -> None: ... - def remove_child_handler(self, pid: int) -> bool: ... + if sys.version_info >= (3, 12): + @deprecated("Deprecated as of Python 3.12; will be removed in Python 3.14") + class SafeChildWatcher(BaseChildWatcher): + def __enter__(self) -> Self: ... + def __exit__(self, a: type[BaseException] | None, b: BaseException | None, c: types.TracebackType | None) -> None: ... + def add_child_handler(self, pid: int, callback: Callable[..., object], *args: Any) -> None: ... + def remove_child_handler(self, pid: int) -> bool: ... - @deprecated("Deprecated as of Python 3.12; will be removed in Python 3.14") - class FastChildWatcher(BaseChildWatcher): - def __enter__(self) -> Self: ... - def __exit__(self, a: type[BaseException] | None, b: BaseException | None, c: types.TracebackType | None) -> None: ... - def add_child_handler(self, pid: int, callback: Callable[..., object], *args: Any) -> None: ... - def remove_child_handler(self, pid: int) -> bool: ... + @deprecated("Deprecated as of Python 3.12; will be removed in Python 3.14") + class FastChildWatcher(BaseChildWatcher): + def __enter__(self) -> Self: ... + def __exit__(self, a: type[BaseException] | None, b: BaseException | None, c: types.TracebackType | None) -> None: ... + def add_child_handler(self, pid: int, callback: Callable[..., object], *args: Any) -> None: ... + def remove_child_handler(self, pid: int) -> bool: ... + else: + class SafeChildWatcher(BaseChildWatcher): + def __enter__(self) -> Self: ... + def __exit__(self, a: type[BaseException] | None, b: BaseException | None, c: types.TracebackType | None) -> None: ... + def add_child_handler(self, pid: int, callback: Callable[..., object], *args: Any) -> None: ... + def remove_child_handler(self, pid: int) -> bool: ... + + class FastChildWatcher(BaseChildWatcher): + def __enter__(self) -> Self: ... + def __exit__(self, a: type[BaseException] | None, b: BaseException | None, c: types.TracebackType | None) -> None: ... + def add_child_handler(self, pid: int, callback: Callable[..., object], *args: Any) -> None: ... + def remove_child_handler(self, pid: int) -> bool: ... class _UnixSelectorEventLoop(BaseSelectorEventLoop): ... class _UnixDefaultEventLoopPolicy(BaseDefaultEventLoopPolicy): - @deprecated("Deprecated as of Python 3.12; will be removed in Python 3.14") - def get_child_watcher(self) -> AbstractChildWatcher: ... - @deprecated("Deprecated as of Python 3.12; will be removed in Python 3.14") - def set_child_watcher(self, watcher: AbstractChildWatcher | None) -> None: ... + if sys.version_info >= (3, 12): + @deprecated("Deprecated as of Python 3.12; will be removed in Python 3.14") + def get_child_watcher(self) -> AbstractChildWatcher: ... + @deprecated("Deprecated as of Python 3.12; will be removed in Python 3.14") + def set_child_watcher(self, watcher: AbstractChildWatcher | None) -> None: ... + else: + def get_child_watcher(self) -> AbstractChildWatcher: ... + def set_child_watcher(self, watcher: AbstractChildWatcher | None) -> None: ... SelectorEventLoop = _UnixSelectorEventLoop DefaultEventLoopPolicy = _UnixDefaultEventLoopPolicy - if sys.version_info >= (3, 8): + if sys.version_info >= (3, 12): @deprecated("Deprecated as of Python 3.12; will be removed in Python 3.14") class MultiLoopChildWatcher(AbstractChildWatcher): def is_active(self) -> bool: ... @@ -100,7 +140,19 @@ if sys.platform != "win32": def add_child_handler(self, pid: int, callback: Callable[..., object], *args: Any) -> None: ... def remove_child_handler(self, pid: int) -> bool: ... def attach_loop(self, loop: AbstractEventLoop | None) -> None: ... + elif sys.version_info >= (3, 8): + class MultiLoopChildWatcher(AbstractChildWatcher): + def is_active(self) -> bool: ... + def close(self) -> None: ... + def __enter__(self) -> Self: ... + def __exit__( + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: types.TracebackType | None + ) -> None: ... + def add_child_handler(self, pid: int, callback: Callable[..., object], *args: Any) -> None: ... + def remove_child_handler(self, pid: int) -> bool: ... + def attach_loop(self, loop: AbstractEventLoop | None) -> None: ... + if sys.version_info >= (3, 8): class ThreadedChildWatcher(AbstractChildWatcher): def is_active(self) -> Literal[True]: ... def close(self) -> None: ... From 367104a3eedf3fb674dea89a1ff83eedad2b4fc6 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sat, 18 Nov 2023 12:22:19 -0800 Subject: [PATCH 4/8] drop deprecated @property --- stdlib/types.pyi | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/stdlib/types.pyi b/stdlib/types.pyi index d66e9d0416b7..b6d952e70a3b 100644 --- a/stdlib/types.pyi +++ b/stdlib/types.pyi @@ -17,7 +17,7 @@ from importlib.machinery import ModuleSpec # pytype crashes if types.MappingProxyType inherits from collections.abc.Mapping instead of typing.Mapping from typing import Any, ClassVar, Mapping, Protocol, TypeVar, overload # noqa: Y022 -from typing_extensions import Literal, ParamSpec, Self, TypeVarTuple, deprecated, final +from typing_extensions import Literal, ParamSpec, Self, TypeVarTuple, final __all__ = [ "FunctionType", @@ -146,7 +146,8 @@ class CodeType: def co_firstlineno(self) -> int: ... if sys.version_info >= (3, 10): @property - @deprecated("Will be removed in Python 3.14. Use the co_lines() method instead.") + # TODO: wait for https://github.com/google/pytype/issues/1531 + # @deprecated("Will be removed in Python 3.14. Use the co_lines() method instead.") def co_lnotab(self) -> bytes: ... else: @property From c313169065cc32439dc0255859a75024e43516a7 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sat, 18 Nov 2023 12:41:57 -0800 Subject: [PATCH 5/8] Undo argparse to see if pytype becomes happier --- stdlib/argparse.pyi | 30 +++--------------------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/stdlib/argparse.pyi b/stdlib/argparse.pyi index dca363f66b6b..e947f67edd55 100644 --- a/stdlib/argparse.pyi +++ b/stdlib/argparse.pyi @@ -3,7 +3,7 @@ from _typeshed import sentinel from collections.abc import Callable, Generator, Iterable, Sequence from re import Pattern from typing import IO, Any, Generic, NewType, NoReturn, Protocol, TypeVar, overload -from typing_extensions import Literal, Self, TypeAlias, deprecated +from typing_extensions import Literal, Self, TypeAlias __all__ = [ "ArgumentParser", @@ -337,23 +337,11 @@ class Action(_AttributeHolder): if sys.version_info >= (3, 12): class BooleanOptionalAction(Action): - @overload def __init__( self, option_strings: Sequence[str], dest: str, - default: bool | None = None, - *, - required: bool = False, - help: str | None = None, - ) -> None: ... - @overload - @deprecated("The `type`, `choices`, and `metavar` parameters are ignored and will be removed in Python 3.14.") - def __init__( - self, - option_strings: Sequence[str], - dest: str, - default: _T | bool | None = None, + default: _T | str | None = None, type: Callable[[str], _T] | FileType | None = sentinel, choices: Iterable[_T] | None = sentinel, required: bool = False, @@ -363,23 +351,11 @@ if sys.version_info >= (3, 12): elif sys.version_info >= (3, 9): class BooleanOptionalAction(Action): - @overload - def __init__( - self, - option_strings: Sequence[str], - dest: str, - default: bool | None = None, - *, - required: bool = False, - help: str | None = None, - ) -> None: ... - @overload - @deprecated("The `type`, `choices`, and `metavar` parameters are ignored and will be removed in Python 3.14.") def __init__( self, option_strings: Sequence[str], dest: str, - default: _T | bool | None = None, + default: _T | str | None = None, type: Callable[[str], _T] | FileType | None = None, choices: Iterable[_T] | None = None, required: bool = False, From 25cf5a71ba26aa8aa40e6a9f17ac999c22c2dd26 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sat, 18 Nov 2023 12:50:07 -0800 Subject: [PATCH 6/8] Revert "Undo argparse to see if pytype becomes happier" This reverts commit c313169065cc32439dc0255859a75024e43516a7. --- stdlib/argparse.pyi | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/stdlib/argparse.pyi b/stdlib/argparse.pyi index e947f67edd55..dca363f66b6b 100644 --- a/stdlib/argparse.pyi +++ b/stdlib/argparse.pyi @@ -3,7 +3,7 @@ from _typeshed import sentinel from collections.abc import Callable, Generator, Iterable, Sequence from re import Pattern from typing import IO, Any, Generic, NewType, NoReturn, Protocol, TypeVar, overload -from typing_extensions import Literal, Self, TypeAlias +from typing_extensions import Literal, Self, TypeAlias, deprecated __all__ = [ "ArgumentParser", @@ -337,11 +337,23 @@ class Action(_AttributeHolder): if sys.version_info >= (3, 12): class BooleanOptionalAction(Action): + @overload def __init__( self, option_strings: Sequence[str], dest: str, - default: _T | str | None = None, + default: bool | None = None, + *, + required: bool = False, + help: str | None = None, + ) -> None: ... + @overload + @deprecated("The `type`, `choices`, and `metavar` parameters are ignored and will be removed in Python 3.14.") + def __init__( + self, + option_strings: Sequence[str], + dest: str, + default: _T | bool | None = None, type: Callable[[str], _T] | FileType | None = sentinel, choices: Iterable[_T] | None = sentinel, required: bool = False, @@ -351,11 +363,23 @@ if sys.version_info >= (3, 12): elif sys.version_info >= (3, 9): class BooleanOptionalAction(Action): + @overload + def __init__( + self, + option_strings: Sequence[str], + dest: str, + default: bool | None = None, + *, + required: bool = False, + help: str | None = None, + ) -> None: ... + @overload + @deprecated("The `type`, `choices`, and `metavar` parameters are ignored and will be removed in Python 3.14.") def __init__( self, option_strings: Sequence[str], dest: str, - default: _T | str | None = None, + default: _T | bool | None = None, type: Callable[[str], _T] | FileType | None = None, choices: Iterable[_T] | None = None, required: bool = False, From c338052b17d4612d0e172ad5fb7b0cc041af2e68 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sat, 18 Nov 2023 12:50:13 -0800 Subject: [PATCH 7/8] Revert "drop deprecated @property" This reverts commit 367104a3eedf3fb674dea89a1ff83eedad2b4fc6. --- stdlib/types.pyi | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/stdlib/types.pyi b/stdlib/types.pyi index b6d952e70a3b..d66e9d0416b7 100644 --- a/stdlib/types.pyi +++ b/stdlib/types.pyi @@ -17,7 +17,7 @@ from importlib.machinery import ModuleSpec # pytype crashes if types.MappingProxyType inherits from collections.abc.Mapping instead of typing.Mapping from typing import Any, ClassVar, Mapping, Protocol, TypeVar, overload # noqa: Y022 -from typing_extensions import Literal, ParamSpec, Self, TypeVarTuple, final +from typing_extensions import Literal, ParamSpec, Self, TypeVarTuple, deprecated, final __all__ = [ "FunctionType", @@ -146,8 +146,7 @@ class CodeType: def co_firstlineno(self) -> int: ... if sys.version_info >= (3, 10): @property - # TODO: wait for https://github.com/google/pytype/issues/1531 - # @deprecated("Will be removed in Python 3.14. Use the co_lines() method instead.") + @deprecated("Will be removed in Python 3.14. Use the co_lines() method instead.") def co_lnotab(self) -> bytes: ... else: @property From 62853a8d1773a277d47624aa424d414e2b029bb2 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sun, 18 Feb 2024 06:42:49 -0800 Subject: [PATCH 8/8] Appease stubtest --- stdlib/xml/etree/ElementTree.pyi | 2 ++ tests/stubtest_allowlists/py310.txt | 3 +++ tests/stubtest_allowlists/py311.txt | 3 +++ tests/stubtest_allowlists/py38.txt | 3 +++ tests/stubtest_allowlists/py39.txt | 3 +++ 5 files changed, 14 insertions(+) diff --git a/stdlib/xml/etree/ElementTree.pyi b/stdlib/xml/etree/ElementTree.pyi index f5400ab42e59..2a363a504dec 100644 --- a/stdlib/xml/etree/ElementTree.pyi +++ b/stdlib/xml/etree/ElementTree.pyi @@ -121,6 +121,8 @@ class Element: def __setitem__(self, __key: SupportsIndex, __value: Element) -> None: ... @overload def __setitem__(self, __key: slice, __value: Iterable[Element]) -> None: ... + + # Doesn't really exist in earlier versions, where __len__ is called implicitly instead @deprecated("Testing an element's truth value is deprecated.") def __bool__(self) -> bool: ... if sys.version_info < (3, 9): diff --git a/tests/stubtest_allowlists/py310.txt b/tests/stubtest_allowlists/py310.txt index 6dd753a7d3bd..0b0c4bb6cba4 100644 --- a/tests/stubtest_allowlists/py310.txt +++ b/tests/stubtest_allowlists/py310.txt @@ -25,6 +25,9 @@ typing._SpecialForm.__mro_entries__ weakref.ProxyType.__reversed__ # Doesn't really exist builtins.ellipsis # type is not exposed anywhere +xml.etree.ElementTree.Element.__bool__ # Doesn't really exist; see comments in stub +xml.etree.cElementTree.Element.__bool__ # Doesn't really exist; see comments in stub + # Runtime definition of protocol is incorrect importlib.metadata._meta.SimplePath.__truediv__ importlib.metadata._meta.SimplePath.joinpath diff --git a/tests/stubtest_allowlists/py311.txt b/tests/stubtest_allowlists/py311.txt index 79d46d642641..46dd1b781f95 100644 --- a/tests/stubtest_allowlists/py311.txt +++ b/tests/stubtest_allowlists/py311.txt @@ -18,6 +18,9 @@ tkinter._VersionInfoType.__doc__ typing.NewType.__mro_entries__ builtins.ellipsis # type is not exposed anywhere +xml.etree.ElementTree.Element.__bool__ # Doesn't really exist; see comments in stub +xml.etree.cElementTree.Element.__bool__ # Doesn't really exist; see comments in stub + # Runtime definition of protocol is incorrect importlib.metadata._meta.SimplePath.__truediv__ importlib.metadata._meta.SimplePath.joinpath diff --git a/tests/stubtest_allowlists/py38.txt b/tests/stubtest_allowlists/py38.txt index 066af3848240..5b8a245bdf89 100644 --- a/tests/stubtest_allowlists/py38.txt +++ b/tests/stubtest_allowlists/py38.txt @@ -52,6 +52,9 @@ xml.etree.ElementTree.TreeBuilder.start # Discrepancy between Python and C modu xml.etree.cElementTree.TreeBuilder.start # bpo-39495 xxsubtype # module missing from the stubs +xml.etree.ElementTree.Element.__bool__ # Doesn't really exist; see comments in stub +xml.etree.cElementTree.Element.__bool__ # Doesn't really exist; see comments in stub + # Exist at runtime for internal reasons, no need to put them in the stub typing_extensions\.TypeAliasType\.__call__ typing_extensions\.TypeAliasType\.__init_subclass__ diff --git a/tests/stubtest_allowlists/py39.txt b/tests/stubtest_allowlists/py39.txt index 2d1e93e5695b..115a13921512 100644 --- a/tests/stubtest_allowlists/py39.txt +++ b/tests/stubtest_allowlists/py39.txt @@ -39,6 +39,9 @@ types.GenericAlias.__call__ # Would be complicated to fix properly, Any could s weakref.ProxyType.__reversed__ # Doesn't really exist xxsubtype # module missing from the stubs +xml.etree.ElementTree.Element.__bool__ # Doesn't really exist; see comments in stub +xml.etree.cElementTree.Element.__bool__ # Doesn't really exist; see comments in stub + # Exist at runtime for internal reasons, no need to put them in the stub typing_extensions\.TypeAliasType\.__call__ typing_extensions\.TypeAliasType\.__init_subclass__