Skip to content
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

stdlib: more deprecations #11009

Merged
merged 12 commits into from
Feb 18, 2024
30 changes: 27 additions & 3 deletions stdlib/argparse.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -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, Literal, NewType, NoReturn, Protocol, TypeVar, overload
from typing_extensions import Self, TypeAlias
from typing_extensions import Self, TypeAlias, deprecated

__all__ = [
"ArgumentParser",
Expand Down Expand Up @@ -339,11 +339,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,
Copy link
Member Author

Choose a reason for hiding this comment

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

It appears that a non-bool default doesn't really make sense on this action.

*,
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.")
Copy link
Member Author

Choose a reason for hiding this comment

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

These apparently never did anything useful, so it seems fair to emit the warning on all versions.

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,
Expand All @@ -353,11 +365,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,
Expand Down
16 changes: 12 additions & 4 deletions stdlib/asyncio/events.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -543,10 +543,18 @@ class AbstractEventLoopPolicy:
@abstractmethod
def new_event_loop(self) -> AbstractEventLoop: ...
# Child processes handling (Unix only).
@abstractmethod
def get_child_watcher(self) -> AbstractChildWatcher: ...
@abstractmethod
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: ...
Expand Down
4 changes: 3 additions & 1 deletion stdlib/datetime.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import sys
from abc import abstractmethod
from time import struct_time
from typing import ClassVar, Literal, NamedTuple, NoReturn, SupportsIndex, TypeVar, final, overload
from typing_extensions import Self, TypeAlias
from typing_extensions import Self, TypeAlias, deprecated

if sys.version_info >= (3, 11):
__all__ = ("date", "datetime", "time", "timedelta", "timezone", "tzinfo", "MINYEAR", "MAXYEAR", "UTC")
Expand Down Expand Up @@ -251,10 +251,12 @@ 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)")
Copy link
Member Author

Choose a reason for hiding this comment

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

This and utcnow() were always mildly discouraged and the replacement has always been available, so chose to deprecate across versions.

def utcfromtimestamp(cls, __t: float) -> Self: ...
@classmethod
def now(cls, tz: _TzInfo | None = None) -> Self: ...
@classmethod
@deprecated("Use timezone-aware objects to represent datetimes in UTC; e.g. by calling .now(datetime.UTC)")
Copy link
Member

Choose a reason for hiding this comment

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

Not sure about this one. It may have always been discouraged to use this method, but I think the deprecation has been pretty disruptive — see https://discuss.python.org/t/deprecating-utcnow-and-utcfromtimestamp/26221/12?u=alexwaygood. For Python 3.8 users, the method is still going to be around for a while; do we need to bother them with this warning just yet? (On the other hand: if the method is widely used, perhaps it's all the more important to make sure the word gets out that it's deprecated...)

Copy link
Collaborator

@hauntsaninja hauntsaninja Nov 10, 2023

Choose a reason for hiding this comment

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

I think it's worth it. Work had a bug just this week because someone was using these (and spoiler, we're not on 3.12).

Also I think it will be like eight years before CPython removes it, I'd definitely oppose removing it in 3.14

def utcnow(cls) -> Self: ...
@classmethod
def combine(cls, date: _Date, time: _Time, tzinfo: _TzInfo | None = ...) -> Self: ...
Expand Down
6 changes: 5 additions & 1 deletion stdlib/email/utils.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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.")
Copy link
Member Author

Choose a reason for hiding this comment

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

The isdst parameter did something before 3.12; didn't study the function enough to determine whether it did anything useful.

def localtime(dt: datetime.datetime | None = None, isdst: Unused = None) -> datetime.datetime: ...

else:
Expand Down
14 changes: 11 additions & 3 deletions stdlib/os/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ from typing import (
overload,
runtime_checkable,
)
from typing_extensions import Self, TypeAlias, Unpack
from typing_extensions import Self, TypeAlias, Unpack, deprecated

from . import path as _path

Expand Down Expand Up @@ -361,8 +361,16 @@ 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":
Copy link
Member Author

Choose a reason for hiding this comment

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

The replacement st_birthtime is only available on 3.12+, so it doesn't make sense to warn on earlier versions.

@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
Expand Down
14 changes: 5 additions & 9 deletions stdlib/shutil.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -78,24 +78,20 @@ 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.")
Copy link
Member Author

Choose a reason for hiding this comment

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

Since the new parameter is only available on 3.12+, applied the warning on 3.12+ only.

def __call__(
self,
path: StrOrBytesPath,
ignore_errors: bool = False,
onerror: _OnErrorCallback | None = None,
*,
onexc: None = None,
dir_fd: int | None = None,
) -> None: ...
@overload
def __call__(
self,
path: StrOrBytesPath,
ignore_errors: bool = False,
onerror: None = None,
*,
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__(
Expand Down
33 changes: 30 additions & 3 deletions stdlib/tarfile.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -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, Literal, Protocol, overload
from typing_extensions import Self, TypeAlias
from typing_extensions import Self, TypeAlias, deprecated

__all__ = [
"TarFile",
Expand Down Expand Up @@ -292,22 +292,49 @@ class TarFile:
def getnames(self) -> _list[str]: ...
def list(self, verbose: bool = True, *, members: _list[TarInfo] | None = None) -> None: ...
def next(self) -> TarInfo | None: ...
@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: None = ...,
) -> None: ...
@overload
def extractall(
self,
path: StrOrBytesPath = ".",
members: Iterable[TarInfo] | None = None,
*,
numeric_owner: bool = False,
filter: _TarfileFilter | None = ...,
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,
path: StrOrBytesPath = "",
set_attrs: bool = True,
*,
numeric_owner: bool = False,
filter: _TarfileFilter | None = ...,
filter: _TarfileFilter,
) -> None: ...
def _extract_member(
self, tarinfo: TarInfo, targetpath: str, set_attrs: bool = True, numeric_owner: bool = False
Expand Down
12 changes: 9 additions & 3 deletions stdlib/types.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -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, Literal, Mapping, Protocol, TypeVar, final, overload # noqa: Y022
from typing_extensions import ParamSpec, Self, TypeVarTuple
from typing_extensions import ParamSpec, Self, TypeVarTuple, deprecated

__all__ = [
"FunctionType",
Expand Down Expand Up @@ -138,8 +138,14 @@ 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.")
Copy link
Member Author

Choose a reason for hiding this comment

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

co_lines() is only in 3.10+.

def co_lnotab(self) -> bytes: ...
else:
@property
def co_lnotab(self) -> bytes: ...

@property
def co_freevars(self) -> tuple[str, ...]: ...
@property
Expand Down
6 changes: 5 additions & 1 deletion stdlib/xml/etree/ElementTree.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -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, Literal, SupportsIndex, TypeVar, overload
from typing_extensions import TypeAlias, TypeGuard
from typing_extensions import TypeAlias, TypeGuard, deprecated

__all__ = [
"C14NWriterTarget",
Expand Down Expand Up @@ -121,6 +121,10 @@ 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.")
Copy link
Member Author

Choose a reason for hiding this comment

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

This always behaved confusingly (and raised a FutureWarning under some circumstances), so seems fine to always warn.

def __bool__(self) -> bool: ...
if sys.version_info < (3, 9):
def getchildren(self) -> list[Element]: ...
def getiterator(self, tag: str | None = None) -> list[Element]: ...
Expand Down
3 changes: 3 additions & 0 deletions tests/stubtest_allowlists/py310.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions tests/stubtest_allowlists/py311.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions tests/stubtest_allowlists/py38.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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__
Expand Down
3 changes: 3 additions & 0 deletions tests/stubtest_allowlists/py39.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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__
Expand Down
Loading