From 4307c45ea6931abd66ab727edfb3af5ba6d07a2b Mon Sep 17 00:00:00 2001 From: Terji Petersen Date: Sat, 18 Feb 2023 19:22:44 +0000 Subject: [PATCH] TYP: Use Self instead of class-bound TypeVar in pyi files (remove Y019 ignore) --- environment.yml | 1 + pandas/_libs/sparse.pyi | 16 ++++----- pandas/_libs/tslibs/offsets.pyi | 21 ++++++----- pandas/_libs/tslibs/timedeltas.pyi | 11 +++--- pandas/_libs/tslibs/timestamps.pyi | 57 +++++++++++++----------------- pandas/_typing.py | 6 ++++ requirements-dev.txt | 1 + setup.cfg | 2 -- 8 files changed, 59 insertions(+), 56 deletions(-) diff --git a/environment.yml b/environment.yml index 04ded62262483..363f911d88f0a 100644 --- a/environment.yml +++ b/environment.yml @@ -117,3 +117,4 @@ dependencies: - pip: - sphinx-toggleprompt + - typing_extensions; python_version<"3.11" diff --git a/pandas/_libs/sparse.pyi b/pandas/_libs/sparse.pyi index 8c3989b818a71..9e5cecc61e5ca 100644 --- a/pandas/_libs/sparse.pyi +++ b/pandas/_libs/sparse.pyi @@ -1,13 +1,11 @@ -from typing import ( - Sequence, - TypeVar, -) +from typing import Sequence import numpy as np -from pandas._typing import npt - -_SparseIndexT = TypeVar("_SparseIndexT", bound=SparseIndex) +from pandas._typing import ( + Self, + npt, +) class SparseIndex: length: int @@ -24,8 +22,8 @@ class SparseIndex: def lookup_array(self, indexer: npt.NDArray[np.int32]) -> npt.NDArray[np.int32]: ... def to_int_index(self) -> IntIndex: ... def to_block_index(self) -> BlockIndex: ... - def intersect(self: _SparseIndexT, y_: SparseIndex) -> _SparseIndexT: ... - def make_union(self: _SparseIndexT, y_: SparseIndex) -> _SparseIndexT: ... + def intersect(self, y_: SparseIndex) -> Self: ... + def make_union(self, y_: SparseIndex) -> Self: ... class IntIndex(SparseIndex): indices: npt.NDArray[np.int32] diff --git a/pandas/_libs/tslibs/offsets.pyi b/pandas/_libs/tslibs/offsets.pyi index f1aca4717665c..c29a057e99ff5 100644 --- a/pandas/_libs/tslibs/offsets.pyi +++ b/pandas/_libs/tslibs/offsets.pyi @@ -13,7 +13,10 @@ from typing import ( import numpy as np from pandas._libs.tslibs.nattype import NaTType -from pandas._typing import npt +from pandas._typing import ( + Self, + npt, +) from .timedeltas import Timedelta @@ -39,7 +42,7 @@ class BaseOffset: @overload def __add__(self, other: npt.NDArray[np.object_]) -> npt.NDArray[np.object_]: ... @overload - def __add__(self: _BaseOffsetT, other: BaseOffset) -> _BaseOffsetT: ... + def __add__(self, other: BaseOffset) -> Self: ... @overload def __add__(self, other: _DatetimeT) -> _DatetimeT: ... @overload @@ -47,18 +50,18 @@ class BaseOffset: @overload def __radd__(self, other: npt.NDArray[np.object_]) -> npt.NDArray[np.object_]: ... @overload - def __radd__(self: _BaseOffsetT, other: BaseOffset) -> _BaseOffsetT: ... + def __radd__(self, other: BaseOffset) -> Self: ... @overload def __radd__(self, other: _DatetimeT) -> _DatetimeT: ... @overload def __radd__(self, other: _TimedeltaT) -> _TimedeltaT: ... @overload def __radd__(self, other: NaTType) -> NaTType: ... - def __sub__(self: _BaseOffsetT, other: BaseOffset) -> _BaseOffsetT: ... + def __sub__(self, other: BaseOffset) -> Self: ... @overload def __rsub__(self, other: npt.NDArray[np.object_]) -> npt.NDArray[np.object_]: ... @overload - def __rsub__(self: _BaseOffsetT, other: BaseOffset) -> _BaseOffsetT: ... + def __rsub__(self, other: BaseOffset): ... @overload def __rsub__(self, other: _DatetimeT) -> _DatetimeT: ... @overload @@ -66,13 +69,13 @@ class BaseOffset: @overload def __mul__(self, other: np.ndarray) -> np.ndarray: ... @overload - def __mul__(self: _BaseOffsetT, other: int) -> _BaseOffsetT: ... + def __mul__(self, other: int): ... @overload def __rmul__(self, other: np.ndarray) -> np.ndarray: ... @overload - def __rmul__(self: _BaseOffsetT, other: int) -> _BaseOffsetT: ... - def __neg__(self: _BaseOffsetT) -> _BaseOffsetT: ... - def copy(self: _BaseOffsetT) -> _BaseOffsetT: ... + def __rmul__(self, other: int) -> Self: ... + def __neg__(self) -> Self: ... + def copy(self) -> Self: ... @property def name(self) -> str: ... @property diff --git a/pandas/_libs/tslibs/timedeltas.pyi b/pandas/_libs/tslibs/timedeltas.pyi index d67a330e0b0c2..0d5afbfe963f1 100644 --- a/pandas/_libs/tslibs/timedeltas.pyi +++ b/pandas/_libs/tslibs/timedeltas.pyi @@ -12,7 +12,10 @@ from pandas._libs.tslibs import ( NaTType, Tick, ) -from pandas._typing import npt +from pandas._typing import ( + Self, + npt, +) # This should be kept consistent with the keys in the dict timedelta_abbrevs # in pandas/_libs/tslibs/timedeltas.pyx @@ -111,9 +114,9 @@ class Timedelta(timedelta): @property def asm8(self) -> np.timedelta64: ... # TODO: round/floor/ceil could return NaT? - def round(self: _S, freq: str) -> _S: ... - def floor(self: _S, freq: str) -> _S: ... - def ceil(self: _S, freq: str) -> _S: ... + def round(self, freq: str) -> Self: ... + def floor(self, freq: str) -> Self: ... + def ceil(self, freq: str) -> Self: ... @property def resolution_string(self) -> str: ... def __add__(self, other: timedelta) -> Timedelta: ... diff --git a/pandas/_libs/tslibs/timestamps.pyi b/pandas/_libs/tslibs/timestamps.pyi index 26b0c9170aaa0..d8112dbaf4b48 100644 --- a/pandas/_libs/tslibs/timestamps.pyi +++ b/pandas/_libs/tslibs/timestamps.pyi @@ -21,6 +21,7 @@ from pandas._libs.tslibs import ( Tick, Timedelta, ) +from pandas._typing import Self _DatetimeT = TypeVar("_DatetimeT", bound=datetime) @@ -80,30 +81,28 @@ class Timestamp(datetime): @property def fold(self) -> int: ... @classmethod - def fromtimestamp( - cls: type[_DatetimeT], ts: float, tz: _tzinfo | None = ... - ) -> _DatetimeT: ... + def fromtimestamp(cls, ts: float, tz: _tzinfo | None = ...) -> Self: ... @classmethod - def utcfromtimestamp(cls: type[_DatetimeT], ts: float) -> _DatetimeT: ... + def utcfromtimestamp(cls, ts: float) -> Self: ... @classmethod - def today(cls: type[_DatetimeT], tz: _tzinfo | str | None = ...) -> _DatetimeT: ... + def today(cls, tz: _tzinfo | str | None = ...) -> Self: ... @classmethod def fromordinal( - cls: type[_DatetimeT], + cls, ordinal: int, tz: _tzinfo | str | None = ..., - ) -> _DatetimeT: ... + ) -> Self: ... @classmethod - def now(cls: type[_DatetimeT], tz: _tzinfo | str | None = ...) -> _DatetimeT: ... + def now(cls, tz: _tzinfo | str | None = ...) -> Self: ... @classmethod - def utcnow(cls: type[_DatetimeT]) -> _DatetimeT: ... + def utcnow(cls) -> Self: ... # error: Signature of "combine" incompatible with supertype "datetime" @classmethod def combine( # type: ignore[override] cls, date: _date, time: _time ) -> datetime: ... @classmethod - def fromisoformat(cls: type[_DatetimeT], date_string: str) -> _DatetimeT: ... + def fromisoformat(cls, date_string: str) -> Self: ... def strftime(self, format: str) -> str: ... def __format__(self, fmt: str) -> str: ... def toordinal(self) -> int: ... @@ -116,7 +115,7 @@ class Timestamp(datetime): # LSP violation: nanosecond is not present in datetime.datetime.replace # and has positional args following it def replace( # type: ignore[override] - self: _DatetimeT, + self, year: int | None = ..., month: int | None = ..., day: int | None = ..., @@ -127,11 +126,9 @@ class Timestamp(datetime): nanosecond: int | None = ..., tzinfo: _tzinfo | type[object] | None = ..., fold: int | None = ..., - ) -> _DatetimeT: ... + ) -> Self: ... # LSP violation: datetime.datetime.astimezone has a default value for tz - def astimezone( # type: ignore[override] - self: _DatetimeT, tz: _tzinfo | None - ) -> _DatetimeT: ... + def astimezone(self, tz: _tzinfo | None) -> Self: ... # type: ignore[override] def ctime(self) -> str: ... def isoformat(self, sep: str = ..., timespec: str = ...) -> str: ... @classmethod @@ -147,16 +144,12 @@ class Timestamp(datetime): @overload # type: ignore[override] def __add__(self, other: np.ndarray) -> np.ndarray: ... @overload - def __add__( - self: _DatetimeT, other: timedelta | np.timedelta64 | Tick - ) -> _DatetimeT: ... - def __radd__(self: _DatetimeT, other: timedelta) -> _DatetimeT: ... + def __add__(self, other: timedelta | np.timedelta64 | Tick) -> Self: ... + def __radd__(self, other: timedelta) -> Self: ... @overload # type: ignore[override] def __sub__(self, other: datetime) -> Timedelta: ... @overload - def __sub__( - self: _DatetimeT, other: timedelta | np.timedelta64 | Tick - ) -> _DatetimeT: ... + def __sub__(self, other: timedelta | np.timedelta64 | Tick) -> Self: ... def __hash__(self) -> int: ... def weekday(self) -> int: ... def isoweekday(self) -> int: ... @@ -181,25 +174,25 @@ class Timestamp(datetime): def to_julian_date(self) -> np.float64: ... @property def asm8(self) -> np.datetime64: ... - def tz_convert(self: _DatetimeT, tz: _tzinfo | str | None) -> _DatetimeT: ... + def tz_convert(self, tz: _tzinfo | str | None) -> Self: ... # TODO: could return NaT? def tz_localize( - self: _DatetimeT, + self, tz: _tzinfo | str | None, ambiguous: str = ..., nonexistent: str = ..., - ) -> _DatetimeT: ... - def normalize(self: _DatetimeT) -> _DatetimeT: ... + ) -> Self: ... + def normalize(self) -> Self: ... # TODO: round/floor/ceil could return NaT? def round( - self: _DatetimeT, freq: str, ambiguous: bool | str = ..., nonexistent: str = ... - ) -> _DatetimeT: ... + self, freq: str, ambiguous: bool | str = ..., nonexistent: str = ... + ) -> Self: ... def floor( - self: _DatetimeT, freq: str, ambiguous: bool | str = ..., nonexistent: str = ... - ) -> _DatetimeT: ... + self, freq: str, ambiguous: bool | str = ..., nonexistent: str = ... + ) -> Self: ... def ceil( - self: _DatetimeT, freq: str, ambiguous: bool | str = ..., nonexistent: str = ... - ) -> _DatetimeT: ... + self, freq: str, ambiguous: bool | str = ..., nonexistent: str = ... + ) -> Self: ... def day_name(self, locale: str | None = ...) -> str: ... def month_name(self, locale: str | None = ...) -> str: ... @property diff --git a/pandas/_typing.py b/pandas/_typing.py index 87979aba9ada4..08c97baa31edd 100644 --- a/pandas/_typing.py +++ b/pandas/_typing.py @@ -6,6 +6,7 @@ tzinfo, ) from os import PathLike +import sys from typing import ( TYPE_CHECKING, Any, @@ -83,8 +84,13 @@ # Name "npt._ArrayLikeInt_co" is not defined [name-defined] NumpySorter = Optional[npt._ArrayLikeInt_co] # type: ignore[name-defined] + if sys.version_info >= (3, 11): + from typing import Self + else: + from typing_extensions import Self # pyright: reportUnusedImport = false else: npt: Any = None + Self: Any = None HashableT = TypeVar("HashableT", bound=Hashable) diff --git a/requirements-dev.txt b/requirements-dev.txt index 044052f4624f5..b18fbd3c4cec3 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -86,4 +86,5 @@ feedparser pyyaml requests sphinx-toggleprompt +typing_extensions; python_version<"3.11" setuptools>=61.0.0 diff --git a/setup.cfg b/setup.cfg index 88b61086e1e0f..ab46464bf1656 100644 --- a/setup.cfg +++ b/setup.cfg @@ -15,8 +15,6 @@ ignore = E731, # found modulo formatter (incorrect picks up mod operations) Y002, - # Use "_typeshed.Self" instead of class-bound TypeVar - Y019, # Docstrings should not be included in stubs Y021, # Use typing_extensions.TypeAlias for type aliases