diff --git a/docs/philosophy.md b/docs/philosophy.md index 853c516e1..f6650c4f9 100644 --- a/docs/philosophy.md +++ b/docs/philosophy.md @@ -36,6 +36,9 @@ This also allows type checking for operations on series that contain date/time d the following example that creates two series of datetimes with corresponding arithmetic. ```python +import pandas as pd +from typing import reveal_type + s1 = pd.Series(pd.to_datetime(["2022-05-01", "2022-06-01"])) reveal_type(s1) s2 = pd.Series(pd.to_datetime(["2022-05-15", "2022-06-15"])) @@ -43,22 +46,21 @@ reveal_type(s2) td = s1 - s2 reveal_type(td) ssum = s1 + s2 -reveal_type(ssum) ``` -The above code (without the `reveal_type()` statements) will raise an `Exception` on the computation of `ssum` because it is +The above code (without the `reveal_type()` statements) will get an error on the computation of `ssum` because it is inappropriate to add two series containing `Timestamp` values. The types will be -revealed as follows: +revealed by `mypy` as follows: ```text -ttest.py:4: note: Revealed type is "pandas.core.series.TimestampSeries" -ttest.py:6: note: Revealed type is "pandas.core.series.TimestampSeries" -ttest.py:8: note: Revealed type is "pandas.core.series.TimedeltaSeries" -ttest.py:10: note: Revealed type is "builtins.Exception" +ttest.py:5: note: Revealed type is "pandas.core.series.Series[pandas._libs.tslibs.timestamps.Timestamp]" +ttest.py:7: note: Revealed type is "pandas.core.series.Series[pandas._libs.tslibs.timestamps.Timestamp]" +ttest.py:9: note: Revealed type is "pandas.core.series.TimedeltaSeries" +ttest.py:10: error: Unsupported operand types for + ("Series[Timestamp]" and "Series[Timestamp]") [operator] ``` -The type `TimestampSeries` is the result of creating a series from `pd.to_datetime()`, while -the type `TimedeltaSeries` is the result of subtracting two `TimestampSeries` as well as +The type `Series[Timestamp]` is the result of creating a series from `pd.to_datetime()`, while +the type `TimedeltaSeries` is the result of subtracting two `Series[Timestamp]` as well as the result of `pd.to_timedelta()`. ### Interval is Generic diff --git a/pandas-stubs/_libs/interval.pyi b/pandas-stubs/_libs/interval.pyi index f22a12778..bdbac57ad 100644 --- a/pandas-stubs/_libs/interval.pyi +++ b/pandas-stubs/_libs/interval.pyi @@ -13,10 +13,7 @@ from pandas import ( Timedelta, Timestamp, ) -from pandas.core.series import ( - TimedeltaSeries, - TimestampSeries, -) +from pandas.core.series import TimedeltaSeries from pandas._typing import ( IntervalClosedType, @@ -176,7 +173,7 @@ class Interval(IntervalMixin, Generic[_OrderableT]): @overload def __gt__( self, - other: Series[int] | Series[float] | TimestampSeries | TimedeltaSeries, + other: Series[int] | Series[float] | Series[Timestamp] | TimedeltaSeries, ) -> Series[bool]: ... @overload def __lt__(self, other: Interval[_OrderableT]) -> bool: ... @@ -187,7 +184,7 @@ class Interval(IntervalMixin, Generic[_OrderableT]): @overload def __lt__( self, - other: Series[int] | Series[float] | TimestampSeries | TimedeltaSeries, + other: Series[int] | Series[float] | Series[Timestamp] | TimedeltaSeries, ) -> Series[bool]: ... @overload def __ge__(self, other: Interval[_OrderableT]) -> bool: ... @@ -198,7 +195,7 @@ class Interval(IntervalMixin, Generic[_OrderableT]): @overload def __ge__( self, - other: Series[int] | Series[float] | TimestampSeries | TimedeltaSeries, + other: Series[int] | Series[float] | Series[Timestamp] | TimedeltaSeries, ) -> Series[bool]: ... @overload def __le__(self, other: Interval[_OrderableT]) -> bool: ... diff --git a/pandas-stubs/_libs/tslibs/timedeltas.pyi b/pandas-stubs/_libs/tslibs/timedeltas.pyi index 54c0509ef..46ca89f48 100644 --- a/pandas-stubs/_libs/tslibs/timedeltas.pyi +++ b/pandas-stubs/_libs/tslibs/timedeltas.pyi @@ -17,10 +17,7 @@ from pandas import ( Series, TimedeltaIndex, ) -from pandas.core.series import ( - TimedeltaSeries, - TimestampSeries, -) +from pandas.core.series import TimedeltaSeries from typing_extensions import ( Self, TypeAlias, @@ -170,7 +167,7 @@ class Timedelta(timedelta): other: TimedeltaSeries, ) -> TimedeltaSeries: ... @overload - def __add__(self, other: TimestampSeries) -> TimestampSeries: ... + def __add__(self, other: Series[Timestamp]) -> Series[Timestamp]: ... @overload def __radd__(self, other: np.datetime64) -> Timestamp: ... @overload diff --git a/pandas-stubs/_libs/tslibs/timestamps.pyi b/pandas-stubs/_libs/tslibs/timestamps.pyi index 6146d0b36..9bd35199f 100644 --- a/pandas-stubs/_libs/tslibs/timestamps.pyi +++ b/pandas-stubs/_libs/tslibs/timestamps.pyi @@ -25,7 +25,6 @@ from pandas import ( from pandas.core.series import ( Series, TimedeltaSeries, - TimestampSeries, ) from typing_extensions import ( Never, @@ -187,7 +186,7 @@ class Timestamp(datetime, SupportsIndex): self, other: np_ndarray[ShapeT, np.datetime64] ) -> np_ndarray[ShapeT, np.bool]: ... @overload - def __le__(self, other: TimestampSeries) -> Series[bool]: ... + def __le__(self, other: Series[Timestamp]) -> Series[bool]: ... @overload # type: ignore[override] def __lt__(self, other: Timestamp | datetime | np.datetime64) -> bool: ... # type: ignore[misc] @overload @@ -197,7 +196,7 @@ class Timestamp(datetime, SupportsIndex): self, other: np_ndarray[ShapeT, np.datetime64] ) -> np_ndarray[ShapeT, np.bool]: ... @overload - def __lt__(self, other: TimestampSeries) -> Series[bool]: ... + def __lt__(self, other: Series[Timestamp]) -> Series[bool]: ... @overload # type: ignore[override] def __ge__(self, other: Timestamp | datetime | np.datetime64) -> bool: ... # type: ignore[misc] @overload @@ -207,7 +206,7 @@ class Timestamp(datetime, SupportsIndex): self, other: np_ndarray[ShapeT, np.datetime64] ) -> np_ndarray[ShapeT, np.bool]: ... @overload - def __ge__(self, other: TimestampSeries) -> Series[bool]: ... + def __ge__(self, other: Series[Timestamp]) -> Series[bool]: ... @overload # type: ignore[override] def __gt__(self, other: Timestamp | datetime | np.datetime64) -> bool: ... # type: ignore[misc] @overload @@ -217,7 +216,7 @@ class Timestamp(datetime, SupportsIndex): self, other: np_ndarray[ShapeT, np.datetime64] ) -> np_ndarray[ShapeT, np.bool]: ... @overload - def __gt__(self, other: TimestampSeries) -> Series[bool]: ... + def __gt__(self, other: Series[Timestamp]) -> Series[bool]: ... # error: Signature of "__add__" incompatible with supertype "date"/"datetime" @overload # type: ignore[override] def __add__( @@ -226,7 +225,7 @@ class Timestamp(datetime, SupportsIndex): @overload def __add__(self, other: timedelta | np.timedelta64 | Tick) -> Self: ... @overload - def __add__(self, other: TimedeltaSeries) -> TimestampSeries: ... + def __add__(self, other: TimedeltaSeries) -> Series[Timestamp]: ... @overload def __add__(self, other: TimedeltaIndex) -> DatetimeIndex: ... @overload @@ -245,9 +244,11 @@ class Timestamp(datetime, SupportsIndex): @overload def __sub__(self, other: TimedeltaIndex) -> DatetimeIndex: ... @overload - def __sub__(self, other: TimedeltaSeries) -> TimestampSeries: ... + def __sub__(self, other: TimedeltaSeries) -> Series[Timestamp]: ... @overload - def __sub__(self, other: TimestampSeries) -> TimedeltaSeries: ... + def __sub__(self, other: Series[Never]) -> Series: ... + @overload + def __sub__(self, other: Series[Timestamp]) -> Series[Timedelta]: ... @overload def __sub__( self, other: np_ndarray[ShapeT, np.timedelta64] @@ -255,7 +256,7 @@ class Timestamp(datetime, SupportsIndex): @overload def __eq__(self, other: Timestamp | datetime | np.datetime64) -> bool: ... # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload] @overload - def __eq__(self, other: TimestampSeries) -> Series[bool]: ... # type: ignore[overload-overlap] + def __eq__(self, other: Series[Timestamp]) -> Series[bool]: ... # type: ignore[overload-overlap] @overload def __eq__(self, other: Index) -> np_1darray[np.bool]: ... # type: ignore[overload-overlap] @overload @@ -265,7 +266,7 @@ class Timestamp(datetime, SupportsIndex): @overload def __ne__(self, other: Timestamp | datetime | np.datetime64) -> bool: ... # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload] @overload - def __ne__(self, other: TimestampSeries) -> Series[bool]: ... # type: ignore[overload-overlap] + def __ne__(self, other: Series[Timestamp]) -> Series[bool]: ... # type: ignore[overload-overlap] @overload def __ne__(self, other: Index) -> np_1darray[np.bool]: ... # type: ignore[overload-overlap] @overload diff --git a/pandas-stubs/core/indexes/accessors.pyi b/pandas-stubs/core/indexes/accessors.pyi index e96615dee..d0cca4a58 100644 --- a/pandas-stubs/core/indexes/accessors.pyi +++ b/pandas-stubs/core/indexes/accessors.pyi @@ -4,9 +4,11 @@ from datetime import ( tzinfo as _tzinfo, ) from typing import ( + Any, Generic, Literal, TypeVar, + overload, ) import numpy as np @@ -16,6 +18,7 @@ from pandas import ( PeriodIndex, Timedelta, TimedeltaIndex, + Timestamp, ) from pandas.core.accessor import PandasDelegate from pandas.core.arrays import ( @@ -28,12 +31,13 @@ from pandas.core.series import ( PeriodSeries, Series, TimedeltaSeries, - TimestampSeries, ) +from typing_extensions import Never from pandas._libs.tslibs import BaseOffset from pandas._libs.tslibs.offsets import DateOffset from pandas._typing import ( + S1, TimeAmbiguous, TimeNonexistent, TimestampConvention, @@ -154,14 +158,14 @@ class _DatetimeLikeOps( ], ): ... -# Ideally, the rounding methods would return TimestampSeries when `Series.dt.method` +# Ideally, the rounding methods would return Series[Timestamp] when `Series.dt.method` # is invoked, but because of how Series.dt is hooked in and that we may not know the # type of the series, we don't know which kind of series was ...ed # in to the dt accessor _DTTimestampTimedeltaReturnType = TypeVar( "_DTTimestampTimedeltaReturnType", - bound=Series | TimestampSeries | TimedeltaSeries | DatetimeIndex | TimedeltaIndex, + bound=Series | Series[Timestamp] | TimedeltaSeries | DatetimeIndex | TimedeltaIndex, ) class _DatetimeRoundingMethods(Generic[_DTTimestampTimedeltaReturnType]): @@ -197,7 +201,7 @@ class _DatetimeRoundingMethods(Generic[_DTTimestampTimedeltaReturnType]): ) -> _DTTimestampTimedeltaReturnType: ... _DTNormalizeReturnType = TypeVar( - "_DTNormalizeReturnType", TimestampSeries, DatetimeIndex + "_DTNormalizeReturnType", Series[Timestamp], DatetimeIndex ) _DTStrKindReturnType = TypeVar("_DTStrKindReturnType", bound=Series[str] | Index) _DTToPeriodReturnType = TypeVar( @@ -316,10 +320,10 @@ class TimedeltaProperties( ): @property def unit(self) -> TimeUnit: ... - def as_unit(self, unit: TimeUnit) -> TimedeltaSeries: ... + def as_unit(self, unit: TimeUnit) -> Series[Timedelta]: ... _PeriodDTReturnTypes = TypeVar( - "_PeriodDTReturnTypes", bound=TimestampSeries | DatetimeIndex + "_PeriodDTReturnTypes", bound=Series[Timestamp] | DatetimeIndex ) _PeriodIntReturnTypes = TypeVar("_PeriodIntReturnTypes", bound=Series[int] | Index[int]) _PeriodStrReturnTypes = TypeVar("_PeriodStrReturnTypes", bound=Series[str] | Index) @@ -362,7 +366,7 @@ class PeriodIndexFieldOps( class PeriodProperties( Properties, _PeriodProperties[ - TimestampSeries, Series[int], Series[str], DatetimeArray, PeriodArray + Series[Timestamp], Series[int], Series[str], DatetimeArray, PeriodArray ], _DatetimeFieldOps[Series[int]], _IsLeapYearProperty, @@ -376,7 +380,7 @@ class CombinedDatetimelikeProperties( Series[dt.date], Series[dt.time], str, - TimestampSeries, + Series[Timestamp], Series[str], PeriodSeries, ], @@ -387,11 +391,11 @@ class TimestampProperties( DatetimeProperties[ Series[int], Series[bool], - TimestampSeries, + Series[Timestamp], Series[dt.date], Series[dt.time], str, - TimestampSeries, + Series[Timestamp], Series[str], PeriodSeries, ] @@ -426,3 +430,50 @@ class TimedeltaIndexProperties( _TimedeltaPropertiesNoRounding[Index, Index], _DatetimeRoundingMethods[TimedeltaIndex], ): ... + +class _dtDescriptor(CombinedDatetimelikeProperties, Generic[S1]): + @overload + def __get__(self, instance: Series[Never], owner: Any) -> Never: ... + @overload + def __get__( + self, instance: Series[Timestamp], owner: Any + ) -> TimestampProperties: ... + @overload + def __get__( + self, instance: Series[Timedelta], owner: Any + ) -> TimedeltaProperties: ... + @overload + def __get__( + self, instance: Series[S1], owner: Any + ) -> CombinedDatetimelikeProperties: ... + def round( + self, + freq: str | BaseOffset | None, + ambiguous: Literal["raise", "infer", "NaT"] | bool | np_ndarray_bool = ..., + nonexistent: ( + Literal["shift_forward", "shift_backward", "NaT", "raise"] + | timedelta + | Timedelta + ) = ..., + ) -> Series[S1]: ... + def floor( + self, + freq: str | BaseOffset | None, + ambiguous: Literal["raise", "infer", "NaT"] | bool | np_ndarray_bool = ..., + nonexistent: ( + Literal["shift_forward", "shift_backward", "NaT", "raise"] + | timedelta + | Timedelta + ) = ..., + ) -> Series[S1]: ... + def ceil( + self, + freq: str | BaseOffset | None, + ambiguous: Literal["raise", "infer", "NaT"] | bool | np_ndarray_bool = ..., + nonexistent: ( + Literal["shift_forward", "shift_backward", "NaT", "raise"] + | timedelta + | Timedelta + ) = ..., + ) -> Series[S1]: ... + def as_unit(self, unit: TimeUnit) -> Series[S1]: ... diff --git a/pandas-stubs/core/indexes/datetimes.pyi b/pandas-stubs/core/indexes/datetimes.pyi index 29c8f1123..d1652fddf 100644 --- a/pandas-stubs/core/indexes/datetimes.pyi +++ b/pandas-stubs/core/indexes/datetimes.pyi @@ -23,8 +23,8 @@ from pandas import ( from pandas.core.indexes.accessors import DatetimeIndexProperties from pandas.core.indexes.datetimelike import DatetimeTimedeltaMixin from pandas.core.series import ( + Series, TimedeltaSeries, - TimestampSeries, ) from typing_extensions import Self @@ -62,13 +62,13 @@ class DatetimeIndex( # various ignores needed for mypy, as we do want to restrict what can be used in # arithmetic for these types @overload - def __add__(self, other: TimedeltaSeries) -> TimestampSeries: ... + def __add__(self, other: TimedeltaSeries) -> Series[Timestamp]: ... @overload def __add__( self, other: timedelta | Timedelta | TimedeltaIndex | BaseOffset ) -> DatetimeIndex: ... @overload - def __sub__(self, other: TimedeltaSeries) -> TimestampSeries: ... + def __sub__(self, other: TimedeltaSeries) -> Series[Timestamp]: ... @overload def __sub__( self, other: timedelta | Timedelta | TimedeltaIndex | BaseOffset @@ -78,7 +78,7 @@ class DatetimeIndex( self, other: datetime | Timestamp | DatetimeIndex ) -> TimedeltaIndex: ... @final - def to_series(self, index=..., name: Hashable = ...) -> TimestampSeries: ... + def to_series(self, index=..., name: Hashable = ...) -> Series[Timestamp]: ... def snap(self, freq: str = ...): ... def slice_indexer(self, start=..., end=..., step=...): ... def searchsorted(self, value, side: str = ..., sorter=...): ... diff --git a/pandas-stubs/core/indexes/interval.pyi b/pandas-stubs/core/indexes/interval.pyi index b59a47bc4..787d5344d 100644 --- a/pandas-stubs/core/indexes/interval.pyi +++ b/pandas-stubs/core/indexes/interval.pyi @@ -15,7 +15,6 @@ from pandas import Index from pandas.core.indexes.extension import ExtensionIndex from pandas.core.series import ( TimedeltaSeries, - TimestampSeries, ) from typing_extensions import TypeAlias @@ -54,7 +53,7 @@ _EdgesFloat: TypeAlias = ( _EdgesTimestamp: TypeAlias = ( Sequence[DatetimeLike] | npt.NDArray[np.datetime64] - | TimestampSeries + | pd.Series[pd.Timestamp] | pd.DatetimeIndex ) _EdgesTimedelta: TypeAlias = ( diff --git a/pandas-stubs/core/reshape/tile.pyi b/pandas-stubs/core/reshape/tile.pyi index 336426cc9..da7d83f16 100644 --- a/pandas-stubs/core/reshape/tile.pyi +++ b/pandas-stubs/core/reshape/tile.pyi @@ -12,10 +12,9 @@ from pandas import ( Index, Interval, IntervalIndex, - Series, Timestamp, ) -from pandas.core.series import TimestampSeries +from pandas.core.series import Series from pandas._typing import ( IntervalT, @@ -51,10 +50,10 @@ def cut( ) -> tuple[npt.NDArray[np.intp], IntervalIndex[IntervalT]]: ... @overload def cut( # pyright: ignore[reportOverlappingOverload] - x: TimestampSeries, + x: Series[Timestamp], bins: ( int - | TimestampSeries + | Series[Timestamp] | DatetimeIndex | Sequence[Timestamp] | Sequence[np.datetime64] @@ -70,7 +69,7 @@ def cut( # pyright: ignore[reportOverlappingOverload] ) -> tuple[Series, DatetimeIndex]: ... @overload def cut( - x: TimestampSeries, + x: Series[Timestamp], bins: IntervalIndex[Interval[Timestamp]], right: bool = ..., labels: Sequence[Label] | None = ..., @@ -156,10 +155,10 @@ def cut( ) -> npt.NDArray[np.intp]: ... @overload def cut( - x: TimestampSeries, + x: Series[Timestamp], bins: ( int - | TimestampSeries + | Series[Timestamp] | DatetimeIndex | Sequence[Timestamp] | Sequence[np.datetime64] diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index f5bea7bfc..d264c3488 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -62,10 +62,9 @@ from pandas.core.groupby.generic import SeriesGroupBy from pandas.core.groupby.groupby import BaseGroupBy from pandas.core.indexers import BaseIndexer from pandas.core.indexes.accessors import ( - CombinedDatetimelikeProperties, PeriodProperties, TimedeltaProperties, - TimestampProperties, + _dtDescriptor, ) from pandas.core.indexes.category import CategoricalIndex from pandas.core.indexes.datetimes import DatetimeIndex @@ -321,7 +320,7 @@ class Series(IndexOpsMixin[S1], NDFrame): dtype: TimestampDtypeArg = ..., name: Hashable = ..., copy: bool = ..., - ) -> TimestampSeries: ... + ) -> Series[Timestamp]: ... @overload def __new__( cls, @@ -331,7 +330,7 @@ class Series(IndexOpsMixin[S1], NDFrame): dtype: TimestampDtypeArg, name: Hashable = ..., copy: bool = ..., - ) -> TimestampSeries: ... + ) -> Series[Timestamp]: ... @overload def __new__( cls, @@ -748,6 +747,11 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> SeriesGroupBy[S1, Any]: ... def count(self) -> int: ... def mode(self, dropna=True) -> Series[S1]: ... + @overload + def unique(self: Series[Never]) -> np.ndarray: ... # type: ignore[overload-overlap] + @overload + def unique(self: Series[Timestamp]) -> DatetimeArray: ... # type: ignore[overload-overlap] + @overload def unique(self) -> np.ndarray: ... @overload def drop_duplicates( @@ -813,6 +817,8 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def diff(self: Series[_str], periods: int = ...) -> Never: ... @overload + def diff(self: Series[Timestamp], periods: int = ...) -> TimedeltaSeries: ... # type: ignore[overload-overlap] + @overload def diff(self, periods: int = ...) -> Series[float]: ... def autocorr(self, lag: int = 1) -> float: ... @overload @@ -1197,7 +1203,7 @@ class Series(IndexOpsMixin[S1], NDFrame): Series, ]: ... @property - def dt(self) -> CombinedDatetimelikeProperties: ... + def dt(self) -> _dtDescriptor[S1]: ... @property def plot(self) -> PlotAccessor: ... sparse = ... @@ -1318,7 +1324,7 @@ class Series(IndexOpsMixin[S1], NDFrame): dtype: TimestampDtypeArg, copy: _bool = ..., errors: IgnoreRaise = ..., - ) -> TimestampSeries: ... + ) -> Series[Timestamp]: ... @overload def astype( self, @@ -1619,9 +1625,9 @@ class Series(IndexOpsMixin[S1], NDFrame): # just failed to generate these so I couldn't match # them up. @overload - def __add__(self: Series[Never], other: Scalar | _ListLike | Series) -> Series: ... + def __add__(self: Series[Never], other: Scalar | _ListLike | Series) -> Series: ... # type: ignore[overload-overlap] @overload - def __add__(self, other: Series[Never]) -> Series: ... + def __add__(self, other: Series[Never]) -> Series: ... # type: ignore[overload-overlap] @overload def __add__( self: Series[bool], @@ -1634,8 +1640,6 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def __add__(self: Series[bool], other: np_ndarray_float) -> Series[float]: ... @overload - def __add__(self: Series[bool], other: np_ndarray_complex) -> Series[complex]: ... - @overload def __add__( self: Series[int], other: ( @@ -1650,8 +1654,6 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def __add__(self: Series[int], other: np_ndarray_float) -> Series[float]: ... @overload - def __add__(self: Series[int], other: np_ndarray_complex) -> Series[complex]: ... - @overload def __add__( self: Series[float], other: ( @@ -1669,8 +1671,6 @@ class Series(IndexOpsMixin[S1], NDFrame): other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], ) -> Series[_T_COMPLEX]: ... @overload - def __add__(self: Series[float], other: np_ndarray_complex) -> Series[complex]: ... - @overload def __add__( self: Series[complex], other: ( @@ -1684,6 +1684,10 @@ class Series(IndexOpsMixin[S1], NDFrame): ), ) -> Series[complex]: ... @overload + def __add__( + self: Series[_T_COMPLEX], other: np_ndarray_complex + ) -> Series[complex]: ... + @overload def __add__( self: Series[_str], other: ( @@ -1695,6 +1699,37 @@ class Series(IndexOpsMixin[S1], NDFrame): self: Series[_str], other: _str | Sequence[_str] | np_ndarray_str | Series[_str] ) -> Series[_str]: ... @overload + def __add__(self: Series[Timestamp], other: np_ndarray_dt) -> Never: ... + @overload + def __add__( + self: Series[Timestamp], + other: ( + timedelta + | np.timedelta64 + | np_ndarray_td + | TimedeltaIndex + | Series[Timedelta] + | TimedeltaSeries + | BaseOffset + ), + ) -> Series[Timestamp]: ... + @overload + def __add__( + self: Series[Timedelta], + other: datetime | np.datetime64 | np_ndarray_dt | Series[Timestamp], + ) -> Series[Timestamp]: ... + @overload + def __add__( + self: Series[Timedelta], + other: timedelta | np.timedelta64 | np_ndarray_td | TimedeltaSeries, + ) -> TimedeltaSeries: ... + @overload + def __add__( + self: Series[Timedelta], other: Series[Timedelta] + ) -> Series[Timedelta]: ... + @overload + def __add__(self: Series[Timedelta], other: Period) -> PeriodSeries: ... + @overload def add( self: Series[Never], other: Scalar | _ListLike | Series, @@ -1743,14 +1778,6 @@ class Series(IndexOpsMixin[S1], NDFrame): axis: int = 0, ) -> Series[float]: ... @overload - def add( - self: Series[bool], - other: np_ndarray_complex, - level: Level | None = None, - fill_value: float | None = None, - axis: int = 0, - ) -> Series[complex]: ... - @overload def add( self: Series[int], other: ( @@ -1777,14 +1804,6 @@ class Series(IndexOpsMixin[S1], NDFrame): axis: int = 0, ) -> Series[float]: ... @overload - def add( - self: Series[int], - other: np_ndarray_complex, - level: Level | None = None, - fill_value: float | None = None, - axis: int = 0, - ) -> Series[complex]: ... - @overload def add( self: Series[float], other: ( @@ -1808,14 +1827,6 @@ class Series(IndexOpsMixin[S1], NDFrame): axis: int = 0, ) -> Series[_T_COMPLEX]: ... @overload - def add( - self: Series[float], - other: np_ndarray_complex, - level: Level | None = None, - fill_value: float | None = None, - axis: int = 0, - ) -> Series[complex]: ... - @overload def add( self: Series[complex], other: ( @@ -1824,7 +1835,6 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | np_ndarray_complex | Series[_T_COMPLEX] ), level: Level | None = None, @@ -1832,6 +1842,14 @@ class Series(IndexOpsMixin[S1], NDFrame): axis: int = 0, ) -> Series[complex]: ... @overload + def add( + self: Series[_T_COMPLEX], + other: np_ndarray_complex, + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[complex]: ... + @overload def add( self: Series[_str], other: _str | Sequence[_str] | np_ndarray_str | Series[_str], @@ -1839,8 +1857,49 @@ class Series(IndexOpsMixin[S1], NDFrame): fill_value: float | None = None, axis: int = 0, ) -> Series[_str]: ... - @overload # type: ignore[override] - def __radd__(self: Series[Never], other: Scalar | _ListLike) -> Series: ... + @overload + def add( + self: Series[Timestamp], + other: ( + timedelta + | np.timedelta64 + | np_ndarray_td + | TimedeltaIndex + | Series[Timedelta] + | TimedeltaSeries + | BaseOffset + ), + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[Timestamp]: ... + @overload + def add( + self: Series[Timedelta], + other: ( + timedelta + | np.timedelta64 + | np_ndarray_td + | TimedeltaIndex + | Series[Timedelta] + | TimedeltaSeries + ), + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[Timedelta]: ... + @overload + def add( + self: Series[Timestamp], + other: Period, + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> PeriodSeries: ... + @overload + def __radd__(self: Series[Never], other: Scalar | _ListLike | Series) -> Series: ... + @overload + def __radd__(self, other: Series[Never]) -> Series: ... @overload def __radd__( self: Series[bool], @@ -1910,6 +1969,28 @@ class Series(IndexOpsMixin[S1], NDFrame): self: Series[_str], other: _str | Sequence[_str] | np_ndarray_str | Series[_str] ) -> Series[_str]: ... @overload + def __radd__(self: Series[Timestamp], other: np_ndarray_dt) -> Never: ... + @overload + def __radd__( + self: Series[Timestamp], + other: ( + timedelta + | np.timedelta64 + | np_ndarray_td + | TimedeltaIndex + | Series[Timedelta] + | TimedeltaSeries + | BaseOffset + ), + ) -> Series[Timestamp]: ... + @overload + def __radd__( + self: Series[Timedelta], + other: datetime | np.datetime64 | np_ndarray_dt | Series[Timestamp], + ) -> Series[Timestamp]: ... + @overload + def __radd__(self: Series[Timedelta], other: Period) -> PeriodSeries: ... + @overload def radd( self: Series[Never], other: Scalar | _ListLike | Series, @@ -1918,6 +1999,14 @@ class Series(IndexOpsMixin[S1], NDFrame): axis: int = 0, ) -> Series: ... @overload + def radd( + self, + other: Series[Never], + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series: ... + @overload def radd( self: Series[bool], other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], @@ -1936,19 +2025,19 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def radd( self: Series[bool], - other: np_ndarray_float, + other: np_ndarray_anyint, level: Level | None = None, fill_value: float | None = None, axis: int = 0, - ) -> Series[float]: ... + ) -> Series[int]: ... @overload def radd( self: Series[bool], - other: np_ndarray_anyint, + other: np_ndarray_float, level: Level | None = None, fill_value: float | None = None, axis: int = 0, - ) -> Series[int]: ... + ) -> Series[float]: ... @overload def radd( self: Series[int], @@ -2029,6 +2118,45 @@ class Series(IndexOpsMixin[S1], NDFrame): fill_value: float | None = None, axis: int = 0, ) -> Series[_str]: ... + @overload + def radd( + self: Series[Timestamp], + other: ( + timedelta + | np.timedelta64 + | np_ndarray_td + | TimedeltaIndex + | Series[Timedelta] + | TimedeltaSeries + | BaseOffset + ), + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[Timestamp]: ... + @overload + def radd( + self: Series[Timedelta], + other: ( + timedelta + | np.timedelta64 + | np_ndarray_td + | TimedeltaIndex + | Series[Timedelta] + | TimedeltaSeries + ), + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> Series[Timedelta]: ... + @overload + def radd( + self: Series[Timestamp], + other: Period, + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> PeriodSeries: ... # ignore needed for mypy as we want different results based on the arguments @overload # type: ignore[override] def __and__( # pyright: ignore[reportOverlappingOverload] @@ -2037,6 +2165,23 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def __and__(self, other: int | np_ndarray_anyint | Series[int]) -> Series[int]: ... def __eq__(self, other: object) -> Series[_bool]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + @overload + def __floordiv__( + self: Series[Timedelta], other: float | Sequence[float] + ) -> TimedeltaSeries: ... + @overload + def __floordiv__( + self: Series[Timedelta], + other: ( + timedelta + | np.timedelta64 + | np_ndarray_td + | TimedeltaIndex + | Series[Timedelta] + | TimedeltaSeries + ), + ) -> Series[int]: ... + @overload def __floordiv__(self, other: num | _ListLike | Series[S1]) -> Series[int]: ... def __ge__( # type: ignore[override] self, other: S1 | _ListLike | Series[S1] | datetime | timedelta | date @@ -2114,9 +2259,42 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Series[complex]: ... @overload def __mul__( - self, other: timedelta | Timedelta | TimedeltaSeries | np.timedelta64 + self: Series[bool], + other: timedelta | np.timedelta64 | np_ndarray_td | TimedeltaSeries, ) -> TimedeltaSeries: ... @overload + def __mul__(self: Series[bool], other: Series[Timedelta]) -> Series[Timedelta]: ... # type: ignore[overload-overlap] + @overload + def __mul__( + self: Series[int], + other: timedelta | np.timedelta64 | np_ndarray_td | TimedeltaSeries, + ) -> TimedeltaSeries: ... + @overload + def __mul__(self: Series[int], other: Series[Timedelta]) -> Series[Timedelta]: ... + @overload + def __mul__( + self: Series[float], + other: timedelta | np.timedelta64 | np_ndarray_td | TimedeltaSeries, + ) -> TimedeltaSeries: ... + @overload + def __mul__(self: Series[float], other: Series[Timedelta]) -> Series[Timedelta]: ... + @overload + def __mul__( + self: Series[Timedelta], + other: ( + float + | Sequence[float] + | np_ndarray_bool + | np_ndarray_anyint + | np_ndarray_float + ), + ) -> TimedeltaSeries: ... + @overload + def __mul__( + self: Series[Timedelta], + other: Series[bool] | Series[int] | Series[float], + ) -> Series[Timedelta]: ... + @overload def mul( self: Series[Never], other: complex | _ListLike | Series, @@ -2239,7 +2417,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def mul( self, - other: timedelta | Timedelta | TimedeltaSeries | np.timedelta64, + other: timedelta | np.timedelta64 | np_ndarray_td | TimedeltaSeries, level: Level | None = ..., fill_value: float | None = None, axis: AxisIndex | None = 0, @@ -2308,8 +2486,49 @@ class Series(IndexOpsMixin[S1], NDFrame): self: Series[_T_COMPLEX], other: np_ndarray_complex ) -> Series[complex]: ... @overload + def __rmul__( # type: ignore[misc] + self: Series[bool], + other: ( + timedelta + | np.timedelta64 + | np_ndarray_td + | Series[Timedelta] + | TimedeltaSeries + ), + ) -> TimedeltaSeries: ... + @overload + def __rmul__( # type: ignore[misc] + self: Series[int], + other: ( + timedelta + | np.timedelta64 + | np_ndarray_td + | Series[Timedelta] + | TimedeltaSeries + ), + ) -> TimedeltaSeries: ... + @overload + def __rmul__( # type: ignore[misc] + self: Series[float], + other: ( + timedelta + | np.timedelta64 + | np_ndarray_td + | Series[Timedelta] + | TimedeltaSeries + ), + ) -> TimedeltaSeries: ... + @overload def __rmul__( - self, other: timedelta | Timedelta | TimedeltaSeries | np.timedelta64 + self: Series[Timedelta], + other: ( + float + | Sequence[float] + | np_ndarray_bool + | np_ndarray_anyint + | np_ndarray_float + | Series[_T_INT] + ), ) -> TimedeltaSeries: ... @overload def rmul( @@ -2434,7 +2653,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def rmul( self, - other: timedelta | Timedelta | TimedeltaSeries | np.timedelta64, + other: timedelta | np.timedelta64 | np_ndarray_td | TimedeltaSeries, level: Level | None = ..., fill_value: float | None = None, axis: AxisIndex = ..., @@ -2457,6 +2676,19 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def __rand__(self, other: int | np_ndarray_anyint | Series[int]) -> Series[int]: ... def __rdivmod__(self, other: num | _ListLike | Series[S1]) -> Series[S1]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + @overload + def __rfloordiv__( + self: Series[Timedelta], + other: ( + timedelta + | np.timedelta64 + | np_ndarray_td + | TimedeltaIndex + | Series[Timedelta] + | TimedeltaSeries + ), + ) -> Series[int]: ... + @overload def __rfloordiv__(self, other: num | _ListLike | Series[S1]) -> Series[S1]: ... def __rmod__(self, other: num | _ListLike | Series[S1]) -> Series[S1]: ... def __rpow__(self, other: num | _ListLike | Series[S1]) -> Series[S1]: ... @@ -2475,11 +2707,14 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def __rxor__(self, other: int | np_ndarray_anyint | Series[int]) -> Series[int]: ... @overload + def __sub__(self: Series[Never], other: Series[Never]) -> Series: ... # type: ignore[overload-overlap] + @overload def __sub__( - self: Series[Never], - other: datetime | np.datetime64 | np_ndarray_dt | TimestampSeries, + self: Series[Never], other: datetime | np.datetime64 | np_ndarray_dt ) -> TimedeltaSeries: ... @overload + def __sub__(self: Series[Never], other: Series[Timestamp]) -> Series[Timedelta]: ... + @overload def __sub__(self: Series[Never], other: complex | _ListLike | Series) -> Series: ... @overload def __sub__(self, other: Series[Never]) -> Series: ... # type: ignore[overload-overlap] @@ -2547,16 +2782,25 @@ class Series(IndexOpsMixin[S1], NDFrame): ), ) -> Series[complex]: ... @overload + def __sub__( + self: Series[Timestamp], other: datetime | np.datetime64 | np_ndarray_dt + ) -> TimedeltaSeries: ... + @overload + def __sub__( + self: Series[Timestamp], other: Series[Timestamp] + ) -> Series[Timedelta]: ... + @overload def __sub__( self: Series[Timestamp], other: ( timedelta | np.timedelta64 | np_ndarray_td - | TimedeltaSeries | TimedeltaIndex + | TimedeltaSeries + | BaseOffset ), - ) -> TimestampSeries: ... + ) -> Series[Timestamp]: ... @overload def __sub__( self: Series[Timedelta], @@ -2564,14 +2808,14 @@ class Series(IndexOpsMixin[S1], NDFrame): timedelta | np.timedelta64 | np_ndarray_td - | TimedeltaSeries | TimedeltaIndex + | TimedeltaSeries ), ) -> TimedeltaSeries: ... @overload def sub( self: Series[Never], - other: datetime | np.datetime64 | np_ndarray_dt | TimestampSeries, + other: datetime | np.datetime64 | np_ndarray_dt | Series[Timestamp], level: Level | None = None, fill_value: float | None = None, axis: int = 0, @@ -2677,19 +2921,28 @@ class Series(IndexOpsMixin[S1], NDFrame): axis: int = 0, ) -> Series[complex]: ... @overload + def sub( + self: Series[Timestamp], + other: datetime | np.datetime64 | np_ndarray_dt | Series[Timestamp], + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> TimedeltaSeries: ... + @overload def sub( self: Series[Timestamp], other: ( timedelta | np.timedelta64 | np_ndarray_td - | TimedeltaSeries | TimedeltaIndex + | TimedeltaSeries + | BaseOffset ), level: Level | None = None, fill_value: float | None = None, axis: int = 0, - ) -> TimestampSeries: ... + ) -> Series[Timestamp]: ... @overload def sub( self: Series[Timedelta], @@ -2697,21 +2950,18 @@ class Series(IndexOpsMixin[S1], NDFrame): timedelta | np.timedelta64 | np_ndarray_td - | TimedeltaSeries | TimedeltaIndex + | Series[Timedelta] + | TimedeltaSeries ), level: Level | None = None, fill_value: float | None = None, axis: int = 0, ) -> TimedeltaSeries: ... @overload - def __rsub__( # type: ignore[misc] + def __rsub__( # type: ignore[overload-overlap] self: Series[Never], - other: datetime | np.datetime64 | np_ndarray_dt | TimestampSeries, - ) -> TimedeltaSeries: ... - @overload - def __rsub__( - self: Series[Never], other: complex | _ListLike | Series + other: complex | datetime | np.datetime64 | _ListLike | Series, ) -> Series: ... @overload def __rsub__(self, other: Series[Never]) -> Series: ... @@ -2779,23 +3029,21 @@ class Series(IndexOpsMixin[S1], NDFrame): ), ) -> Series[complex]: ... @overload - def rsub( - self: Series[Never], - other: datetime | np.datetime64 | np_ndarray_dt | TimestampSeries, - level: Level | None = None, - fill_value: float | None = None, - axis: int = 0, + def __rsub__(self: Series[Timestamp], other: np_ndarray_td) -> Never: ... + @overload + def __rsub__( + self: Series[Timestamp], other: datetime | np.datetime64 | np_ndarray_dt ) -> TimedeltaSeries: ... @overload - def rsub( + def rsub( # type: ignore[overload-overlap] self: Series[Never], - other: complex | _ListLike | Series, + other: complex | datetime | np.datetime64 | _ListLike | Series, level: Level | None = None, fill_value: float | None = None, axis: int = 0, ) -> Series: ... @overload - def rsub( + def rsub( # type: ignore[overload-overlap] self, other: Series[Never], level: Level | None = None, @@ -2887,6 +3135,14 @@ class Series(IndexOpsMixin[S1], NDFrame): axis: int = 0, ) -> Series[complex]: ... @overload + def rsub( + self: Series[Timestamp], + other: datetime | np.datetime64 | np_ndarray_dt | Series[Timestamp], + level: Level | None = None, + fill_value: float | None = None, + axis: int = 0, + ) -> TimedeltaSeries: ... + @overload def __truediv__( self: Series[Never], other: complex | _ListLike | Series ) -> Series: ... @@ -2963,6 +3219,23 @@ class Series(IndexOpsMixin[S1], NDFrame): self: Series[_T_COMPLEX], other: np_ndarray_complex ) -> Series[complex]: ... @overload + def __truediv__( + self: Series[Timestamp], + other: float | Sequence[float] | Series[int] | Series[float], + ) -> Series[Timestamp]: ... + @overload + def __truediv__( + self: Series[Timedelta], + other: ( + timedelta + | np.timedelta64 + | np_ndarray_td + | TimedeltaIndex + | Series[Timedelta] + | TimedeltaSeries + ), + ) -> Series[float]: ... + @overload def __truediv__(self, other: Path) -> Series: ... @overload def truediv( @@ -3074,6 +3347,29 @@ class Series(IndexOpsMixin[S1], NDFrame): axis: AxisIndex = 0, ) -> Series[complex]: ... @overload + def truediv( + self: Series[Timestamp], + other: float | Sequence[float] | Series[int] | Series[float], + level: Level | None = None, + fill_value: float | None = None, + axis: AxisIndex = 0, + ) -> Series[Timestamp]: ... + @overload + def truediv( + self: Series[Timedelta], + other: ( + timedelta + | np.timedelta64 + | np_ndarray_td + | TimedeltaIndex + | Series[Timedelta] + | TimedeltaSeries + ), + level: Level | None = None, + fill_value: float | None = None, + axis: AxisIndex = 0, + ) -> Series[Timedelta]: ... + @overload def truediv( self, other: Path, @@ -3158,6 +3454,18 @@ class Series(IndexOpsMixin[S1], NDFrame): self: Series[_T_COMPLEX], other: np_ndarray_complex ) -> Series[complex]: ... @overload + def __rtruediv__( + self: Series[Timedelta], + other: ( + timedelta + | np.timedelta64 + | np_ndarray_td + | TimedeltaIndex + | Series[Timedelta] + | TimedeltaSeries + ), + ) -> Series[float]: ... + @overload def __rtruediv__(self, other: Path) -> Series: ... @overload def rtruediv( @@ -3337,6 +3645,14 @@ class Series(IndexOpsMixin[S1], NDFrame): **kwargs: Any, ) -> Never: ... @overload + def cumprod( + self: Series[Timestamp], + axis: AxisIndex = ..., + skipna: _bool = ..., + *args: Any, + **kwargs: Any, + ) -> Never: ... + @overload def cumprod( self, axis: AxisIndex = ..., @@ -3445,6 +3761,25 @@ class Series(IndexOpsMixin[S1], NDFrame): numeric_only: _bool = False, **kwargs: Any, ) -> S1: ... + @overload + def mean( + self: Series[Never], + axis: AxisIndex | None = ..., + skipna: _bool = ..., + level: None = ..., + numeric_only: _bool = False, + **kwargs: Any, + ) -> float: ... + @overload + def mean( + self: Series[Timestamp], + axis: AxisIndex | None = ..., + skipna: _bool = ..., + level: None = ..., + numeric_only: _bool = False, + **kwargs: Any, + ) -> Timestamp: ... + @overload def mean( self, axis: AxisIndex | None = 0, @@ -3453,14 +3788,24 @@ class Series(IndexOpsMixin[S1], NDFrame): numeric_only: _bool = False, **kwargs: Any, ) -> float: ... + @overload def median( - self, + self: Series[float], axis: AxisIndex | None = 0, skipna: _bool = True, level: None = ..., numeric_only: _bool = False, **kwargs: Any, ) -> float: ... + @overload + def median( + self: Series[Timestamp], + axis: AxisIndex | None = 0, + skipna: _bool = True, + level: None = ..., + numeric_only: _bool = False, + **kwargs: Any, + ) -> Timestamp: ... def min( self, axis: AxisIndex | None = 0, @@ -3577,6 +3922,17 @@ class Series(IndexOpsMixin[S1], NDFrame): numeric_only: _bool = False, **kwargs: Any, ) -> Scalar: ... + @overload + def std( + self: Series[Timestamp], + axis: AxisIndex | None = 0, + skipna: _bool | None = True, + level: None = ..., + ddof: int = ..., + numeric_only: _bool = False, + **kwargs: Any, + ) -> Timedelta: ... + @overload def std( self, axis: AxisIndex | None = 0, @@ -3614,6 +3970,30 @@ class Series(IndexOpsMixin[S1], NDFrame): **kwargs: Any, ) -> S1: ... def to_list(self) -> list[S1]: ... + @overload # type: ignore[override] + def to_numpy( + self: Series[Timestamp], + dtype: None = None, + copy: bool = False, + na_value: Scalar = ..., + **kwargs, + ) -> np_1darray[np.datetime64]: ... + @overload + def to_numpy( + self: Series[Timestamp], + dtype: np.dtype[GenericT] | SupportsDType[GenericT] | type[GenericT], + copy: bool = False, + na_value: Scalar = ..., + **kwargs, + ) -> np_1darray[GenericT]: ... + @overload + def to_numpy( + self, + dtype: DTypeLike | None = None, + copy: bool = False, + na_value: Scalar = ..., + **kwargs, + ) -> np_1darray: ... def tolist(self) -> list[S1]: ... def var( self, @@ -3676,7 +4056,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @type_check_only class _SeriesSubclassBase(Series[S1], Generic[S1, GenericT_co]): - @overload + @overload # type: ignore[override] def to_numpy( # pyrefly: ignore self, dtype: None = None, @@ -3693,7 +4073,7 @@ class _SeriesSubclassBase(Series[S1], Generic[S1, GenericT_co]): **kwargs, ) -> np_1darray[GenericT]: ... @overload - def to_numpy( + def to_numpy( # pyright: ignore[reportIncompatibleMethodOverride] self, dtype: DTypeLike, copy: bool = False, @@ -3701,80 +4081,24 @@ class _SeriesSubclassBase(Series[S1], Generic[S1, GenericT_co]): **kwargs, ) -> np_1darray: ... -class TimestampSeries(_SeriesSubclassBase[Timestamp, np.datetime64]): - @property - def dt(self) -> TimestampProperties: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] - def __add__(self, other: TimedeltaSeries | np.timedelta64 | timedelta | BaseOffset) -> TimestampSeries: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] - def __radd__(self, other: TimedeltaSeries | np.timedelta64 | timedelta) -> TimestampSeries: ... # type: ignore[override] - @overload # type: ignore[override] - def __sub__( - self, other: Timestamp | datetime | TimestampSeries - ) -> TimedeltaSeries: ... - @overload - def __sub__( # pyright: ignore[reportIncompatibleMethodOverride] - self, - other: ( - timedelta | TimedeltaSeries | TimedeltaIndex | np.timedelta64 | BaseOffset - ), - ) -> TimestampSeries: ... - def __mul__(self, other: float | Series[int] | Series[float] | Sequence[float]) -> TimestampSeries: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] - def __truediv__(self, other: float | Series[int] | Series[float] | Sequence[float]) -> TimestampSeries: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] - def unique(self) -> DatetimeArray: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] - def mean( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] - self, - axis: AxisIndex | None = 0, - skipna: _bool = ..., - level: None = ..., - numeric_only: _bool = ..., - **kwargs: Any, - ) -> Timestamp: ... - def median( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] - self, - axis: AxisIndex | None = 0, - skipna: _bool = ..., - level: None = ..., - numeric_only: _bool = ..., - **kwargs: Any, - ) -> Timestamp: ... - def std( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] - self, - axis: AxisIndex | None = 0, - skipna: _bool | None = ..., - ddof: int = ..., - numeric_only: _bool = ..., - **kwargs: Any, - ) -> Timedelta: ... - def diff(self, periods: int = ...) -> TimedeltaSeries: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] - def cumprod( - self, - axis: AxisIndex = ..., - skipna: _bool = ..., - *args: Any, - **kwargs: Any, - ) -> Never: ... - class TimedeltaSeries(_SeriesSubclassBase[Timedelta, np.timedelta64]): # ignores needed because of mypy @overload # type: ignore[override] def __add__(self, other: Period) -> PeriodSeries: ... @overload def __add__( - self, other: datetime | Timestamp | TimestampSeries | DatetimeIndex - ) -> TimestampSeries: ... + self, other: datetime | Series[Timestamp] | DatetimeIndex + ) -> Series[Timestamp]: ... @overload - def __add__( # pyright: ignore[reportIncompatibleMethodOverride] - self, other: timedelta | Timedelta | np.timedelta64 - ) -> TimedeltaSeries: ... - def __radd__(self, other: datetime | Timestamp | TimestampSeries) -> TimestampSeries: ... # type: ignore[override] + def __add__(self, other: timedelta | np.timedelta64) -> TimedeltaSeries: ... + def __radd__(self, other: datetime | Series[Timestamp]) -> Series[Timestamp]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] def __mul__( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] self, other: num | Sequence[num] | Series[int] | Series[float] ) -> TimedeltaSeries: ... def unique(self) -> TimedeltaArray: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] def __sub__( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] self, - other: ( - timedelta | Timedelta | TimedeltaSeries | TimedeltaIndex | np.timedelta64 - ), + other: timedelta | TimedeltaSeries | TimedeltaIndex | np.timedelta64, ) -> TimedeltaSeries: ... @overload # type: ignore[override] def __truediv__(self, other: float | Sequence[float]) -> Self: ... @@ -3789,14 +4113,28 @@ class TimedeltaSeries(_SeriesSubclassBase[Timedelta, np.timedelta64]): | Sequence[timedelta] ), ) -> Series[float]: ... - def __rtruediv__( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + @overload # type: ignore[override] + def __rtruediv__( self, other: ( timedelta + | np.timedelta64 + | Sequence[timedelta] + | np_ndarray_td | TimedeltaSeries + | TimedeltaIndex + ), + ) -> Series[float]: ... + @overload + def __rtruediv__( # pyright: ignore[reportIncompatibleMethodOverride] + self: Series[Timedelta], + other: ( + timedelta | np.timedelta64 + | Series[Timedelta] + | np_ndarray_td + | TimedeltaSeries | TimedeltaIndex - | Sequence[timedelta] ), ) -> Series[float]: ... @overload # type: ignore[override] @@ -3806,8 +4144,8 @@ class TimedeltaSeries(_SeriesSubclassBase[Timedelta, np.timedelta64]): self, other: ( timedelta - | TimedeltaSeries | np.timedelta64 + | TimedeltaSeries | TimedeltaIndex | Sequence[timedelta] ), @@ -3816,14 +4154,16 @@ class TimedeltaSeries(_SeriesSubclassBase[Timedelta, np.timedelta64]): self, other: ( timedelta - | TimedeltaSeries | np.timedelta64 + | TimedeltaSeries | TimedeltaIndex | Sequence[timedelta] ), ) -> Series[int]: ... @property - def dt(self) -> TimedeltaProperties: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + def dt( # pyright: ignore[reportIncompatibleMethodOverride] # pyrefly: ignore + self, + ) -> TimedeltaProperties: ... def mean( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] self, axis: AxisIndex | None = 0, @@ -3832,7 +4172,7 @@ class TimedeltaSeries(_SeriesSubclassBase[Timedelta, np.timedelta64]): numeric_only: _bool = ..., **kwargs: Any, ) -> Timedelta: ... - def median( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + def median( # type: ignore[override] self, axis: AxisIndex | None = 0, skipna: _bool = ..., @@ -3857,7 +4197,7 @@ class TimedeltaSeries(_SeriesSubclassBase[Timedelta, np.timedelta64]): *args: Any, **kwargs: Any, ) -> TimedeltaSeries: ... - def cumprod( + def cumprod( # pyrefly: ignore self, axis: AxisIndex = ..., skipna: _bool = ..., @@ -3882,8 +4222,10 @@ class OffsetSeries(_SeriesSubclassBase[BaseOffset, np.object_]): @overload # type: ignore[override] def __radd__(self, other: Period) -> PeriodSeries: ... @overload - def __radd__(self, other: BaseOffset) -> OffsetSeries: ... - def cumprod( + def __radd__( # pyright: ignore[reportIncompatibleMethodOverride] + self, other: BaseOffset + ) -> OffsetSeries: ... + def cumprod( # pyrefly: ignore self, axis: AxisIndex = ..., skipna: _bool = ..., @@ -3896,4 +4238,4 @@ class IntervalSeries( ): @property def array(self) -> IntervalArray: ... - def diff(self, periods: int = ...) -> Never: ... + def diff(self, periods: int = ...) -> Never: ... # pyrefly: ignore diff --git a/pandas-stubs/core/tools/datetimes.pyi b/pandas-stubs/core/tools/datetimes.pyi index 6d45eef4d..f040023bf 100644 --- a/pandas-stubs/core/tools/datetimes.pyi +++ b/pandas-stubs/core/tools/datetimes.pyi @@ -16,10 +16,7 @@ from pandas import ( ) from pandas.core.arrays import ExtensionArray from pandas.core.indexes.datetimes import DatetimeIndex -from pandas.core.series import ( - Series, - TimestampSeries, -) +from pandas.core.series import Series from typing_extensions import TypeAlias from pandas._libs.tslibs import NaTType @@ -94,7 +91,7 @@ def to_datetime( unit: str | None = ..., origin: Literal["julian", "unix"] | TimestampConvertibleTypes = ..., cache: bool = ..., -) -> TimestampSeries: ... +) -> Series[Timestamp]: ... @overload def to_datetime( arg: ( diff --git a/tests/series/arithmetic/str/test_add.py b/tests/series/arithmetic/str/test_add.py index 2eaffd59a..e113586fd 100644 --- a/tests/series/arithmetic/str/test_add.py +++ b/tests/series/arithmetic/str/test_add.py @@ -35,7 +35,7 @@ def test_add_py_scalar() -> None: check(assert_type(left.add(r0), "pd.Series[str]"), pd.Series, str) if TYPE_CHECKING_INVALID_USAGE: - left.radd(i) # type: ignore[call-overload] # pyright: ignore[reportArgumentType] + left.radd(i) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] check(assert_type(left.radd(r0), "pd.Series[str]"), pd.Series, str) @@ -61,7 +61,7 @@ def test_add_py_sequence() -> None: check(assert_type(left.add(r1), "pd.Series[str]"), pd.Series, str) if TYPE_CHECKING_INVALID_USAGE: - left.radd(i) # type: ignore[arg-type] # pyright: ignore[reportArgumentType] + left.radd(i) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] check(assert_type(left.radd(r0), "pd.Series[str]"), pd.Series, str) check(assert_type(left.radd(r1), "pd.Series[str]"), pd.Series, str) @@ -96,7 +96,7 @@ def test_add_numpy_array() -> None: check(assert_type(left.add(r0), "pd.Series[str]"), pd.Series, str) if TYPE_CHECKING_INVALID_USAGE: - left.radd(i) # type: ignore[arg-type] # pyright: ignore[reportArgumentType] + left.radd(i) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] check(assert_type(left.radd(r0), "pd.Series[str]"), pd.Series, str) @@ -118,5 +118,5 @@ def test_add_pd_series() -> None: check(assert_type(left.add(r0), "pd.Series[str]"), pd.Series, str) if TYPE_CHECKING_INVALID_USAGE: - left.radd(i) # type: ignore[arg-type] # pyright: ignore[reportArgumentType] + left.radd(i) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] check(assert_type(left.radd(r0), "pd.Series[str]"), pd.Series, str) diff --git a/tests/series/arithmetic/test_sub.py b/tests/series/arithmetic/test_sub.py index 636aa242c..497c1ef25 100644 --- a/tests/series/arithmetic/test_sub.py +++ b/tests/series/arithmetic/test_sub.py @@ -146,11 +146,11 @@ def test_sub_py_datetime() -> None: check(assert_type(left_ts - s, "TimedeltaSeries"), pd.Series, pd.Timedelta) - check(assert_type(s - left_ts, "TimedeltaSeries"), pd.Series, pd.Timedelta) + check(assert_type(s - left_ts, pd.Series), pd.Series, pd.Timedelta) check(assert_type(left_ts.sub(s), "TimedeltaSeries"), pd.Series, pd.Timedelta) - check(assert_type(left_ts.rsub(s), "TimedeltaSeries"), pd.Series, pd.Timedelta) + check(assert_type(left_ts.rsub(s), pd.Series), pd.Series, pd.Timedelta) def test_sub_numpy_datetime() -> None: @@ -161,7 +161,7 @@ def test_sub_numpy_datetime() -> None: check(assert_type(left_ts - s, "TimedeltaSeries"), pd.Series, pd.Timedelta) check(assert_type(left_ts - a, "TimedeltaSeries"), pd.Series, pd.Timedelta) - check(assert_type(s - left_ts, "TimedeltaSeries"), pd.Series, pd.Timedelta) + check(assert_type(s - left_ts, pd.Series), pd.Series, pd.Timedelta) # `numpy` typing gives the corresponding `ndarray`s in the static type # checking, where our `__rsub__` cannot override. At runtime, they return # `Series`s. @@ -170,8 +170,8 @@ def test_sub_numpy_datetime() -> None: check(assert_type(left_ts.sub(s), "TimedeltaSeries"), pd.Series, pd.Timedelta) check(assert_type(left_ts.sub(a), "TimedeltaSeries"), pd.Series, pd.Timedelta) - check(assert_type(left_ts.rsub(s), "TimedeltaSeries"), pd.Series, pd.Timedelta) - check(assert_type(left_ts.rsub(a), "TimedeltaSeries"), pd.Series, pd.Timedelta) + check(assert_type(left_ts.rsub(s), pd.Series), pd.Series, pd.Timedelta) + check(assert_type(left_ts.rsub(a), pd.Series), pd.Series, pd.Timedelta) def test_sub_pd_datetime() -> None: @@ -180,13 +180,13 @@ def test_sub_pd_datetime() -> None: a = pd.Series([s + pd.Timedelta(minutes=m) for m in range(3)]) check(assert_type(left_ts - s, "TimedeltaSeries"), pd.Series, pd.Timedelta) - check(assert_type(left_ts - a, "TimedeltaSeries"), pd.Series, pd.Timedelta) + check(assert_type(left_ts - a, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) - check(assert_type(s - left_ts, "TimedeltaSeries"), pd.Series, pd.Timedelta) - check(assert_type(a - left_ts, "TimedeltaSeries"), pd.Series, pd.Timedelta) + check(assert_type(s - left_ts, pd.Series), pd.Series, pd.Timedelta) + check(assert_type(a - left_ts, pd.Series), pd.Series, pd.Timedelta) check(assert_type(left_ts.sub(s), "TimedeltaSeries"), pd.Series, pd.Timedelta) check(assert_type(left_ts.sub(a), "TimedeltaSeries"), pd.Series, pd.Timedelta) - check(assert_type(left_ts.rsub(s), "TimedeltaSeries"), pd.Series, pd.Timedelta) - check(assert_type(left_ts.rsub(a), "TimedeltaSeries"), pd.Series, pd.Timedelta) + check(assert_type(left_ts.rsub(s), pd.Series), pd.Series, pd.Timedelta) + check(assert_type(left_ts.rsub(a), pd.Series), pd.Series, pd.Timedelta) diff --git a/tests/series/arithmetic/timestamp/__init__.py b/tests/series/arithmetic/timestamp/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/series/arithmetic/timestamp/test_add.py b/tests/series/arithmetic/timestamp/test_add.py new file mode 100644 index 000000000..689b04811 --- /dev/null +++ b/tests/series/arithmetic/timestamp/test_add.py @@ -0,0 +1,151 @@ +from datetime import ( + datetime, + timedelta, +) + +import numpy as np +from numpy import typing as npt # noqa: F401 +import pandas as pd +from typing_extensions import ( + Never, + assert_type, +) + +from tests import ( + TYPE_CHECKING_INVALID_USAGE, + check, +) + +left = pd.Series([pd.Timestamp(2025, 8, 20)]) # left operand + + +def test_add_py_scalar() -> None: + """Test pd.Series[pd.Timestamp] + Python native scalars""" + s = datetime(2025, 8, 20) + d = timedelta(seconds=1) + + if TYPE_CHECKING_INVALID_USAGE: + _0 = left + s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left + d, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + if TYPE_CHECKING_INVALID_USAGE: + _1 = s + left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d + left, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + if TYPE_CHECKING_INVALID_USAGE: + left.add(s) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.add(d), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + if TYPE_CHECKING_INVALID_USAGE: + left.radd(s) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.radd(d), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + +def test_add_numpy_scalar() -> None: + """Test pd.Series[pd.Timestamp] + numpy scalars""" + s = np.datetime64("2025-08-20") + d = np.timedelta64(1, "s") + + if TYPE_CHECKING_INVALID_USAGE: + _0 = left + s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left + d, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + if TYPE_CHECKING_INVALID_USAGE: + _1 = s + left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d + left, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + if TYPE_CHECKING_INVALID_USAGE: + left.add(s) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.add(d), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + if TYPE_CHECKING_INVALID_USAGE: + left.radd(s) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.radd(d), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + +def test_add_pd_scalar() -> None: + """Test pd.Series[pd.Timestamp] + pandas scalars""" + s = pd.Timestamp("2025-08-20") + d = pd.Timedelta(seconds=1) + + if TYPE_CHECKING_INVALID_USAGE: + _0 = left + s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left + d, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + if TYPE_CHECKING_INVALID_USAGE: + _1 = s + left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d + left, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + if TYPE_CHECKING_INVALID_USAGE: + left.add(s) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.add(d), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + if TYPE_CHECKING_INVALID_USAGE: + left.radd(s) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.radd(d), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + +def test_add_py_sequence() -> None: + """Test pd.Series[pd.Timestamp] + Python native sequence""" + s = [datetime(2025, 8, 20)] + d = [timedelta(seconds=1)] + + if TYPE_CHECKING_INVALID_USAGE: + _0 = left + s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _a = left + d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + _1 = s + left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _b = d + left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + left.add(s) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + left.add(d) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + + left.radd(s) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + left.radd(d) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + + +def test_add_numpy_array() -> None: + """Test pd.Series[pd.Timestamp] + numpy array""" + s = np.array([np.datetime64("2025-08-20")], np.datetime64) + d = np.array([np.timedelta64(1, "s")], np.timedelta64) + + if TYPE_CHECKING_INVALID_USAGE: + assert_type(left + s, Never) + check(assert_type(left + d, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + # `numpy` typing gives the corresponding `ndarray`s in the static type + # checking, where our `__radd__` cannot override. At runtime, they return + # `Series`s. + if TYPE_CHECKING_INVALID_USAGE: + assert_type(s + left, "npt.NDArray[np.datetime64]") + check(assert_type(d + left, "npt.NDArray[np.timedelta64]"), pd.Series, pd.Timestamp) + + if TYPE_CHECKING_INVALID_USAGE: + left.add(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.add(d), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + if TYPE_CHECKING_INVALID_USAGE: + left.radd(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.radd(d), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + +def test_add_pd_series() -> None: + """Test pd.Series[pd.Timestamp] + pandas Series""" + s = pd.Series([pd.Timestamp("2025-08-20")]) + d = pd.Series([pd.Timedelta(seconds=1)]) + + if TYPE_CHECKING_INVALID_USAGE: + _0 = left + s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left + d, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + if TYPE_CHECKING_INVALID_USAGE: + _1 = s + left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d + left, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + if TYPE_CHECKING_INVALID_USAGE: + left.add(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.add(d), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + if TYPE_CHECKING_INVALID_USAGE: + left.radd(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.radd(d), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) diff --git a/tests/series/arithmetic/timestamp/test_sub.py b/tests/series/arithmetic/timestamp/test_sub.py new file mode 100644 index 000000000..ab9c02a2d --- /dev/null +++ b/tests/series/arithmetic/timestamp/test_sub.py @@ -0,0 +1,142 @@ +from datetime import ( + datetime, + timedelta, +) +from typing import TYPE_CHECKING + +import numpy as np +from numpy import typing as npt # noqa: F401 +import pandas as pd +from typing_extensions import assert_type + +from tests import ( + TYPE_CHECKING_INVALID_USAGE, + check, +) + +if TYPE_CHECKING: + from pandas.core.series import TimedeltaSeries # noqa: F401 + +left = pd.Series([pd.Timestamp(2025, 8, 20)]) # left operand + + +def test_sub_py_scalar() -> None: + """Test pd.Series[pd.Timestamp] - Python native scalars""" + s = datetime(2025, 8, 20) + d = timedelta(seconds=1) + + check(assert_type(left - s, "TimedeltaSeries"), pd.Series, pd.Timedelta) + check(assert_type(left - d, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + check(assert_type(s - left, "TimedeltaSeries"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + _ = d - left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + check(assert_type(left.sub(s), "TimedeltaSeries"), pd.Series, pd.Timedelta) + check(assert_type(left - d, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + check(assert_type(left.rsub(s), "TimedeltaSeries"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + left.rsub(d) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + + +def test_sub_numpy_scalar() -> None: + """Test pd.Series[pd.Timestamp] - numpy scalars""" + s = np.datetime64("2025-08-20") + d = np.timedelta64(1, "s") + + check(assert_type(left - s, "TimedeltaSeries"), pd.Series, pd.Timedelta) + check(assert_type(left - d, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + check(assert_type(s - left, "TimedeltaSeries"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + _ = d - left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + check(assert_type(left.sub(s), "TimedeltaSeries"), pd.Series, pd.Timedelta) + check(assert_type(left - d, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + check(assert_type(left.rsub(s), "TimedeltaSeries"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + left.rsub(d) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + + +def test_sub_pd_scalar() -> None: + """Test pd.Series[pd.Timestamp] - pandas scalars""" + s = pd.Timestamp("2025-08-20") + d = pd.Timedelta(seconds=1) + + check(assert_type(left - s, "TimedeltaSeries"), pd.Series, pd.Timedelta) + check(assert_type(left - d, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + check(assert_type(s - left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + _ = d - left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + check(assert_type(left.sub(s), "TimedeltaSeries"), pd.Series, pd.Timedelta) + check(assert_type(left - d, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + check(assert_type(left.rsub(s), "TimedeltaSeries"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + left.rsub(d) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + + +def test_sub_py_sequence() -> None: + """Test pd.Series[pd.Timestamp] - Python native sequence""" + s = [datetime(2025, 8, 20)] + d = [timedelta(seconds=1)] + + if TYPE_CHECKING_INVALID_USAGE: + _0 = left - s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _a = left - d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + _1 = s - left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _b = d - left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + left.sub(s) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + left.sub(d) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + + left.rsub(s) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rsub(d) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + + +def test_sub_numpy_array() -> None: + """Test pd.Series[pd.Timestamp] - numpy array""" + s = np.array([np.datetime64("2025-08-20")], np.datetime64) + d = np.array([np.timedelta64(1, "s")], np.timedelta64) + + check(assert_type(left - s, "TimedeltaSeries"), pd.Series, pd.Timedelta) + check(assert_type(left - d, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + # `numpy` typing gives the corresponding `ndarray`s in the static type + # checking, where our `__radd__` cannot override. At runtime, they return + # `Series`s. + check(assert_type(s - left, "npt.NDArray[np.datetime64]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + assert_type(d - left, "npt.NDArray[np.timedelta64]") + + check(assert_type(left.sub(s), "TimedeltaSeries"), pd.Series, pd.Timedelta) + check(assert_type(left - d, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + check(assert_type(left.rsub(s), "TimedeltaSeries"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + left.rsub(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + +def test_sub_pd_series() -> None: + """Test pd.Series[pd.Timestamp] - pandas Series""" + s = pd.Series([pd.Timestamp("2025-08-20")]) + d = pd.Series([pd.Timedelta(seconds=1)]) + + check(assert_type(left - s, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left - d, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + check(assert_type(s - left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + _ = d - left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + check(assert_type(left.sub(s), "TimedeltaSeries"), pd.Series, pd.Timedelta) + check(assert_type(left - d, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + check(assert_type(left.rsub(s), "TimedeltaSeries"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + left.rsub(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] diff --git a/tests/series/test_series.py b/tests/series/test_series.py index af90cde4b..9d44c3592 100644 --- a/tests/series/test_series.py +++ b/tests/series/test_series.py @@ -75,7 +75,6 @@ from pandas.core.series import ( OffsetSeries, TimedeltaSeries, - TimestampSeries, ) from tests import ( @@ -95,7 +94,6 @@ else: TimedeltaSeries: TypeAlias = pd.Series - TimestampSeries: TypeAlias = pd.Series OffsetSeries: TypeAlias = pd.Series if not PD_LTE_23: @@ -1654,12 +1652,6 @@ def test_reset_index() -> None: assert assert_type(s.reset_index(inplace=True, drop=True), None) is None -def test_series_add_str() -> None: - s = pd.Series(["abc", "def"]) - check(assert_type(s + "x", "pd.Series[str]"), pd.Series, str) - check(assert_type("x" + s, "pd.Series[str]"), pd.Series, str) - - def test_series_dtype() -> None: s = pd.Series(["abc", "def"], dtype=str) check(assert_type(s, "pd.Series[str]"), pd.Series, str) @@ -2775,64 +2767,64 @@ def test_astype_timestamp(cast_arg: TimestampDtypeArg, target_type: type) -> Non if cast_arg in ("date32[pyarrow]", "date64[pyarrow]"): x = pd.Series(pd.date_range("2000-01-01", "2000-02-01")) - check(x.astype(cast_arg), TimestampSeries, target_type) + check(x.astype(cast_arg), pd.Series, target_type) else: - check(s.astype(cast_arg), TimestampSeries, target_type) + check(s.astype(cast_arg), pd.Series, target_type) if TYPE_CHECKING: # numpy datetime64 - assert_type(s.astype("datetime64[Y]"), TimestampSeries) - assert_type(s.astype("datetime64[M]"), TimestampSeries) - assert_type(s.astype("datetime64[W]"), TimestampSeries) - assert_type(s.astype("datetime64[D]"), TimestampSeries) - assert_type(s.astype("datetime64[h]"), TimestampSeries) - assert_type(s.astype("datetime64[m]"), TimestampSeries) - assert_type(s.astype("datetime64[s]"), TimestampSeries) - assert_type(s.astype("datetime64[ms]"), TimestampSeries) - assert_type(s.astype("datetime64[us]"), TimestampSeries) - assert_type(s.astype("datetime64[μs]"), TimestampSeries) - assert_type(s.astype("datetime64[ns]"), TimestampSeries) - assert_type(s.astype("datetime64[ps]"), TimestampSeries) - assert_type(s.astype("datetime64[fs]"), TimestampSeries) - assert_type(s.astype("datetime64[as]"), TimestampSeries) + assert_type(s.astype("datetime64[Y]"), "pd.Series[pd.Timestamp]") + assert_type(s.astype("datetime64[M]"), "pd.Series[pd.Timestamp]") + assert_type(s.astype("datetime64[W]"), "pd.Series[pd.Timestamp]") + assert_type(s.astype("datetime64[D]"), "pd.Series[pd.Timestamp]") + assert_type(s.astype("datetime64[h]"), "pd.Series[pd.Timestamp]") + assert_type(s.astype("datetime64[m]"), "pd.Series[pd.Timestamp]") + assert_type(s.astype("datetime64[s]"), "pd.Series[pd.Timestamp]") + assert_type(s.astype("datetime64[ms]"), "pd.Series[pd.Timestamp]") + assert_type(s.astype("datetime64[us]"), "pd.Series[pd.Timestamp]") + assert_type(s.astype("datetime64[μs]"), "pd.Series[pd.Timestamp]") + assert_type(s.astype("datetime64[ns]"), "pd.Series[pd.Timestamp]") + assert_type(s.astype("datetime64[ps]"), "pd.Series[pd.Timestamp]") + assert_type(s.astype("datetime64[fs]"), "pd.Series[pd.Timestamp]") + assert_type(s.astype("datetime64[as]"), "pd.Series[pd.Timestamp]") # numpy datetime64 type codes - assert_type(s.astype("M8[Y]"), TimestampSeries) - assert_type(s.astype("M8[M]"), TimestampSeries) - assert_type(s.astype("M8[W]"), TimestampSeries) - assert_type(s.astype("M8[D]"), TimestampSeries) - assert_type(s.astype("M8[h]"), TimestampSeries) - assert_type(s.astype("M8[m]"), TimestampSeries) - assert_type(s.astype("M8[s]"), TimestampSeries) - assert_type(s.astype("M8[ms]"), TimestampSeries) - assert_type(s.astype("M8[us]"), TimestampSeries) - assert_type(s.astype("M8[μs]"), TimestampSeries) - assert_type(s.astype("M8[ns]"), TimestampSeries) - assert_type(s.astype("M8[ps]"), TimestampSeries) - assert_type(s.astype("M8[fs]"), TimestampSeries) - assert_type(s.astype("M8[as]"), TimestampSeries) + assert_type(s.astype("M8[Y]"), "pd.Series[pd.Timestamp]") + assert_type(s.astype("M8[M]"), "pd.Series[pd.Timestamp]") + assert_type(s.astype("M8[W]"), "pd.Series[pd.Timestamp]") + assert_type(s.astype("M8[D]"), "pd.Series[pd.Timestamp]") + assert_type(s.astype("M8[h]"), "pd.Series[pd.Timestamp]") + assert_type(s.astype("M8[m]"), "pd.Series[pd.Timestamp]") + assert_type(s.astype("M8[s]"), "pd.Series[pd.Timestamp]") + assert_type(s.astype("M8[ms]"), "pd.Series[pd.Timestamp]") + assert_type(s.astype("M8[us]"), "pd.Series[pd.Timestamp]") + assert_type(s.astype("M8[μs]"), "pd.Series[pd.Timestamp]") + assert_type(s.astype("M8[ns]"), "pd.Series[pd.Timestamp]") + assert_type(s.astype("M8[ps]"), "pd.Series[pd.Timestamp]") + assert_type(s.astype("M8[fs]"), "pd.Series[pd.Timestamp]") + assert_type(s.astype("M8[as]"), "pd.Series[pd.Timestamp]") # numpy datetime64 type codes - assert_type(s.astype(" None: def test_timedeltaseries_operators() -> None: series = pd.Series([pd.Timedelta(days=1)]) check( - assert_type(series + datetime.datetime.now(), TimestampSeries), + assert_type(series + datetime.datetime.now(), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp, ) @@ -3347,7 +3339,7 @@ def test_timedeltaseries_operators() -> None: pd.Timedelta, ) check( - assert_type(datetime.datetime.now() + series, TimestampSeries), + assert_type(datetime.datetime.now() + series, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp, ) @@ -3361,13 +3353,13 @@ def test_timedeltaseries_operators() -> None: def test_timestamp_series() -> None: series = pd.Series([pd.Timestamp(2024, 4, 4)]) check( - assert_type(series + YearEnd(0), TimestampSeries), - TimestampSeries, + assert_type(series + YearEnd(0), "pd.Series[pd.Timestamp]"), + pd.Series, pd.Timestamp, ) check( - assert_type(series - YearEnd(0), TimestampSeries), - TimestampSeries, + assert_type(series - YearEnd(0), "pd.Series[pd.Timestamp]"), + pd.Series, pd.Timestamp, ) @@ -3915,7 +3907,7 @@ def test_cumsum_timedelta() -> None: s = pd.Series(pd.to_timedelta([1, 2, 3], "h")) check(assert_type(s.cumsum(), "TimedeltaSeries"), pd.Series, pd.Timedelta) check( - assert_type(pd.Timestamp(0) + s.cumsum(), "TimestampSeries"), + assert_type(pd.Timestamp(0) + s.cumsum(), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp, ) diff --git a/tests/test_pandas.py b/tests/test_pandas.py index a7633fa8a..8795b7fb7 100644 --- a/tests/test_pandas.py +++ b/tests/test_pandas.py @@ -23,7 +23,6 @@ import pytest from typing_extensions import ( Never, - TypeAlias, assert_type, ) @@ -39,18 +38,19 @@ pytest_warns_bounded, ) -if TYPE_CHECKING: - from pandas.core.series import TimestampSeries -else: - TimestampSeries: TypeAlias = pd.Series - def test_types_to_datetime() -> None: df = pd.DataFrame({"year": [2015, 2016], "month": [2, 3], "day": [4, 5]}) - check(assert_type(pd.to_datetime(df), TimestampSeries), pd.Series, pd.Timestamp) + check( + assert_type(pd.to_datetime(df), "pd.Series[pd.Timestamp]"), + pd.Series, + pd.Timestamp, + ) check( - assert_type(pd.to_datetime(df, unit="s", origin="unix"), TimestampSeries), + assert_type( + pd.to_datetime(df, unit="s", origin="unix"), "pd.Series[pd.Timestamp]" + ), pd.Series, pd.Timestamp, ) @@ -59,7 +59,7 @@ def test_types_to_datetime() -> None: pd.to_datetime( df, unit="ns", dayfirst=True, utc=False, format="%M:%D", exact=False ), - TimestampSeries, + "pd.Series[pd.Timestamp]", ), pd.Series, pd.Timestamp, @@ -95,7 +95,7 @@ def test_types_to_datetime() -> None: check( assert_type( pd.to_datetime({"year": [2015, 2016], "month": [2, 3], "day": [4, 5]}), - TimestampSeries, + "pd.Series[pd.Timestamp]", ), pd.Series, pd.Timestamp, diff --git a/tests/test_scalars.py b/tests/test_scalars.py index 92b29f4bc..16b791ef7 100644 --- a/tests/test_scalars.py +++ b/tests/test_scalars.py @@ -42,12 +42,10 @@ OffsetSeries, PeriodSeries, TimedeltaSeries, - TimestampSeries, ) else: TimedeltaSeries: TypeAlias = pd.Series - TimestampSeries: TypeAlias = pd.Series PeriodSeries: TypeAlias = pd.Series OffsetSeries: TypeAlias = pd.Series @@ -1151,10 +1149,14 @@ def test_timestamp_add_sub() -> None: check(assert_type(as_timedelta_index + ts, pd.DatetimeIndex), pd.DatetimeIndex) check( - assert_type(ts + as_timedelta_series, TimestampSeries), pd.Series, pd.Timestamp + assert_type(ts + as_timedelta_series, "pd.Series[pd.Timestamp]"), + pd.Series, + pd.Timestamp, ) check( - assert_type(as_timedelta_series + ts, TimestampSeries), pd.Series, pd.Timestamp + assert_type(as_timedelta_series + ts, "pd.Series[pd.Timestamp]"), + pd.Series, + pd.Timestamp, ) check( @@ -1177,7 +1179,9 @@ def test_timestamp_add_sub() -> None: check(assert_type(ts - as_offset, pd.Timestamp), pd.Timestamp) check(assert_type(ts - as_timedelta_index, pd.DatetimeIndex), pd.DatetimeIndex) check( - assert_type(ts - as_timedelta_series, TimestampSeries), pd.Series, pd.Timestamp + assert_type(ts - as_timedelta_series, "pd.Series[pd.Timestamp]"), + pd.Series, + pd.Timestamp, ) check( assert_type(ts - as_np_ndarray_td64, npt.NDArray[np.datetime64]), @@ -1255,7 +1259,7 @@ def test_timestamp_cmp_scalar() -> None: def test_timestamp_cmp_series() -> None: ts = pd.Timestamp(year=2000, month=3, day=24, hour=12, minute=27) ts_ser = pd.Series(pd.DatetimeIndex(["2000-1-1", "2000-1-2"])) - check(assert_type(ts_ser, TimestampSeries), pd.Series, pd.Timestamp) + check(assert_type(ts_ser, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) # >, <= gt1 = check(assert_type(ts > ts_ser, "pd.Series[bool]"), pd.Series, np.bool) @@ -1673,7 +1677,7 @@ def test_types_timestamp_series_comparisons() -> None: data = pd.date_range("2022-01-01", "2022-01-31", freq="D") s = pd.Series(data) ts2 = pd.Timestamp("2022-01-15") - check(assert_type(s, TimestampSeries), pd.Series, pd.Timestamp) + check(assert_type(s, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) check(assert_type(ts2 <= s, "pd.Series[bool]"), pd.Series, np.bool_) check(assert_type(ts2 >= s, "pd.Series[bool]"), pd.Series, np.bool_) check(assert_type(ts2 < s, "pd.Series[bool]"), pd.Series, np.bool_) diff --git a/tests/test_timefuncs.py b/tests/test_timefuncs.py index cf7c0bf5c..a870270e7 100644 --- a/tests/test_timefuncs.py +++ b/tests/test_timefuncs.py @@ -4,7 +4,6 @@ from typing import ( TYPE_CHECKING, Optional, - TypeAlias, cast, ) @@ -23,6 +22,7 @@ from pandas.core.tools.datetimes import FulldatetimeDict import pytz from typing_extensions import ( + TypeAlias, assert_never, assert_type, ) @@ -53,12 +53,9 @@ from pandas.core.series import ( IntervalSeries, OffsetSeries, - TimestampSeries, ) from pandas.core.series import PeriodSeries # noqa: F401 from pandas.core.series import TimedeltaSeries # noqa: F401 -else: - TimestampSeries: TypeAlias = pd.Series if not PD_LTE_23: from pandas.errors import Pandas4Warning # type: ignore[attr-defined] # pyright: ignore # isort: skip @@ -135,7 +132,7 @@ def test_types_timestamp_series_comparisons() -> None: data = pd.date_range("2022-01-01", "2022-01-31", freq="D") s = pd.Series(data) ts2 = pd.Timestamp("2022-01-15") - check(assert_type(s, "TimestampSeries"), pd.Series, pd.Timestamp) + check(assert_type(s, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) check(assert_type(ts2 <= s, "pd.Series[bool]"), pd.Series, np.bool_) check(assert_type(ts2 >= s, "pd.Series[bool]"), pd.Series, np.bool_) check(assert_type(ts2 < s, "pd.Series[bool]"), pd.Series, np.bool_) @@ -194,7 +191,7 @@ def test_timestamp_timedelta_series_arithmetic() -> None: td1 = pd.to_timedelta([2, 3], "seconds") ts2 = pd.to_datetime(pd.Series(["2022-03-08", "2022-03-10"])) r1 = ts1 - ts2 - check(assert_type(r1, "TimedeltaSeries"), pd.Series, pd.Timedelta) + check(assert_type(r1, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) r2 = r1 / td1 check(assert_type(r2, "pd.Series[float]"), pd.Series, float) r3 = r1 - td1 @@ -204,7 +201,7 @@ def test_timestamp_timedelta_series_arithmetic() -> None: sb = pd.Series([1, 2]) == pd.Series([1, 3]) check(assert_type(sb, "pd.Series[bool]"), pd.Series, np.bool_) r5 = sb * r1 - check(assert_type(r5, "TimedeltaSeries"), pd.Series, pd.Timedelta) + check(assert_type(r5, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) r6 = r1 * 4 check(assert_type(r6, "TimedeltaSeries"), pd.Series, pd.Timedelta) @@ -226,7 +223,7 @@ def test_datetimeindex_plus_timedelta() -> None: check( assert_type( pd.Series([pd.Timestamp("2022-03-05"), pd.Timestamp("2022-03-06")]), - "TimestampSeries", + "pd.Series[pd.Timestamp]", ), pd.Series, pd.Timestamp, @@ -235,13 +232,13 @@ def test_datetimeindex_plus_timedelta() -> None: td_s = pd.to_timedelta(pd.Series([10, 20]), "minutes") dti_td_s = dti + td_s check( - assert_type(dti_td_s, "TimestampSeries"), + assert_type(dti_td_s, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp, ) td_dti_s = td_s + dti check( - assert_type(td_dti_s, "TimestampSeries"), + assert_type(td_dti_s, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp, ) @@ -261,7 +258,7 @@ def test_datetimeindex_minus_timedelta() -> None: check( assert_type( pd.Series([pd.Timestamp("2022-03-05"), pd.Timestamp("2022-03-06")]), - "TimestampSeries", + "pd.Series[pd.Timestamp]", ), pd.Series, pd.Timestamp, @@ -270,7 +267,7 @@ def test_datetimeindex_minus_timedelta() -> None: td_s = pd.to_timedelta(pd.Series([10, 20]), "minutes") dti_td_s = dti - td_s check( - assert_type(dti_td_s, "TimestampSeries"), + assert_type(dti_td_s, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp, ) @@ -287,7 +284,7 @@ def test_timestamp_plus_timedelta_series() -> None: check( assert_type( pd.Series([pd.Timestamp("2022-03-05"), pd.Timestamp("2022-03-06")]), - "TimestampSeries", + "pd.Series[pd.Timestamp]", ), pd.Series, pd.Timestamp, @@ -295,9 +292,9 @@ def test_timestamp_plus_timedelta_series() -> None: ts = pd.Timestamp("2022-03-05") td = pd.to_timedelta(pd.Series([10, 20]), "minutes") r3 = td + ts - check(assert_type(r3, "TimestampSeries"), pd.Series, pd.Timestamp) + check(assert_type(r3, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) r4 = ts + td - check(assert_type(r4, "TimestampSeries"), pd.Series, pd.Timestamp) + check(assert_type(r4, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) def test_timedelta_series_mult() -> None: @@ -388,7 +385,9 @@ def test_series_dt_accessors() -> None: i0 = pd.date_range(start="2022-06-01", periods=10) check(assert_type(i0, pd.DatetimeIndex), pd.DatetimeIndex, pd.Timestamp) - check(assert_type(i0.to_series(), "TimestampSeries"), pd.Series, pd.Timestamp) + check( + assert_type(i0.to_series(), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp + ) s0 = pd.Series(i0) @@ -435,94 +434,125 @@ def test_series_dt_accessors() -> None: ) s0_local = s0.dt.tz_localize("UTC") check( - assert_type(s0_local, "TimestampSeries"), + assert_type(s0_local, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp, ) check( - assert_type(s0.dt.tz_localize(None), "TimestampSeries"), pd.Series, pd.Timestamp + assert_type(s0.dt.tz_localize(None), "pd.Series[pd.Timestamp]"), + pd.Series, + pd.Timestamp, ) check( assert_type( s0.dt.tz_localize(pytz.UTC, nonexistent=dt.timedelta(0)), - "TimestampSeries", + "pd.Series[pd.Timestamp]", ), pd.Series, pd.Timestamp, ) check( - assert_type(s0.dt.tz_localize(pytz.timezone("US/Eastern")), "TimestampSeries"), + assert_type( + s0.dt.tz_localize(pytz.timezone("US/Eastern")), "pd.Series[pd.Timestamp]" + ), pd.Series, pd.Timestamp, ) check( - assert_type(s0_local.dt.tz_convert("EST"), "TimestampSeries"), + assert_type(s0_local.dt.tz_convert("EST"), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp, ) check( - assert_type(s0_local.dt.tz_convert(None), "TimestampSeries"), + assert_type(s0_local.dt.tz_convert(None), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp, ) check( - assert_type(s0_local.dt.tz_convert(pytz.UTC), "TimestampSeries"), + assert_type(s0_local.dt.tz_convert(pytz.UTC), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp, ) check( - assert_type(s0_local.dt.tz_convert(1), "TimestampSeries"), + assert_type(s0_local.dt.tz_convert(1), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp, ) check( assert_type( - s0_local.dt.tz_convert(pytz.timezone("US/Eastern")), "TimestampSeries" + s0_local.dt.tz_convert(pytz.timezone("US/Eastern")), + "pd.Series[pd.Timestamp]", ), pd.Series, pd.Timestamp, ) check(assert_type(s0.dt.tz, Optional[dt.tzinfo]), type(None)) check(assert_type(s0_local.dt.tz, Optional[dt.tzinfo]), dt.tzinfo) - check(assert_type(s0.dt.normalize(), "TimestampSeries"), pd.Series, pd.Timestamp) + check( + assert_type(s0.dt.normalize(), "pd.Series[pd.Timestamp]"), + pd.Series, + pd.Timestamp, + ) check(assert_type(s0.dt.strftime("%Y"), "pd.Series[str]"), pd.Series, str) check( - assert_type(s0.dt.round("D", nonexistent=dt.timedelta(1)), "TimestampSeries"), + assert_type( + s0.dt.round("D", nonexistent=dt.timedelta(1)), "pd.Series[pd.Timestamp]" + ), pd.Series, pd.Timestamp, ) check( - assert_type(s0.dt.round("D", ambiguous=False), "TimestampSeries"), + assert_type(s0.dt.round("D", ambiguous=False), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp, ) check( - assert_type(s0.dt.floor("D", nonexistent=dt.timedelta(1)), "TimestampSeries"), + assert_type( + s0.dt.floor("D", nonexistent=dt.timedelta(1)), "pd.Series[pd.Timestamp]" + ), pd.Series, pd.Timestamp, ) check( - assert_type(s0.dt.floor("D", ambiguous=False), "TimestampSeries"), + assert_type(s0.dt.floor("D", ambiguous=False), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp, ) check( - assert_type(s0.dt.ceil("D", nonexistent=dt.timedelta(1)), "TimestampSeries"), + assert_type( + s0.dt.ceil("D", nonexistent=dt.timedelta(1)), "pd.Series[pd.Timestamp]" + ), pd.Series, pd.Timestamp, ) check( - assert_type(s0.dt.ceil("D", ambiguous=False), "TimestampSeries"), + assert_type(s0.dt.ceil("D", ambiguous=False), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp, ) check(assert_type(s0.dt.month_name(), "pd.Series[str]"), pd.Series, str) check(assert_type(s0.dt.day_name(), "pd.Series[str]"), pd.Series, str) check(assert_type(s0.dt.unit, TimeUnit), str) - check(assert_type(s0.dt.as_unit("s"), "TimestampSeries"), pd.Series, pd.Timestamp) - check(assert_type(s0.dt.as_unit("ms"), "TimestampSeries"), pd.Series, pd.Timestamp) - check(assert_type(s0.dt.as_unit("us"), "TimestampSeries"), pd.Series, pd.Timestamp) - check(assert_type(s0.dt.as_unit("ns"), "TimestampSeries"), pd.Series, pd.Timestamp) + check( + assert_type(s0.dt.as_unit("s"), "pd.Series[pd.Timestamp]"), + pd.Series, + pd.Timestamp, + ) + check( + assert_type(s0.dt.as_unit("ms"), "pd.Series[pd.Timestamp]"), + pd.Series, + pd.Timestamp, + ) + check( + assert_type(s0.dt.as_unit("us"), "pd.Series[pd.Timestamp]"), + pd.Series, + pd.Timestamp, + ) + check( + assert_type(s0.dt.as_unit("ns"), "pd.Series[pd.Timestamp]"), + pd.Series, + pd.Timestamp, + ) i1 = pd.period_range(start="2022-06-01", periods=10) @@ -533,8 +563,14 @@ def test_series_dt_accessors() -> None: s1 = pd.Series(i1) check(assert_type(s1.dt.qyear, "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(s1.dt.start_time, "TimestampSeries"), pd.Series, pd.Timestamp) - check(assert_type(s1.dt.end_time, "TimestampSeries"), pd.Series, pd.Timestamp) + check( + assert_type(s1.dt.start_time, "pd.Series[pd.Timestamp]"), + pd.Series, + pd.Timestamp, + ) + check( + assert_type(s1.dt.end_time, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp + ) i2 = pd.timedelta_range(start="1 day", periods=10) check(assert_type(i2, pd.TimedeltaIndex), pd.TimedeltaIndex) @@ -569,23 +605,53 @@ def test_series_dt_accessors() -> None: ) check(assert_type(s2.dt.total_seconds(), "pd.Series[float]"), pd.Series, float) check(assert_type(s2.dt.unit, TimeUnit), str) - check(assert_type(s2.dt.as_unit("s"), "TimedeltaSeries"), pd.Series, pd.Timedelta) - check(assert_type(s2.dt.as_unit("ms"), "TimedeltaSeries"), pd.Series, pd.Timedelta) - check(assert_type(s2.dt.as_unit("us"), "TimedeltaSeries"), pd.Series, pd.Timedelta) - check(assert_type(s2.dt.as_unit("ns"), "TimedeltaSeries"), pd.Series, pd.Timedelta) + check( + assert_type(s2.dt.as_unit("s"), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) + check( + assert_type(s2.dt.as_unit("ms"), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) + check( + assert_type(s2.dt.as_unit("us"), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) + check( + assert_type(s2.dt.as_unit("ns"), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) - # Checks for general Series other than TimestampSeries and TimedeltaSeries + # Checks for general Series other than Series[Timestamp] and TimedeltaSeries - s4 = cast( - "pd.Series[pd.Timestamp]", - pd.Series([pd.Timestamp("2024-01-01"), pd.Timestamp("2024-01-02")]), - ) + s4 = pd.Series([pd.Timestamp("2024-01-01"), pd.Timestamp("2024-01-02")]) + check(assert_type(s4, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) check(assert_type(s4.dt.unit, TimeUnit), str) - check(assert_type(s4.dt.as_unit("s"), pd.Series), pd.Series, pd.Timestamp) - check(assert_type(s4.dt.as_unit("ms"), pd.Series), pd.Series, pd.Timestamp) - check(assert_type(s4.dt.as_unit("us"), pd.Series), pd.Series, pd.Timestamp) - check(assert_type(s4.dt.as_unit("ns"), pd.Series), pd.Series, pd.Timestamp) + check( + assert_type(s4.dt.as_unit("s"), "pd.Series[pd.Timestamp]"), + pd.Series, + pd.Timestamp, + ) + check( + assert_type(s4.dt.as_unit("ms"), "pd.Series[pd.Timestamp]"), + pd.Series, + pd.Timestamp, + ) + check( + assert_type(s4.dt.as_unit("us"), "pd.Series[pd.Timestamp]"), + pd.Series, + pd.Timestamp, + ) + check( + assert_type(s4.dt.as_unit("ns"), "pd.Series[pd.Timestamp]"), + pd.Series, + pd.Timestamp, + ) s5 = cast( "pd.Series[pd.Timedelta]", @@ -593,10 +659,26 @@ def test_series_dt_accessors() -> None: ) check(assert_type(s5.dt.unit, TimeUnit), str) - check(assert_type(s5.dt.as_unit("s"), pd.Series), pd.Series, pd.Timedelta) - check(assert_type(s5.dt.as_unit("ms"), pd.Series), pd.Series, pd.Timedelta) - check(assert_type(s5.dt.as_unit("us"), pd.Series), pd.Series, pd.Timedelta) - check(assert_type(s5.dt.as_unit("ns"), pd.Series), pd.Series, pd.Timedelta) + check( + assert_type(s5.dt.as_unit("s"), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) + check( + assert_type(s5.dt.as_unit("ms"), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) + check( + assert_type(s5.dt.as_unit("us"), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) + check( + assert_type(s5.dt.as_unit("ns"), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) def test_datetimeindex_accessors() -> None: @@ -1309,7 +1391,7 @@ def test_to_datetime_scalar_extended() -> None: def test_to_datetime_series() -> None: s = pd.Series(["2000-01-01", "2000-01-02"]) - check(assert_type(pd.to_datetime(s), "TimestampSeries"), pd.Series) + check(assert_type(pd.to_datetime(s), "pd.Series[pd.Timestamp]"), pd.Series) d: FulldatetimeDict = { "year": [2000, 2000, 2000], "month": [1, 1, 1], @@ -1330,9 +1412,9 @@ def test_to_datetime_series() -> None: "us": [1, 1, 1], "ns": [1, 1, 1], } - check(assert_type(pd.to_datetime(df), "TimestampSeries"), pd.Series) - check(assert_type(pd.to_datetime(d), "TimestampSeries"), pd.Series) - check(assert_type(pd.to_datetime(d_ex), "TimestampSeries"), pd.Series) + check(assert_type(pd.to_datetime(df), "pd.Series[pd.Timestamp]"), pd.Series) + check(assert_type(pd.to_datetime(d), "pd.Series[pd.Timestamp]"), pd.Series) + check(assert_type(pd.to_datetime(d_ex), "pd.Series[pd.Timestamp]"), pd.Series) def test_to_datetime_array() -> None: @@ -1573,16 +1655,16 @@ def test_timedelta64_and_arithmatic_operator() -> None: s1 = pd.Series(data=pd.date_range("1/1/2020", "2/1/2020")) s2 = pd.Series(data=pd.date_range("1/1/2021", "2/1/2021")) s3 = s2 - s1 - check(assert_type(s3, "TimedeltaSeries"), pd.Series, pd.Timedelta) + check(assert_type(s3, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) td1 = pd.Timedelta(1, "D") - check(assert_type(s2 - td1, "TimestampSeries"), pd.Series, pd.Timestamp) + check(assert_type(s2 - td1, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) # GH 758 s4 = s1.astype(object) - check(assert_type(s4 - td1, "TimestampSeries"), pd.Series, pd.Timestamp) + check(assert_type(s4 - td1, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) td = np.timedelta64(1, "D") - check(assert_type((s1 - td), "TimestampSeries"), pd.Series, pd.Timestamp) - check(assert_type((s1 + td), "TimestampSeries"), pd.Series, pd.Timestamp) + check(assert_type((s1 - td), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type((s1 + td), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) check(assert_type((s3 - td), "TimedeltaSeries"), pd.Series, pd.Timedelta) check(assert_type((s3 + td), "TimedeltaSeries"), pd.Series, pd.Timedelta) check(assert_type((s3 / td), "pd.Series[float]"), pd.Series, float) @@ -1596,7 +1678,7 @@ def test_timedeltaseries_add_timestampseries() -> None: tds = pd.Series(pd.timedelta_range(start="1 day", periods=10)) tss = pd.Series(pd.date_range(start="2012-01-01", periods=10, freq="W-MON")) plus = tds + tss - check(assert_type(plus, "TimestampSeries"), pd.Series, pd.Timestamp) + check(assert_type(plus, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) def test_mean_median_std() -> None: @@ -1830,7 +1912,7 @@ def test_timestamp_sub_series() -> None: ts1 = pd.to_datetime(pd.Series(["2022-03-05", "2022-03-06"])) one_ts = ts1.iloc[0] check(assert_type(ts1.iloc[0], pd.Timestamp), pd.Timestamp) - check(assert_type(one_ts - ts1, "TimedeltaSeries"), pd.Series, pd.Timedelta) + check(assert_type(one_ts - ts1, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) def test_creating_date_range() -> None: @@ -1858,7 +1940,7 @@ def test_timestamp_to_list_add() -> None: sseries + pd.Timedelta(1, "d") check( - assert_type(sseries + pd.Timedelta(1, "D"), TimestampSeries), + assert_type(sseries + pd.Timedelta(1, "D"), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp, )