From cbbd3720b025408dc85709b2b84e147f1f7b3273 Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Sun, 13 Jul 2025 08:23:15 +0200 Subject: [PATCH 01/13] refactor: only drop TimestampSeries https://github.com/pandas-dev/pandas-stubs/pull/1273#pullrequestreview-3013726071 --- docs/philosophy.md | 16 +- pandas-stubs/_libs/interval.pyi | 11 +- pandas-stubs/_libs/tslibs/timedeltas.pyi | 7 +- pandas-stubs/_libs/tslibs/timestamps.pyi | 19 +- pandas-stubs/core/indexes/accessors.pyi | 66 +++++- pandas-stubs/core/indexes/datetimes.pyi | 8 +- pandas-stubs/core/indexes/interval.pyi | 3 +- pandas-stubs/core/reshape/tile.pyi | 13 +- pandas-stubs/core/series.pyi | 253 ++++++++++++++++------- pandas-stubs/core/tools/datetimes.pyi | 7 +- pyproject.toml | 2 +- tests/test_frame.py | 14 +- tests/test_pandas.py | 20 +- tests/test_scalars.py | 24 ++- tests/test_series.py | 134 ++++++------ tests/test_timefuncs.py | 183 ++++++++++------ 16 files changed, 494 insertions(+), 286 deletions(-) diff --git a/docs/philosophy.md b/docs/philosophy.md index 853c516e1..c19f1e1b9 100644 --- a/docs/philosophy.md +++ b/docs/philosophy.md @@ -36,6 +36,8 @@ 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 + 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"])) @@ -46,19 +48,21 @@ 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 a `Never` +on the computation of `ssum` because it is inappropriate to add two series containing `Timestamp` values. The types will be revealed 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:4: note: Revealed type is "pandas.core.series.Series[pandas._libs.tslibs.timestamps.Timestamp]" +ttest.py:6: note: Revealed type is "pandas.core.series.Series[pandas._libs.tslibs.timestamps.Timestamp]" ttest.py:8: note: Revealed type is "pandas.core.series.TimedeltaSeries" -ttest.py:10: note: Revealed type is "builtins.Exception" +ttest.py:9: error: Need type annotation for "ssum" [var-annotated] +ttest.py:10: note: Revealed type is "Never" ``` -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 fdb0a398c..613eb06ba 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, @@ -174,7 +171,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: ... @@ -183,7 +180,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: ... @@ -192,7 +189,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 01a17e1df..798b87a9d 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, @@ -167,7 +164,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 b986c186a..3b991d7ef 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, @@ -172,7 +171,7 @@ class Timestamp(datetime, SupportsIndex): self, other: DatetimeIndex | npt.NDArray[np.datetime64] ) -> np_ndarray_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 @@ -180,7 +179,7 @@ class Timestamp(datetime, SupportsIndex): self, other: DatetimeIndex | npt.NDArray[np.datetime64] ) -> np_ndarray_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 @@ -188,7 +187,7 @@ class Timestamp(datetime, SupportsIndex): self, other: DatetimeIndex | npt.NDArray[np.datetime64] ) -> np_ndarray_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 @@ -196,7 +195,7 @@ class Timestamp(datetime, SupportsIndex): self, other: DatetimeIndex | npt.NDArray[np.datetime64] ) -> np_ndarray_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__( @@ -205,7 +204,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 @@ -224,9 +223,9 @@ 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[Timestamp]) -> TimedeltaSeries: ... @overload def __sub__( self, other: npt.NDArray[np.timedelta64] @@ -234,7 +233,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: npt.NDArray[np.datetime64] | Index) -> np_ndarray_bool: ... # type: ignore[overload-overlap] @overload @@ -242,7 +241,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: npt.NDArray[np.datetime64] | Index) -> np_ndarray_bool: ... # type: ignore[overload-overlap] @overload diff --git a/pandas-stubs/core/indexes/accessors.pyi b/pandas-stubs/core/indexes/accessors.pyi index b5db84dba..70ce8e090 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 @@ -17,6 +19,7 @@ from pandas import ( PeriodIndex, Timedelta, TimedeltaIndex, + Timestamp, ) from pandas.core.accessor import PandasDelegate from pandas.core.arrays import ( @@ -29,12 +32,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, @@ -155,14 +159,13 @@ 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, + "_DTTimestampTimedeltaReturnType", bound=Series | DatetimeIndex | TimedeltaIndex ) class _DatetimeRoundingMethods(Generic[_DTTimestampTimedeltaReturnType]): @@ -198,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( @@ -320,7 +323,7 @@ class TimedeltaProperties( def as_unit(self, unit: TimeUnit) -> TimedeltaSeries: ... _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) @@ -363,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, @@ -377,7 +380,7 @@ class CombinedDatetimelikeProperties( Series[dt.date], Series[dt.time], str, - TimestampSeries, + Series[Timestamp], Series[str], PeriodSeries, ], @@ -388,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, ] @@ -427,3 +430,46 @@ 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[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 40a7102cd..589390856 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 @@ -60,13 +60,13 @@ class DatetimeIndex(DatetimeTimedeltaMixin[Timestamp], DatetimeIndexProperties): # 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 @@ -76,7 +76,7 @@ class DatetimeIndex(DatetimeTimedeltaMixin[Timestamp], DatetimeIndexProperties): 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 026c4f2af..cc53b668c 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 @@ -53,7 +52,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 0fac9a3de..68e9fccb0 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -25,6 +25,7 @@ from typing import ( Generic, Literal, NoReturn, + TypeVar, final, overload, ) @@ -59,10 +60,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 @@ -184,6 +184,30 @@ from pandas.core.dtypes.dtypes import CategoricalDtype from pandas.plotting import PlotAccessor +_T_FLOAT = TypeVar("_T_FLOAT", bound=float) +_T_COMPLEX = TypeVar("_T_COMPLEX", bound=complex) + +_scalar_timestamp: TypeAlias = datetime | np.datetime64 | Timestamp +_vector_timestamp: TypeAlias = ( + Sequence[datetime] + | Sequence[np.datetime64] + | Sequence[Timestamp] + | np.typing.NDArray[np.datetime64] + | DatetimeIndex +) +_nonseries_timestamp: TypeAlias = _scalar_timestamp | _vector_timestamp + +_scalar_timedelta: TypeAlias = timedelta | np.timedelta64 | BaseOffset | Timedelta +_vector_timedelta: TypeAlias = ( + Sequence[timedelta] + | Sequence[np.timedelta64] + | Sequence[Timedelta] + | np.typing.NDArray[np.timedelta64] + | TimedeltaIndex +) +_nonseries_timedelta: TypeAlias = _scalar_timedelta | _vector_timedelta +_T_TIMESTAMP = TypeVar("_T_TIMESTAMP", bound=Timestamp) + class _iLocIndexerSeries(_iLocIndexer, Generic[S1]): # get item @overload @@ -301,7 +325,7 @@ class Series(IndexOpsMixin[S1], NDFrame): dtype: TimestampDtypeArg = ..., name: Hashable = ..., copy: bool = ..., - ) -> TimestampSeries: ... + ) -> Series[Timestamp]: ... @overload def __new__( cls, @@ -311,7 +335,7 @@ class Series(IndexOpsMixin[S1], NDFrame): dtype: TimestampDtypeArg, name: Hashable = ..., copy: bool = ..., - ) -> TimestampSeries: ... + ) -> Series[Timestamp]: ... @overload def __new__( cls, @@ -752,6 +776,13 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def count(self, level: Hashable) -> Series[S1]: ... def mode(self, dropna=...) -> 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: Series[Timedelta]) -> TimedeltaArray: ... # type: ignore[overload-overlap] + @overload def unique(self) -> np.ndarray: ... @overload def drop_duplicates( @@ -809,6 +840,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 = ...) -> float: ... @overload @@ -1191,7 +1224,7 @@ class Series(IndexOpsMixin[S1], NDFrame): Series[type[object]], ]: ... @property - def dt(self) -> CombinedDatetimelikeProperties: ... + def dt(self) -> _dtDescriptor[S1]: ... @property def plot(self) -> PlotAccessor: ... sparse = ... @@ -1311,7 +1344,7 @@ class Series(IndexOpsMixin[S1], NDFrame): dtype: TimestampDtypeArg, copy: _bool = ..., errors: IgnoreRaise = ..., - ) -> TimestampSeries: ... + ) -> Series[Timestamp]: ... @overload def astype( self, @@ -1613,6 +1646,26 @@ class Series(IndexOpsMixin[S1], NDFrame): # just failed to generate these so I couldn't match # them up. @overload + def __add__( + self: Series[Never], + other: num | _str | timedelta | Timedelta | _ListLike | Series | np.timedelta64, + ) -> Series: ... + @overload + def __add__( + self: Series[Timestamp], other: _nonseries_timestamp | Series[Timestamp] + ) -> Never: ... + @overload + def __add__( + self: Series[Timestamp], + other: _nonseries_timedelta | Series[Timedelta] | TimedeltaSeries, + ) -> Series[Timestamp]: ... + @overload + def __add__(self: Series[Timedelta], other: Period) -> PeriodSeries: ... + @overload + def __add__( + self: Series[Timedelta], other: _nonseries_timestamp | Series[Timestamp] + ) -> Series[Timestamp]: ... + @overload def __add__(self, other: S1 | Self) -> Self: ... @overload def __add__( @@ -1629,6 +1682,16 @@ class Series(IndexOpsMixin[S1], NDFrame): # def __array__(self, dtype: Optional[_bool] = ...) -> _np_ndarray def __div__(self, other: num | _ListLike | Series[S1]) -> Series[S1]: ... 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: _nonseries_timedelta | Series[Timedelta], + ) -> 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 @@ -1643,8 +1706,27 @@ class Series(IndexOpsMixin[S1], NDFrame): self, other: S1 | _ListLike | Series[S1] | datetime | timedelta | date ) -> Series[_bool]: ... @overload + def __mul__(self: Series[Never], other: num | _ListLike | Series) -> Series: ... + @overload + def __mul__(self, other: Series[Never]) -> Series: ... # type: ignore[overload-overlap] + @overload def __mul__( - self, other: timedelta | Timedelta | TimedeltaSeries | np.timedelta64 + self: Series[int], other: _T_COMPLEX | Series[_T_COMPLEX] + ) -> Series[_T_COMPLEX]: ... + @overload + def __mul__( + self: Series[Timestamp], + other: ( + num | Sequence[num] | Series[int] | Series[float] | float | Sequence[float] + ), + ) -> Series[Timestamp]: ... + @overload + def __mul__( + self: Series[Timestamp], other: _nonseries_timedelta | TimedeltaSeries + ) -> Never: ... + @overload + def __mul__( + self: Series[_T_FLOAT], other: _nonseries_timedelta | TimedeltaSeries ) -> TimedeltaSeries: ... @overload def __mul__(self, other: num | _ListLike | Series) -> Series: ... @@ -1659,6 +1741,18 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def __or__(self, other: int | np_ndarray_anyint | Series[int]) -> Series[int]: ... @overload + def __radd__( + self: Series[Never], other: num | _str | _ListLike | Series + ) -> Series: ... + @overload + def __radd__( + self: Series[Timestamp], other: _nonseries_timedelta | Series[Timedelta] + ) -> Series[Timestamp]: ... + @overload + def __radd__( + self: Series[Timedelta], other: datetime | Timestamp | Series[Timestamp] + ) -> Series[Timestamp]: ... + @overload def __radd__(self, other: S1 | Series[S1]) -> Self: ... @overload def __radd__(self, other: num | _str | _ListLike | Series) -> Series: ... @@ -1671,6 +1765,11 @@ class Series(IndexOpsMixin[S1], NDFrame): def __rand__(self, other: int | np_ndarray_anyint | Series[int]) -> Series[int]: ... def __rdiv__(self, other: num | _ListLike | Series[S1]) -> Series[S1]: ... def __rdivmod__(self, other: num | _ListLike | Series[S1]) -> Series[S1]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + @overload + def __rfloordiv__( + self: Series[Timedelta], other: _nonseries_timedelta | Series[Timedelta] + ) -> Series[int]: ... + @overload def __rfloordiv__(self, other: num | _ListLike | Series[S1]) -> Series[S1]: ... def __rmod__(self, other: num | _ListLike | Series[S1]) -> Series[S1]: ... @overload @@ -1689,6 +1788,11 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def __ror__(self, other: int | np_ndarray_anyint | Series[int]) -> Series[int]: ... def __rsub__(self, other: num | _ListLike | Series[S1]) -> Series: ... + @overload + def __rtruediv__( + self: Series[Timedelta], other: _nonseries_timedelta | Series[Timedelta] + ) -> Series[float]: ... + @overload def __rtruediv__(self, other: num | _ListLike | Series[S1] | Path) -> Series: ... # ignore needed for mypy as we want different results based on the arguments @overload # type: ignore[override] @@ -1698,21 +1802,33 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def __rxor__(self, other: int | np_ndarray_anyint | Series[int]) -> Series[int]: ... @overload - def __sub__( - self: Series[Timestamp], - other: Timedelta | TimedeltaSeries | TimedeltaIndex | np.timedelta64, - ) -> TimestampSeries: ... + def __sub__(self: Series[Never], other: num | _ListLike | Series) -> Series: ... @overload def __sub__( - self: Series[Timedelta], - other: Timedelta | TimedeltaSeries | TimedeltaIndex | np.timedelta64, - ) -> TimedeltaSeries: ... + self: Series[Timestamp], other: _nonseries_timedelta | TimedeltaSeries + ) -> Series[Timestamp]: ... @overload def __sub__( - self, other: Timestamp | datetime | TimestampSeries + self: Series[Timestamp], other: _nonseries_timestamp | Series[_T_TIMESTAMP] ) -> TimedeltaSeries: ... @overload + def __sub__(self, other: S1 | Self) -> Self: ... + @overload def __sub__(self, other: num | _ListLike | Series) -> Series: ... + @overload + def __truediv__( + self: Series[Never], other: num | _ListLike | Series[S1] | Path + ) -> Series: ... + @overload + def __truediv__( + self: Series[Timestamp], + other: float | Series[int] | Series[float] | Sequence[float], + ) -> Series[Timestamp]: ... + @overload + def __truediv__( + self: Series[Timedelta], other: _nonseries_timedelta | Series[Timedelta] + ) -> Series[float]: ... + @overload def __truediv__(self, other: num | _ListLike | Series[S1] | Path) -> Series: ... # ignore needed for mypy as we want different results based on the arguments @overload # type: ignore[override] @@ -1782,6 +1898,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 = ..., @@ -1895,6 +2019,25 @@ class Series(IndexOpsMixin[S1], NDFrame): numeric_only: _bool = ..., **kwargs: Any, ) -> S1: ... + @overload + def mean( + self: Series[Never], + axis: AxisIndex | None = ..., + skipna: _bool = ..., + level: None = ..., + numeric_only: _bool = ..., + **kwargs: Any, + ) -> float: ... + @overload + def mean( + self: Series[Timestamp], + axis: AxisIndex | None = ..., + skipna: _bool = ..., + level: None = ..., + numeric_only: _bool = ..., + **kwargs: Any, + ) -> Timestamp: ... + @overload def mean( self, axis: AxisIndex | None = ..., @@ -1910,7 +2053,7 @@ class Series(IndexOpsMixin[S1], NDFrame): level: None = ..., numeric_only: _bool = ..., **kwargs: Any, - ) -> float: ... + ) -> S1: ... def min( self, axis: AxisIndex | None = ..., @@ -2091,6 +2234,17 @@ class Series(IndexOpsMixin[S1], NDFrame): numeric_only: _bool = ..., **kwargs: Any, ) -> Scalar: ... + @overload + def std( + self: Series[Timestamp], + axis: AxisIndex | None = ..., + skipna: _bool | None = ..., + level: None = ..., + ddof: int = ..., + numeric_only: _bool = ..., + **kwargs: Any, + ) -> Timedelta: ... + @overload def std( self, axis: AxisIndex | None = ..., @@ -2224,72 +2378,19 @@ class Series(IndexOpsMixin[S1], NDFrame): @final def __bool__(self) -> NoReturn: ... -class TimestampSeries(Series[Timestamp]): - @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] # pyright: ignore[reportIncompatibleMethodOverride] - @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 = ..., - skipna: _bool = ..., - level: None = ..., - numeric_only: _bool = ..., - **kwargs: Any, - ) -> Timestamp: ... - def median( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] - self, - axis: AxisIndex | None = ..., - skipna: _bool = ..., - level: None = ..., - numeric_only: _bool = ..., - **kwargs: Any, - ) -> Timestamp: ... - def std( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] - self, - axis: AxisIndex | None = ..., - skipna: _bool | None = ..., - level: 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(Series[Timedelta]): # 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 | Timestamp | 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] # pyright: ignore[reportIncompatibleMethodOverride] + def __radd__(self, other: datetime | Timestamp | 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: ... @@ -2356,7 +2457,7 @@ class TimedeltaSeries(Series[Timedelta]): numeric_only: _bool = ..., **kwargs: Any, ) -> Timedelta: ... - def median( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + def median( self, axis: AxisIndex | None = ..., skipna: _bool = ..., @@ -2381,7 +2482,7 @@ class TimedeltaSeries(Series[Timedelta]): *args: Any, **kwargs: Any, ) -> TimedeltaSeries: ... - def cumprod( + def cumprod( # pyrefly: ignore self, axis: AxisIndex = ..., skipna: _bool = ..., @@ -2409,7 +2510,7 @@ class OffsetSeries(Series[BaseOffset]): def __radd__( # pyright: ignore[reportIncompatibleMethodOverride] self, other: BaseOffset ) -> OffsetSeries: ... - def cumprod( + def cumprod( # pyrefly: ignore self, axis: AxisIndex = ..., skipna: _bool = ..., @@ -2420,4 +2521,4 @@ class OffsetSeries(Series[BaseOffset]): class IntervalSeries(Series[Interval[_OrderableT]], Generic[_OrderableT]): @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/pyproject.toml b/pyproject.toml index 71400163a..d916bfa93 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,7 +39,7 @@ mypy = "1.17.0" pandas = "2.3.0" pyarrow = ">=10.0.1" pytest = ">=7.1.2" -pyright = ">=1.1.400" +pyright = ">=1.1.403" ty = "^0.0.1a8" pyrefly = "^0.21.0" poethepoet = ">=0.16.5" diff --git a/tests/test_frame.py b/tests/test_frame.py index ffd85d609..ac711045f 100644 --- a/tests/test_frame.py +++ b/tests/test_frame.py @@ -31,7 +31,6 @@ import numpy as np import numpy.typing as npt import pandas as pd -from pandas import Timestamp from pandas.api.typing import NAType from pandas.core.resample import ( DatetimeIndexResampler, @@ -63,10 +62,8 @@ if TYPE_CHECKING: from pandas.core.frame import _PandasNamedTuple - from pandas.core.series import TimestampSeries else: _PandasNamedTuple: TypeAlias = tuple - TimestampSeries: TypeAlias = pd.Series DF = pd.DataFrame(data={"col1": [1, 2], "col2": [3, 4]}) @@ -2535,9 +2532,9 @@ def test_types_regressions() -> 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, - Timestamp, + pd.Timestamp, ) # https://github.com/microsoft/pylance-release/issues/2133 @@ -2819,9 +2816,9 @@ def test_sum_get_add() -> None: summer = df.sum(axis=1) check(assert_type(summer, pd.Series), pd.Series) - check(assert_type(s + summer, pd.Series), pd.Series) - check(assert_type(s + df["y"], pd.Series), pd.Series) - check(assert_type(summer + summer, pd.Series), pd.Series) + check(assert_type(s + summer, pd.Series), pd.Series) # type: ignore[assert-type] + check(assert_type(s + df["y"], pd.Series), pd.Series) # type: ignore[assert-type] + check(assert_type(summer + summer, pd.Series), pd.Series) # type: ignore[assert-type] def test_getset_untyped() -> None: @@ -3469,6 +3466,7 @@ def test_groupby_apply() -> None: df = pd.DataFrame({"col1": [1, 2, 3], "col2": [4, 5, 6]}) def sum_mean(x: pd.DataFrame) -> float: + x.sum() return x.sum().mean() with pytest_warns_bounded( diff --git a/tests/test_pandas.py b/tests/test_pandas.py index 068254c3a..1807a3c50 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, ) @@ -36,18 +35,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, ) @@ -56,7 +56,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, @@ -92,7 +92,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 bfc78ae65..0a782ddbd 100644 --- a/tests/test_scalars.py +++ b/tests/test_scalars.py @@ -39,12 +39,10 @@ OffsetSeries, PeriodSeries, TimedeltaSeries, - TimestampSeries, ) else: TimedeltaSeries: TypeAlias = pd.Series - TimestampSeries: TypeAlias = pd.Series PeriodSeries: TypeAlias = pd.Series OffsetSeries: TypeAlias = pd.Series @@ -1215,10 +1213,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( @@ -1241,7 +1243,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]), @@ -1264,9 +1268,13 @@ def test_timestamp_cmp() -> None: # DatetimeIndex, but the type checker detects it to be UnknownIndex. c_unknown_index = pd.DataFrame({"a": [1]}, index=c_datetimeindex).index c_np_ndarray_dt64 = np_dt64_arr - c_series_dt64: TimestampSeries = pd.Series([1, 2, 3], dtype="datetime64[ns]") + c_series_dt64 = pd.Series([1, 2, 3], dtype="datetime64[ns]") c_series_timestamp = pd.Series(pd.DatetimeIndex(["2000-1-1"])) - check(assert_type(c_series_timestamp, TimestampSeries), pd.Series, pd.Timestamp) + check( + assert_type(c_series_timestamp, "pd.Series[pd.Timestamp]"), + pd.Series, + pd.Timestamp, + ) # Use xor to ensure one is True and the other is False # Correctness ensures since tested to be bools gt = check(assert_type(ts > c_timestamp, bool), bool) @@ -1725,7 +1733,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_series.py b/tests/test_series.py index 1e48aae75..f542c1bd2 100644 --- a/tests/test_series.py +++ b/tests/test_series.py @@ -68,7 +68,6 @@ from pandas.core.series import ( OffsetSeries, TimedeltaSeries, - TimestampSeries, ) from tests import ( @@ -89,7 +88,6 @@ else: TimedeltaSeries: TypeAlias = pd.Series - TimestampSeries: TypeAlias = pd.Series OffsetSeries: TypeAlias = pd.Series @@ -811,13 +809,11 @@ def test_types_element_wise_arithmetic() -> None: check(assert_type(s + s2, "pd.Series[int]"), pd.Series, np.integer) check(assert_type(s.add(s2, fill_value=0), "pd.Series[int]"), pd.Series, np.integer) - # TODO this one below should type pd.Series[int] - check(assert_type(s - s2, pd.Series), pd.Series, np.integer) + check(assert_type(s - s2, "pd.Series[int]"), pd.Series, np.integer) check(assert_type(s.sub(s2, fill_value=0), "pd.Series[int]"), pd.Series, np.integer) - # TODO these two below should type pd.Series[int] - # check(assert_type(s * s2, "pd.Series[int]"), pd.Series, np.integer ) - check(assert_type(s * s2, pd.Series), pd.Series, np.integer) + check(assert_type(s * s2, "pd.Series[int]"), pd.Series, np.integer) + # TODO this below should type pd.Series[int] # check(assert_type(s.mul(s2, fill_value=0), "pd.Series[int]"), pd.Series, np.integer) check(assert_type(s.mul(s2, fill_value=0), pd.Series), pd.Series, np.integer) @@ -1599,8 +1595,8 @@ def test_series_min_max_sub_axis() -> None: ss = s1 - s2 sm = s1 * s2 sd = s1 / s2 - check(assert_type(sa, pd.Series), pd.Series) - check(assert_type(ss, pd.Series), pd.Series) + check(assert_type(sa, pd.Series), pd.Series) # type: ignore[assert-type] + check(assert_type(ss, pd.Series), pd.Series) # type: ignore[assert-type] check(assert_type(sm, pd.Series), pd.Series) check(assert_type(sd, pd.Series), pd.Series) @@ -1636,11 +1632,11 @@ def test_series_multiindex_getitem() -> None: def test_series_mul() -> None: s = pd.Series([1, 2, 3]) sm = s * 4 - check(assert_type(sm, pd.Series), pd.Series) + check(assert_type(sm, "pd.Series[int]"), pd.Series, np.integer) ss = s - 4 - check(assert_type(ss, pd.Series), pd.Series) + check(assert_type(ss, "pd.Series[int]"), pd.Series, np.integer) sm2 = s * s - check(assert_type(sm2, pd.Series), pd.Series) + check(assert_type(sm2, "pd.Series[int]"), pd.Series, np.integer) sp = s + 4 check(assert_type(sp, "pd.Series[int]"), pd.Series, np.integer) @@ -2783,64 +2779,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, ) @@ -3355,7 +3351,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, ) @@ -3369,13 +3365,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, ) @@ -3905,7 +3901,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_timefuncs.py b/tests/test_timefuncs.py index 4843c5139..67de2b7ae 100644 --- a/tests/test_timefuncs.py +++ b/tests/test_timefuncs.py @@ -51,7 +51,6 @@ if TYPE_CHECKING: from pandas.core.series import PeriodSeries # noqa: F401 from pandas.core.series import TimedeltaSeries # noqa: F401 - from pandas.core.series import TimestampSeries # noqa: F401 from tests import np_ndarray_bool @@ -125,7 +124,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_) @@ -216,7 +215,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, @@ -225,13 +224,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, ) @@ -251,7 +250,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, @@ -260,7 +259,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, ) @@ -277,7 +276,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, @@ -285,9 +284,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: @@ -321,9 +320,9 @@ def test_fail_on_adding_two_timestamps() -> None: s1 = pd.Series(pd.to_datetime(["2022-05-01", "2022-06-01"])) s2 = pd.Series(pd.to_datetime(["2022-05-15", "2022-06-15"])) if TYPE_CHECKING_INVALID_USAGE: - ssum: pd.Series = s1 + s2 # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + ssum = s1 + s2 # type: ignore[var-annotated] ts = pd.Timestamp("2022-06-30") - tsum: pd.Series = s1 + ts # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + tsum = s1 + ts # type: ignore[var-annotated] def test_dtindex_tzinfo() -> None: @@ -378,7 +377,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) @@ -425,94 +426,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) @@ -523,8 +555,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) @@ -551,18 +589,31 @@ def test_series_dt_accessors() -> None: 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) - # 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.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]", @@ -570,10 +621,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]"), # type: ignore[assert-type] + pd.Series, + pd.Timedelta, + ) + check( + assert_type(s5.dt.as_unit("ms"), "pd.Series[pd.Timedelta]"), # type: ignore[assert-type] + pd.Series, + pd.Timedelta, + ) + check( + assert_type(s5.dt.as_unit("us"), "pd.Series[pd.Timedelta]"), # type: ignore[assert-type] + pd.Series, + pd.Timedelta, + ) + check( + assert_type(s5.dt.as_unit("ns"), "pd.Series[pd.Timedelta]"), # type: ignore[assert-type] + pd.Series, + pd.Timedelta, + ) def test_datetimeindex_accessors() -> None: @@ -1068,7 +1135,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], @@ -1089,9 +1156,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: @@ -1334,19 +1401,19 @@ def test_timedelta64_and_arithmatic_operator() -> None: s3 = s2 - s1 check(assert_type(s3, "TimedeltaSeries"), 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) if TYPE_CHECKING_INVALID_USAGE: - r1 = s1 * td # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + r1 = s1 * td # type: ignore[var-annotated] r2 = s1 / td # type: ignore[operator] # pyright: ignore[reportOperatorIssue] r3 = s3 * td # type: ignore[operator] # pyright: ignore[reportOperatorIssue] @@ -1355,7 +1422,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: From 3df8ea0df3bc46284ed36d05c0c9ef909f7611e6 Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Sat, 12 Jul 2025 23:25:32 +0200 Subject: [PATCH 02/13] refactor: also remove TimedeltaSeries --- docs/philosophy.md | 4 +- pandas-stubs/_libs/interval.pyi | 7 +- pandas-stubs/_libs/tslibs/period.pyi | 7 +- pandas-stubs/_libs/tslibs/timedeltas.pyi | 48 +++--- pandas-stubs/_libs/tslibs/timestamps.pyi | 11 +- pandas-stubs/core/indexes/accessors.pyi | 9 +- pandas-stubs/core/indexes/datetimes.pyi | 9 +- pandas-stubs/core/indexes/interval.pyi | 5 +- pandas-stubs/core/indexes/timedeltas.pyi | 4 +- pandas-stubs/core/series.pyi | 209 ++++++----------------- pandas-stubs/core/tools/timedeltas.pyi | 7 +- tests/test_scalars.py | 84 +++++++-- tests/test_series.py | 147 ++++++++-------- tests/test_timefuncs.py | 129 ++++++-------- 14 files changed, 293 insertions(+), 387 deletions(-) diff --git a/docs/philosophy.md b/docs/philosophy.md index c19f1e1b9..e9d58f5e4 100644 --- a/docs/philosophy.md +++ b/docs/philosophy.md @@ -56,13 +56,13 @@ revealed as follows: ```text ttest.py:4: note: Revealed type is "pandas.core.series.Series[pandas._libs.tslibs.timestamps.Timestamp]" ttest.py:6: note: Revealed type is "pandas.core.series.Series[pandas._libs.tslibs.timestamps.Timestamp]" -ttest.py:8: note: Revealed type is "pandas.core.series.TimedeltaSeries" +ttest.py:8: note: Revealed type is "pandas.core.series.Series[pandas._libs.tslibs.timedeltas.Timedelta]" ttest.py:9: error: Need type annotation for "ssum" [var-annotated] ttest.py:10: note: Revealed type is "Never" ``` 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 type `Series[Timedelta]` 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 613eb06ba..ad1327bad 100644 --- a/pandas-stubs/_libs/interval.pyi +++ b/pandas-stubs/_libs/interval.pyi @@ -13,7 +13,6 @@ from pandas import ( Timedelta, Timestamp, ) -from pandas.core.series import TimedeltaSeries from pandas._typing import ( IntervalClosedType, @@ -171,7 +170,7 @@ class Interval(IntervalMixin, Generic[_OrderableT]): @overload def __gt__( self, - other: Series[int] | Series[float] | Series[Timestamp] | TimedeltaSeries, + other: Series[int] | Series[float] | Series[Timestamp] | Series[Timedelta], ) -> Series[bool]: ... @overload def __lt__(self, other: Interval[_OrderableT]) -> bool: ... @@ -180,7 +179,7 @@ class Interval(IntervalMixin, Generic[_OrderableT]): @overload def __lt__( self, - other: Series[int] | Series[float] | Series[Timestamp] | TimedeltaSeries, + other: Series[int] | Series[float] | Series[Timestamp] | Series[Timedelta], ) -> Series[bool]: ... @overload def __ge__(self, other: Interval[_OrderableT]) -> bool: ... @@ -189,7 +188,7 @@ class Interval(IntervalMixin, Generic[_OrderableT]): @overload def __ge__( self, - other: Series[int] | Series[float] | Series[Timestamp] | TimedeltaSeries, + other: Series[int] | Series[float] | Series[Timestamp] | Series[Timedelta], ) -> Series[bool]: ... @overload def __le__(self, other: Interval[_OrderableT]) -> bool: ... diff --git a/pandas-stubs/_libs/tslibs/period.pyi b/pandas-stubs/_libs/tslibs/period.pyi index cf93f3664..353c4083a 100644 --- a/pandas-stubs/_libs/tslibs/period.pyi +++ b/pandas-stubs/_libs/tslibs/period.pyi @@ -15,7 +15,6 @@ from pandas import ( from pandas.core.series import ( OffsetSeries, PeriodSeries, - TimedeltaSeries, ) from typing_extensions import TypeAlias @@ -82,7 +81,7 @@ class Period(PeriodMixin): @overload def __sub__(self, other: PeriodIndex) -> Index: ... @overload - def __sub__(self, other: TimedeltaSeries) -> PeriodSeries: ... + def __sub__(self, other: Series[Timedelta]) -> PeriodSeries: ... @overload def __sub__(self, other: TimedeltaIndex) -> PeriodIndex: ... @overload @@ -92,7 +91,7 @@ class Period(PeriodMixin): @overload def __add__(self, other: Index) -> PeriodIndex: ... @overload - def __add__(self, other: OffsetSeries | TimedeltaSeries) -> PeriodSeries: ... + def __add__(self, other: OffsetSeries | Series[Timedelta]) -> PeriodSeries: ... # ignore[misc] here because we know all other comparisons # are False, so we use Literal[False] @overload @@ -148,7 +147,7 @@ class Period(PeriodMixin): @overload def __radd__(self, other: Index) -> Index: ... @overload - def __radd__(self, other: TimedeltaSeries) -> PeriodSeries: ... + def __radd__(self, other: Series[Timedelta]) -> PeriodSeries: ... @overload def __radd__(self, other: NaTType) -> NaTType: ... @property diff --git a/pandas-stubs/_libs/tslibs/timedeltas.pyi b/pandas-stubs/_libs/tslibs/timedeltas.pyi index 798b87a9d..d43b5fba3 100644 --- a/pandas-stubs/_libs/tslibs/timedeltas.pyi +++ b/pandas-stubs/_libs/tslibs/timedeltas.pyi @@ -17,7 +17,6 @@ from pandas import ( Series, TimedeltaIndex, ) -from pandas.core.series import TimedeltaSeries from typing_extensions import ( Self, TypeAlias, @@ -159,10 +158,7 @@ class Timedelta(timedelta): @overload def __add__(self, other: pd.TimedeltaIndex) -> pd.TimedeltaIndex: ... @overload - def __add__( - self, - other: TimedeltaSeries, - ) -> TimedeltaSeries: ... + def __add__(self, other: Series[Timedelta]) -> Series[Timedelta]: ... @overload def __add__(self, other: Series[Timestamp]) -> Series[Timestamp]: ... @overload @@ -195,9 +191,7 @@ class Timedelta(timedelta): @overload def __sub__(self, other: pd.TimedeltaIndex) -> TimedeltaIndex: ... @overload - def __sub__( - self, other: TimedeltaSeries | Series[pd.Timedelta] - ) -> TimedeltaSeries: ... + def __sub__(self, other: Series[pd.Timedelta]) -> Series[pd.Timedelta]: ... @overload def __rsub__(self, other: timedelta | Timedelta | np.timedelta64) -> Timedelta: ... @overload @@ -231,9 +225,9 @@ class Timedelta(timedelta): self, other: npt.NDArray[np.integer] | npt.NDArray[np.floating] ) -> npt.NDArray[np.timedelta64]: ... @overload - def __mul__(self, other: Series[int]) -> TimedeltaSeries: ... + def __mul__(self, other: Series[int]) -> Series[Timedelta]: ... @overload - def __mul__(self, other: Series[float]) -> TimedeltaSeries: ... + def __mul__(self, other: Series[float]) -> Series[Timedelta]: ... @overload def __mul__(self, other: Index[int] | Index[float]) -> TimedeltaIndex: ... @overload @@ -243,9 +237,9 @@ class Timedelta(timedelta): self, other: npt.NDArray[np.floating] | npt.NDArray[np.integer] ) -> npt.NDArray[np.timedelta64]: ... @overload - def __rmul__(self, other: Series[int]) -> TimedeltaSeries: ... + def __rmul__(self, other: Series[int]) -> Series[Timedelta]: ... @overload - def __rmul__(self, other: Series[float]) -> TimedeltaSeries: ... + def __rmul__(self, other: Series[float]) -> Series[Timedelta]: ... # maybe related to https://github.com/python/mypy/issues/10755 @overload def __rmul__(self, other: Index[int] | Index[float]) -> TimedeltaIndex: ... @@ -266,11 +260,11 @@ class Timedelta(timedelta): @overload def __floordiv__(self, other: Index[int] | Index[float]) -> TimedeltaIndex: ... @overload - def __floordiv__(self, other: Series[int]) -> TimedeltaSeries: ... + def __floordiv__(self, other: Series[int]) -> Series[Timedelta]: ... @overload - def __floordiv__(self, other: Series[float]) -> TimedeltaSeries: ... + def __floordiv__(self, other: Series[float]) -> Series[Timedelta]: ... @overload - def __floordiv__(self, other: TimedeltaSeries) -> Series[int]: ... + def __floordiv__(self, other: Series[Timedelta]) -> Series[int]: ... @overload def __floordiv__(self, other: NaTType | None) -> float: ... @overload @@ -291,11 +285,11 @@ class Timedelta(timedelta): self, other: npt.NDArray[np.integer] | npt.NDArray[np.floating] ) -> npt.NDArray[np.timedelta64]: ... @overload - def __truediv__(self, other: TimedeltaSeries) -> Series[float]: ... + def __truediv__(self, other: Series[Timedelta]) -> Series[float]: ... @overload - def __truediv__(self, other: Series[int]) -> TimedeltaSeries: ... + def __truediv__(self, other: Series[int]) -> Series[Timedelta]: ... @overload - def __truediv__(self, other: Series[float]) -> TimedeltaSeries: ... + def __truediv__(self, other: Series[float]) -> Series[Timedelta]: ... @overload def __truediv__(self, other: Index[int] | Index[float]) -> TimedeltaIndex: ... def __rtruediv__(self, other: timedelta | Timedelta | NaTType) -> float: ... @@ -303,7 +297,7 @@ class Timedelta(timedelta): @overload def __eq__(self, other: timedelta | Timedelta | np.timedelta64) -> bool: ... # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload] @overload - def __eq__(self, other: TimedeltaSeries | Series[pd.Timedelta]) -> Series[bool]: ... # type: ignore[overload-overlap] + def __eq__(self, other: Series[Timedelta]) -> Series[bool]: ... # type: ignore[overload-overlap] @overload def __eq__( # type: ignore[overload-overlap] self, other: TimedeltaIndex | npt.NDArray[np.timedelta64] @@ -314,7 +308,7 @@ class Timedelta(timedelta): @overload def __ne__(self, other: timedelta | Timedelta | np.timedelta64) -> bool: ... # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload] @overload - def __ne__(self, other: TimedeltaSeries | Series[pd.Timedelta]) -> Series[bool]: ... # type: ignore[overload-overlap] + def __ne__(self, other: Series[pd.Timedelta]) -> Series[bool]: ... # type: ignore[overload-overlap] @overload def __ne__( # type: ignore[overload-overlap] self, other: TimedeltaIndex | npt.NDArray[np.timedelta64] @@ -327,7 +321,7 @@ class Timedelta(timedelta): @overload def __mod__(self, other: float) -> Timedelta: ... @overload - def __mod__(self, other: Series[int] | Series[float]) -> TimedeltaSeries: ... + def __mod__(self, other: Series[int] | Series[float]) -> Series[Timedelta]: ... @overload def __mod__(self, other: Index[int] | Index[float]) -> TimedeltaIndex: ... @overload @@ -336,8 +330,8 @@ class Timedelta(timedelta): ) -> npt.NDArray[np.timedelta64]: ... @overload def __mod__( - self, other: Series[int] | Series[float] | TimedeltaSeries - ) -> TimedeltaSeries: ... + self, other: Series[int] | Series[float] | Series[Timedelta] + ) -> Series[Timedelta]: ... def __divmod__(self, other: timedelta) -> tuple[int, Timedelta]: ... # Mypy complains Forward operator "" is not callable, so ignore misc # for le, lt ge and gt @@ -349,7 +343,7 @@ class Timedelta(timedelta): self, other: TimedeltaIndex | npt.NDArray[np.timedelta64] ) -> npt.NDArray[np.bool_]: ... @overload - def __le__(self, other: TimedeltaSeries | Series[pd.Timedelta]) -> Series[bool]: ... + def __le__(self, other: Series[pd.Timedelta]) -> Series[bool]: ... # Override due to more types supported than dt.timedelta @overload # type: ignore[override] def __lt__(self, other: timedelta | Timedelta | np.timedelta64) -> bool: ... # type: ignore[misc] @@ -358,7 +352,7 @@ class Timedelta(timedelta): self, other: TimedeltaIndex | npt.NDArray[np.timedelta64] ) -> npt.NDArray[np.bool_]: ... @overload - def __lt__(self, other: TimedeltaSeries | Series[pd.Timedelta]) -> Series[bool]: ... + def __lt__(self, other: Series[pd.Timedelta]) -> Series[bool]: ... # Override due to more types supported than dt.timedelta @overload # type: ignore[override] def __ge__(self, other: timedelta | Timedelta | np.timedelta64) -> bool: ... # type: ignore[misc] @@ -367,7 +361,7 @@ class Timedelta(timedelta): self, other: TimedeltaIndex | npt.NDArray[np.timedelta64] ) -> npt.NDArray[np.bool_]: ... @overload - def __ge__(self, other: TimedeltaSeries | Series[pd.Timedelta]) -> Series[bool]: ... + def __ge__(self, other: Series[pd.Timedelta]) -> Series[bool]: ... # Override due to more types supported than dt.timedelta @overload # type: ignore[override] def __gt__(self, other: timedelta | Timedelta | np.timedelta64) -> bool: ... # type: ignore[misc] @@ -376,7 +370,7 @@ class Timedelta(timedelta): self, other: TimedeltaIndex | npt.NDArray[np.timedelta64] ) -> npt.NDArray[np.bool_]: ... @overload - def __gt__(self, other: TimedeltaSeries | Series[pd.Timedelta]) -> Series[bool]: ... + def __gt__(self, other: Series[pd.Timedelta]) -> Series[bool]: ... def __hash__(self) -> int: ... def isoformat(self) -> str: ... def to_numpy(self) -> np.timedelta64: ... diff --git a/pandas-stubs/_libs/tslibs/timestamps.pyi b/pandas-stubs/_libs/tslibs/timestamps.pyi index 3b991d7ef..e0b113cd6 100644 --- a/pandas-stubs/_libs/tslibs/timestamps.pyi +++ b/pandas-stubs/_libs/tslibs/timestamps.pyi @@ -22,10 +22,7 @@ from pandas import ( Index, TimedeltaIndex, ) -from pandas.core.series import ( - Series, - TimedeltaSeries, -) +from pandas.core.series import Series from typing_extensions import ( Never, Self, @@ -204,7 +201,7 @@ class Timestamp(datetime, SupportsIndex): @overload def __add__(self, other: timedelta | np.timedelta64 | Tick) -> Self: ... @overload - def __add__(self, other: TimedeltaSeries) -> Series[Timestamp]: ... + def __add__(self, other: Series[Timedelta]) -> Series[Timestamp]: ... @overload def __add__(self, other: TimedeltaIndex) -> DatetimeIndex: ... @overload @@ -223,9 +220,9 @@ class Timestamp(datetime, SupportsIndex): @overload def __sub__(self, other: TimedeltaIndex) -> DatetimeIndex: ... @overload - def __sub__(self, other: TimedeltaSeries) -> Series[Timestamp]: ... + def __sub__(self, other: Series[Timedelta]) -> Series[Timestamp]: ... @overload - def __sub__(self, other: Series[Timestamp]) -> TimedeltaSeries: ... + def __sub__(self, other: Series[Timestamp]) -> Series[Timedelta]: ... @overload def __sub__( self, other: npt.NDArray[np.timedelta64] diff --git a/pandas-stubs/core/indexes/accessors.pyi b/pandas-stubs/core/indexes/accessors.pyi index 70ce8e090..87dbf510f 100644 --- a/pandas-stubs/core/indexes/accessors.pyi +++ b/pandas-stubs/core/indexes/accessors.pyi @@ -31,7 +31,6 @@ from pandas.core.frame import DataFrame from pandas.core.series import ( PeriodSeries, Series, - TimedeltaSeries, ) from typing_extensions import Never @@ -316,11 +315,11 @@ class _TimedeltaPropertiesNoRounding( class TimedeltaProperties( Properties, _TimedeltaPropertiesNoRounding[Series[int], Series[float]], - _DatetimeRoundingMethods[TimedeltaSeries], + _DatetimeRoundingMethods[Series[Timedelta]], ): @property def unit(self) -> TimeUnit: ... - def as_unit(self, unit: TimeUnit) -> TimedeltaSeries: ... + def as_unit(self, unit: TimeUnit) -> Series[Timedelta]: ... _PeriodDTReturnTypes = TypeVar( "_PeriodDTReturnTypes", bound=Series[Timestamp] | DatetimeIndex @@ -439,6 +438,10 @@ class _dtDescriptor(CombinedDatetimelikeProperties, Generic[S1]): 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: ... diff --git a/pandas-stubs/core/indexes/datetimes.pyi b/pandas-stubs/core/indexes/datetimes.pyi index 589390856..798f747d2 100644 --- a/pandas-stubs/core/indexes/datetimes.pyi +++ b/pandas-stubs/core/indexes/datetimes.pyi @@ -22,10 +22,7 @@ from pandas import ( ) from pandas.core.indexes.accessors import DatetimeIndexProperties from pandas.core.indexes.datetimelike import DatetimeTimedeltaMixin -from pandas.core.series import ( - Series, - TimedeltaSeries, -) +from pandas.core.series import Series from typing_extensions import Self from pandas._typing import ( @@ -60,13 +57,13 @@ class DatetimeIndex(DatetimeTimedeltaMixin[Timestamp], DatetimeIndexProperties): # 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) -> Series[Timestamp]: ... + def __add__(self, other: Series[Timedelta]) -> Series[Timestamp]: ... @overload def __add__( self, other: timedelta | Timedelta | TimedeltaIndex | BaseOffset ) -> DatetimeIndex: ... @overload - def __sub__(self, other: TimedeltaSeries) -> Series[Timestamp]: ... + def __sub__(self, other: Series[Timedelta]) -> Series[Timestamp]: ... @overload def __sub__( self, other: timedelta | Timedelta | TimedeltaIndex | BaseOffset diff --git a/pandas-stubs/core/indexes/interval.pyi b/pandas-stubs/core/indexes/interval.pyi index cc53b668c..1aa315610 100644 --- a/pandas-stubs/core/indexes/interval.pyi +++ b/pandas-stubs/core/indexes/interval.pyi @@ -13,9 +13,6 @@ import numpy as np import pandas as pd from pandas import Index from pandas.core.indexes.extension import ExtensionIndex -from pandas.core.series import ( - TimedeltaSeries, -) from typing_extensions import TypeAlias from pandas._libs.interval import ( @@ -58,7 +55,7 @@ _EdgesTimestamp: TypeAlias = ( _EdgesTimedelta: TypeAlias = ( Sequence[pd.Timedelta] | npt.NDArray[np.timedelta64] - | TimedeltaSeries + | pd.Series[pd.Timedelta] | pd.TimedeltaIndex ) _TimestampLike: TypeAlias = pd.Timestamp | np.datetime64 | dt.datetime diff --git a/pandas-stubs/core/indexes/timedeltas.pyi b/pandas-stubs/core/indexes/timedeltas.pyi index 6d50cdbd2..e14d84db5 100644 --- a/pandas-stubs/core/indexes/timedeltas.pyi +++ b/pandas-stubs/core/indexes/timedeltas.pyi @@ -19,7 +19,7 @@ from pandas.core.indexes.accessors import TimedeltaIndexProperties from pandas.core.indexes.datetimelike import DatetimeTimedeltaMixin from pandas.core.indexes.datetimes import DatetimeIndex from pandas.core.indexes.period import PeriodIndex -from pandas.core.series import TimedeltaSeries +from pandas.core.series import Series from typing_extensions import Self from pandas._libs import ( @@ -75,7 +75,7 @@ class TimedeltaIndex(DatetimeTimedeltaMixin[Timedelta], TimedeltaIndexProperties @property def inferred_type(self) -> str: ... @final - def to_series(self, index=..., name: Hashable = ...) -> TimedeltaSeries: ... + def to_series(self, index=..., name: Hashable = ...) -> Series[Timedelta]: ... def shift(self, periods: int = ..., freq=...) -> Self: ... def timedelta_range( diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index 68e9fccb0..7729fddf0 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -61,7 +61,6 @@ from pandas.core.groupby.groupby import BaseGroupBy from pandas.core.indexers import BaseIndexer from pandas.core.indexes.accessors import ( PeriodProperties, - TimedeltaProperties, _dtDescriptor, ) from pandas.core.indexes.category import CategoricalIndex @@ -175,6 +174,7 @@ from pandas._typing import ( VoidDtypeArg, WriteBuffer, np_ndarray_anyint, + np_ndarray_float, npt, num, ) @@ -206,7 +206,7 @@ _vector_timedelta: TypeAlias = ( | TimedeltaIndex ) _nonseries_timedelta: TypeAlias = _scalar_timedelta | _vector_timedelta -_T_TIMESTAMP = TypeVar("_T_TIMESTAMP", bound=Timestamp) +_T_STAMP_AND_DELTA = TypeVar("_T_STAMP_AND_DELTA", bound=Timestamp | Timedelta) class _iLocIndexerSeries(_iLocIndexer, Generic[S1]): # get item @@ -359,7 +359,7 @@ class Series(IndexOpsMixin[S1], NDFrame): dtype: TimedeltaDtypeArg = ..., name: Hashable = ..., copy: bool = ..., - ) -> TimedeltaSeries: ... + ) -> Series[Timedelta]: ... @overload def __new__( cls, @@ -840,7 +840,7 @@ 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] + def diff(self: Series[_T_STAMP_AND_DELTA], periods: int = ...) -> Series[Timedelta]: ... # type: ignore[overload-overlap] @overload def diff(self, periods: int = ...) -> Series[float]: ... def autocorr(self, lag: int = ...) -> float: ... @@ -1337,7 +1337,7 @@ class Series(IndexOpsMixin[S1], NDFrame): dtype: TimedeltaDtypeArg, copy: _bool = ..., errors: IgnoreRaise = ..., - ) -> TimedeltaSeries: ... + ) -> Series[Timedelta]: ... @overload def astype( self, @@ -1656,9 +1656,9 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Never: ... @overload def __add__( - self: Series[Timestamp], - other: _nonseries_timedelta | Series[Timedelta] | TimedeltaSeries, - ) -> Series[Timestamp]: ... + self: Series[_T_STAMP_AND_DELTA], + other: _nonseries_timedelta | Series[Timedelta], + ) -> Series[_T_STAMP_AND_DELTA]: ... @overload def __add__(self: Series[Timedelta], other: Period) -> PeriodSeries: ... @overload @@ -1685,7 +1685,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def __floordiv__( self: Series[Timedelta], other: float | Sequence[float] - ) -> TimedeltaSeries: ... + ) -> Series[Timedelta]: ... @overload def __floordiv__( self: Series[Timedelta], @@ -1715,19 +1715,23 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Series[_T_COMPLEX]: ... @overload def __mul__( - self: Series[Timestamp], + self: Series[_T_STAMP_AND_DELTA], other: ( - num | Sequence[num] | Series[int] | Series[float] | float | Sequence[float] + _T_FLOAT + | Sequence[_T_FLOAT] + | np_ndarray_anyint + | np_ndarray_float + | Series[_T_FLOAT] ), - ) -> Series[Timestamp]: ... + ) -> Series[_T_STAMP_AND_DELTA]: ... @overload def __mul__( - self: Series[Timestamp], other: _nonseries_timedelta | TimedeltaSeries + self: Series[Timestamp], other: _nonseries_timedelta | Series[Timedelta] ) -> Never: ... @overload def __mul__( - self: Series[_T_FLOAT], other: _nonseries_timedelta | TimedeltaSeries - ) -> TimedeltaSeries: ... + self: Series[_T_FLOAT], other: _nonseries_timedelta | Series[Timedelta] + ) -> Series[Timedelta]: ... @overload def __mul__(self, other: num | _ListLike | Series) -> Series: ... def __mod__(self, other: num | _ListLike | Series[S1]) -> Series[S1]: ... @@ -1746,11 +1750,11 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Series: ... @overload def __radd__( - self: Series[Timestamp], other: _nonseries_timedelta | Series[Timedelta] + self: Series[Timestamp], other: _nonseries_timedelta ) -> Series[Timestamp]: ... @overload def __radd__( - self: Series[Timedelta], other: datetime | Timestamp | Series[Timestamp] + self: Series[Timedelta], other: _nonseries_timestamp ) -> Series[Timestamp]: ... @overload def __radd__(self, other: S1 | Series[S1]) -> Self: ... @@ -1774,8 +1778,8 @@ class Series(IndexOpsMixin[S1], NDFrame): def __rmod__(self, other: num | _ListLike | Series[S1]) -> Series[S1]: ... @overload def __rmul__( - self, other: timedelta | Timedelta | TimedeltaSeries | np.timedelta64 - ) -> TimedeltaSeries: ... + self, other: timedelta | Timedelta | Series[Timedelta] | np.timedelta64 + ) -> Series[Timedelta]: ... @overload def __rmul__(self, other: num | _ListLike | Series) -> Series: ... def __rnatmul__(self, other: num | _ListLike | Series[S1]) -> Series[S1]: ... @@ -1805,12 +1809,16 @@ class Series(IndexOpsMixin[S1], NDFrame): def __sub__(self: Series[Never], other: num | _ListLike | Series) -> Series: ... @overload def __sub__( - self: Series[Timestamp], other: _nonseries_timedelta | TimedeltaSeries + self: Series[Timestamp], other: _nonseries_timedelta | Series[Timedelta] ) -> Series[Timestamp]: ... @overload def __sub__( - self: Series[Timestamp], other: _nonseries_timestamp | Series[_T_TIMESTAMP] - ) -> TimedeltaSeries: ... + self: Series[Timestamp], other: _nonseries_timestamp | Series[Timestamp] + ) -> Series[Timedelta]: ... + @overload + def __sub__( + self: Series[Timedelta], other: _nonseries_timedelta | Series[Timedelta] + ) -> Series[Timedelta]: ... @overload def __sub__(self, other: S1 | Self) -> Self: ... @overload @@ -1821,9 +1829,15 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Series: ... @overload def __truediv__( - self: Series[Timestamp], - other: float | Series[int] | Series[float] | Sequence[float], - ) -> Series[Timestamp]: ... + self: Series[_T_STAMP_AND_DELTA], + other: ( + _T_FLOAT + | Sequence[_T_FLOAT] + | np_ndarray_anyint + | np_ndarray_float + | Series[_T_FLOAT] + ), + ) -> Series[_T_STAMP_AND_DELTA]: ... @overload def __truediv__( self: Series[Timedelta], other: _nonseries_timedelta | Series[Timedelta] @@ -1899,7 +1913,7 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Never: ... @overload def cumprod( - self: Series[Timestamp], + self: Series[_T_STAMP_AND_DELTA], axis: AxisIndex = ..., skipna: _bool = ..., *args: Any, @@ -2021,22 +2035,13 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> S1: ... @overload def mean( - self: Series[Never], - axis: AxisIndex | None = ..., - skipna: _bool = ..., - level: None = ..., - numeric_only: _bool = ..., - **kwargs: Any, - ) -> float: ... - @overload - def mean( - self: Series[Timestamp], + self: Series[_T_STAMP_AND_DELTA], axis: AxisIndex | None = ..., skipna: _bool = ..., level: None = ..., numeric_only: _bool = ..., **kwargs: Any, - ) -> Timestamp: ... + ) -> _T_STAMP_AND_DELTA: ... @overload def mean( self, @@ -2072,11 +2077,19 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def mul( self, - other: timedelta | Timedelta | TimedeltaSeries | np.timedelta64, + other: timedelta | Timedelta | Series[Timedelta] | np.timedelta64, level: Level | None = ..., fill_value: float | None = ..., axis: AxisIndex | None = ..., - ) -> TimedeltaSeries: ... + ) -> Series[Timedelta]: ... + @overload + def mul( + self: Series[int], + other: int | Series[int], + level: Level | None = ..., + fill_value: int | None = ..., + axis: AxisIndex | None = ..., + ) -> Series[int]: ... @overload def mul( self, @@ -2157,11 +2170,11 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def rmul( self, - other: timedelta | Timedelta | TimedeltaSeries | np.timedelta64, + other: timedelta | Timedelta | Series[Timedelta] | np.timedelta64, level: Level | None = ..., fill_value: float | None = ..., axis: AxisIndex = ..., - ) -> TimedeltaSeries: ... + ) -> Series[Timedelta]: ... @overload def rmul( self, @@ -2236,7 +2249,7 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Scalar: ... @overload def std( - self: Series[Timestamp], + self: Series[_T_STAMP_AND_DELTA], axis: AxisIndex | None = ..., skipna: _bool | None = ..., level: None = ..., @@ -2378,118 +2391,6 @@ class Series(IndexOpsMixin[S1], NDFrame): @final def __bool__(self) -> NoReturn: ... -class TimedeltaSeries(Series[Timedelta]): - # ignores needed because of mypy - @overload # type: ignore[override] - def __add__(self, other: Period) -> PeriodSeries: ... - @overload - def __add__( - self, other: datetime | Timestamp | Series[Timestamp] | DatetimeIndex - ) -> Series[Timestamp]: ... - @overload - def __add__( # pyright: ignore[reportIncompatibleMethodOverride] - self, other: timedelta | Timedelta | np.timedelta64 - ) -> TimedeltaSeries: ... - def __radd__(self, other: datetime | Timestamp | 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 - ), - ) -> TimedeltaSeries: ... - @overload # type: ignore[override] - def __truediv__(self, other: float | Sequence[float]) -> Self: ... - @overload - def __truediv__( # pyright: ignore[reportIncompatibleMethodOverride] - self, - other: ( - timedelta - | TimedeltaSeries - | np.timedelta64 - | TimedeltaIndex - | Sequence[timedelta] - ), - ) -> Series[float]: ... - def __rtruediv__( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] - self, - other: ( - timedelta - | TimedeltaSeries - | np.timedelta64 - | TimedeltaIndex - | Sequence[timedelta] - ), - ) -> Series[float]: ... - @overload # type: ignore[override] - def __floordiv__(self, other: float | Sequence[float]) -> Self: ... - @overload - def __floordiv__( # pyright: ignore[reportIncompatibleMethodOverride] - self, - other: ( - timedelta - | TimedeltaSeries - | np.timedelta64 - | TimedeltaIndex - | Sequence[timedelta] - ), - ) -> Series[int]: ... - def __rfloordiv__( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] - self, - other: ( - timedelta - | TimedeltaSeries - | np.timedelta64 - | TimedeltaIndex - | Sequence[timedelta] - ), - ) -> Series[int]: ... - @property - def dt(self) -> TimedeltaProperties: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] - def mean( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] - self, - axis: AxisIndex | None = ..., - skipna: _bool = ..., - level: None = ..., - numeric_only: _bool = ..., - **kwargs: Any, - ) -> Timedelta: ... - def median( - self, - axis: AxisIndex | None = ..., - skipna: _bool = ..., - level: None = ..., - numeric_only: _bool = ..., - **kwargs: Any, - ) -> Timedelta: ... - def std( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] - self, - axis: AxisIndex | None = ..., - skipna: _bool | None = ..., - level: None = ..., - ddof: int = ..., - numeric_only: _bool = ..., - **kwargs: Any, - ) -> Timedelta: ... - def diff(self, periods: int = ...) -> TimedeltaSeries: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] - def cumsum( - self, - axis: AxisIndex | None = ..., - skipna: _bool = ..., - *args: Any, - **kwargs: Any, - ) -> TimedeltaSeries: ... - def cumprod( # pyrefly: ignore - self, - axis: AxisIndex = ..., - skipna: _bool = ..., - *args: Any, - **kwargs: Any, - ) -> Never: ... - class PeriodSeries(Series[Period]): @property def dt(self) -> PeriodProperties: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] diff --git a/pandas-stubs/core/tools/timedeltas.pyi b/pandas-stubs/core/tools/timedeltas.pyi index 38ed0c074..3057ce808 100644 --- a/pandas-stubs/core/tools/timedeltas.pyi +++ b/pandas-stubs/core/tools/timedeltas.pyi @@ -4,10 +4,7 @@ from typing import overload from pandas import Index from pandas.core.indexes.timedeltas import TimedeltaIndex -from pandas.core.series import ( - Series, - TimedeltaSeries, -) +from pandas.core.series import Series from pandas._libs.tslibs import Timedelta from pandas._libs.tslibs.timedeltas import TimeDeltaUnitChoices @@ -28,7 +25,7 @@ def to_timedelta( arg: Series, unit: TimeDeltaUnitChoices | None = ..., errors: RaiseCoerce = ..., -) -> TimedeltaSeries: ... +) -> Series[Timedelta]: ... @overload def to_timedelta( arg: ( diff --git a/tests/test_scalars.py b/tests/test_scalars.py index 0a782ddbd..126e378ad 100644 --- a/tests/test_scalars.py +++ b/tests/test_scalars.py @@ -38,11 +38,9 @@ from pandas.core.series import ( OffsetSeries, PeriodSeries, - TimedeltaSeries, ) else: - TimedeltaSeries: TypeAlias = pd.Series PeriodSeries: TypeAlias = pd.Series OffsetSeries: TypeAlias = pd.Series @@ -545,7 +543,9 @@ def test_timedelta_add_sub() -> None: check(assert_type(td + as_timedelta64, pd.Timedelta), pd.Timedelta) check(assert_type(td + as_timedelta_index, pd.TimedeltaIndex), pd.TimedeltaIndex) check( - assert_type(td + as_timedelta_series, TimedeltaSeries), pd.Series, pd.Timedelta + assert_type(td + as_timedelta_series, "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, ) check(assert_type(td + as_period_index, pd.PeriodIndex), pd.PeriodIndex) check(assert_type(td + as_datetime_index, pd.DatetimeIndex), pd.DatetimeIndex) @@ -585,7 +585,9 @@ def test_timedelta_add_sub() -> None: ) check(assert_type(as_timedelta_index + td, pd.TimedeltaIndex), pd.TimedeltaIndex) check( - assert_type(as_timedelta_series + td, TimedeltaSeries), pd.Series, pd.Timedelta + assert_type(as_timedelta_series + td, "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, ) check(assert_type(as_period_index + td, pd.PeriodIndex), pd.PeriodIndex) check(assert_type(as_datetime_index + td, pd.DatetimeIndex), pd.DatetimeIndex) @@ -618,7 +620,9 @@ def test_timedelta_add_sub() -> None: check(assert_type(td - as_timedelta64, pd.Timedelta), pd.Timedelta) check(assert_type(td - as_timedelta_index, pd.TimedeltaIndex), pd.TimedeltaIndex) check( - assert_type(td - as_timedelta_series, TimedeltaSeries), pd.Series, pd.Timedelta + assert_type(td - as_timedelta_series, "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, ) check( assert_type(td - as_ndarray_td64, npt.NDArray[np.timedelta64]), @@ -650,7 +654,9 @@ def test_timedelta_add_sub() -> None: ) check(assert_type(as_timedelta_index - td, pd.TimedeltaIndex), pd.TimedeltaIndex) check( - assert_type(as_timedelta_series - td, TimedeltaSeries), pd.Series, pd.Timedelta + assert_type(as_timedelta_series - td, "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, ) check(assert_type(as_period_index - td, pd.PeriodIndex), pd.PeriodIndex) check(assert_type(as_datetime_index - td, pd.DatetimeIndex), pd.DatetimeIndex) @@ -704,8 +710,16 @@ def test_timedelta_mul_div() -> None: np.ndarray, np.timedelta64, ) - check(assert_type(td * mp_series_int, TimedeltaSeries), pd.Series, pd.Timedelta) - check(assert_type(td * md_series_float, TimedeltaSeries), pd.Series, pd.Timedelta) + check( + assert_type(td * mp_series_int, "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) + check( + assert_type(td * md_series_float, "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) check(assert_type(td * md_int64_index, pd.TimedeltaIndex), pd.TimedeltaIndex) check(assert_type(td * md_float_index, pd.TimedeltaIndex), pd.TimedeltaIndex) @@ -721,8 +735,16 @@ def test_timedelta_mul_div() -> None: np.ndarray, np.timedelta64, ) - check(assert_type(mp_series_int * td, TimedeltaSeries), pd.Series, pd.Timedelta) - check(assert_type(md_series_float * td, TimedeltaSeries), pd.Series, pd.Timedelta) + check( + assert_type(mp_series_int * td, "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) + check( + assert_type(md_series_float * td, "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) check(assert_type(md_int64_index * td, pd.TimedeltaIndex), pd.TimedeltaIndex) check(assert_type(md_float_index * td, pd.TimedeltaIndex), pd.TimedeltaIndex) @@ -740,8 +762,16 @@ def test_timedelta_mul_div() -> None: np.ndarray, np.timedelta64, ) - check(assert_type(td // mp_series_int, TimedeltaSeries), pd.Series, pd.Timedelta) - check(assert_type(td // md_series_float, TimedeltaSeries), pd.Series, pd.Timedelta) + check( + assert_type(td // mp_series_int, "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) + check( + assert_type(td // md_series_float, "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) check(assert_type(td // md_int64_index, pd.TimedeltaIndex), pd.TimedeltaIndex) check(assert_type(td // md_float_index, pd.TimedeltaIndex), pd.TimedeltaIndex) check( @@ -778,8 +808,16 @@ def test_timedelta_mul_div() -> None: np.ndarray, np.timedelta64, ) - check(assert_type(td / mp_series_int, TimedeltaSeries), pd.Series, pd.Timedelta) - check(assert_type(td / md_series_float, TimedeltaSeries), pd.Series, pd.Timedelta) + check( + assert_type(td / mp_series_int, "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) + check( + assert_type(td / md_series_float, "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) check(assert_type(td / md_int64_index, pd.TimedeltaIndex), pd.TimedeltaIndex) check(assert_type(td / md_float_index, pd.TimedeltaIndex), pd.TimedeltaIndex) check(assert_type(td / md_timedelta_series, "pd.Series[float]"), pd.Series, float) @@ -820,8 +858,14 @@ def test_timedelta_mod_abs_unary() -> None: ) int_series = pd.Series([1, 2, 3], dtype=int) float_series = pd.Series([1.2, 2.2, 3.4], dtype=float) - check(assert_type(td % int_series, TimedeltaSeries), pd.Series, pd.Timedelta) - check(assert_type(td % float_series, TimedeltaSeries), pd.Series, pd.Timedelta) + check( + assert_type(td % int_series, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta + ) + check( + assert_type(td % float_series, "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) check(assert_type(td % i_idx, pd.TimedeltaIndex), pd.TimedeltaIndex) check( @@ -1197,7 +1241,11 @@ def test_timestamp_add_sub() -> None: as_timedelta_index = pd.to_timedelta([1, 2, 3], unit="D") as_timedelta_series = pd.Series(as_timedelta_index) - check(assert_type(as_timedelta_series, TimedeltaSeries), pd.Series, pd.Timedelta) + check( + assert_type(as_timedelta_series, "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) as_np_ndarray_td64 = np_td64_arr check(assert_type(ts + as_pd_timedelta, pd.Timestamp), pd.Timestamp) @@ -1856,7 +1904,7 @@ def test_period_add_subtract() -> None: as_period = pd.Period("2012-1-1", freq="D") scale = 24 * 60 * 60 * 10**9 as_td_series = pd.Series(pd.timedelta_range(scale, scale, freq="D")) - check(assert_type(as_td_series, TimedeltaSeries), pd.Series, pd.Timedelta) + check(assert_type(as_td_series, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) as_period_series = pd.Series(as_period_index) check(assert_type(as_period_series, PeriodSeries), pd.Series, pd.Period) as_timedelta_idx = pd.timedelta_range(scale, scale, freq="D") diff --git a/tests/test_series.py b/tests/test_series.py index f542c1bd2..c4e94e91d 100644 --- a/tests/test_series.py +++ b/tests/test_series.py @@ -65,10 +65,7 @@ ) if TYPE_CHECKING: - from pandas.core.series import ( - OffsetSeries, - TimedeltaSeries, - ) + from pandas.core.series import OffsetSeries from tests import ( BooleanDtypeArg, @@ -87,7 +84,6 @@ from tests import np_ndarray_int # noqa: F401 else: - TimedeltaSeries: TypeAlias = pd.Series OffsetSeries: TypeAlias = pd.Series @@ -813,9 +809,7 @@ def test_types_element_wise_arithmetic() -> None: check(assert_type(s.sub(s2, fill_value=0), "pd.Series[int]"), pd.Series, np.integer) check(assert_type(s * s2, "pd.Series[int]"), pd.Series, np.integer) - # TODO this below should type pd.Series[int] - # check(assert_type(s.mul(s2, fill_value=0), "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(s.mul(s2, fill_value=0), pd.Series), pd.Series, np.integer) + check(assert_type(s.mul(s2, fill_value=0), "pd.Series[int]"), pd.Series, np.integer) # TODO these two below should type pd.Series[float] # check(assert_type(s / s2, "pd.Series[float]"), pd.Series, np.float64) @@ -1596,8 +1590,8 @@ def test_series_min_max_sub_axis() -> None: sm = s1 * s2 sd = s1 / s2 check(assert_type(sa, pd.Series), pd.Series) # type: ignore[assert-type] - check(assert_type(ss, pd.Series), pd.Series) # type: ignore[assert-type] - check(assert_type(sm, pd.Series), pd.Series) + check(assert_type(ss, pd.Series), pd.Series) + check(assert_type(sm, pd.Series), pd.Series) # type: ignore[assert-type] check(assert_type(sd, pd.Series), pd.Series) @@ -2842,58 +2836,58 @@ def test_astype_timestamp(cast_arg: TimestampDtypeArg, target_type: type) -> Non @pytest.mark.parametrize("cast_arg, target_type", ASTYPE_TIMEDELTA_ARGS, ids=repr) def test_astype_timedelta(cast_arg: TimedeltaDtypeArg, target_type: type) -> None: s = pd.Series([1, 2, 3]) - check(s.astype(cast_arg), TimedeltaSeries, target_type) + check(s.astype(cast_arg), pd.Series, target_type) if TYPE_CHECKING: - assert_type(s.astype("timedelta64[Y]"), "TimedeltaSeries") - assert_type(s.astype("timedelta64[M]"), "TimedeltaSeries") - assert_type(s.astype("timedelta64[W]"), "TimedeltaSeries") - assert_type(s.astype("timedelta64[D]"), "TimedeltaSeries") - assert_type(s.astype("timedelta64[h]"), "TimedeltaSeries") - assert_type(s.astype("timedelta64[m]"), "TimedeltaSeries") - assert_type(s.astype("timedelta64[s]"), "TimedeltaSeries") - assert_type(s.astype("timedelta64[ms]"), "TimedeltaSeries") - assert_type(s.astype("timedelta64[us]"), "TimedeltaSeries") - assert_type(s.astype("timedelta64[μs]"), "TimedeltaSeries") - assert_type(s.astype("timedelta64[ns]"), "TimedeltaSeries") - assert_type(s.astype("timedelta64[ps]"), "TimedeltaSeries") - assert_type(s.astype("timedelta64[fs]"), "TimedeltaSeries") - assert_type(s.astype("timedelta64[as]"), "TimedeltaSeries") + assert_type(s.astype("timedelta64[Y]"), "pd.Series[pd.Timedelta]") + assert_type(s.astype("timedelta64[M]"), "pd.Series[pd.Timedelta]") + assert_type(s.astype("timedelta64[W]"), "pd.Series[pd.Timedelta]") + assert_type(s.astype("timedelta64[D]"), "pd.Series[pd.Timedelta]") + assert_type(s.astype("timedelta64[h]"), "pd.Series[pd.Timedelta]") + assert_type(s.astype("timedelta64[m]"), "pd.Series[pd.Timedelta]") + assert_type(s.astype("timedelta64[s]"), "pd.Series[pd.Timedelta]") + assert_type(s.astype("timedelta64[ms]"), "pd.Series[pd.Timedelta]") + assert_type(s.astype("timedelta64[us]"), "pd.Series[pd.Timedelta]") + assert_type(s.astype("timedelta64[μs]"), "pd.Series[pd.Timedelta]") + assert_type(s.astype("timedelta64[ns]"), "pd.Series[pd.Timedelta]") + assert_type(s.astype("timedelta64[ps]"), "pd.Series[pd.Timedelta]") + assert_type(s.astype("timedelta64[fs]"), "pd.Series[pd.Timedelta]") + assert_type(s.astype("timedelta64[as]"), "pd.Series[pd.Timedelta]") # numpy timedelta64 type codes - assert_type(s.astype("m8[Y]"), "TimedeltaSeries") - assert_type(s.astype("m8[M]"), "TimedeltaSeries") - assert_type(s.astype("m8[W]"), "TimedeltaSeries") - assert_type(s.astype("m8[D]"), "TimedeltaSeries") - assert_type(s.astype("m8[h]"), "TimedeltaSeries") - assert_type(s.astype("m8[m]"), "TimedeltaSeries") - assert_type(s.astype("m8[s]"), "TimedeltaSeries") - assert_type(s.astype("m8[ms]"), "TimedeltaSeries") - assert_type(s.astype("m8[us]"), "TimedeltaSeries") - assert_type(s.astype("m8[μs]"), "TimedeltaSeries") - assert_type(s.astype("m8[ns]"), "TimedeltaSeries") - assert_type(s.astype("m8[ps]"), "TimedeltaSeries") - assert_type(s.astype("m8[fs]"), "TimedeltaSeries") - assert_type(s.astype("m8[as]"), "TimedeltaSeries") + assert_type(s.astype("m8[Y]"), "pd.Series[pd.Timedelta]") + assert_type(s.astype("m8[M]"), "pd.Series[pd.Timedelta]") + assert_type(s.astype("m8[W]"), "pd.Series[pd.Timedelta]") + assert_type(s.astype("m8[D]"), "pd.Series[pd.Timedelta]") + assert_type(s.astype("m8[h]"), "pd.Series[pd.Timedelta]") + assert_type(s.astype("m8[m]"), "pd.Series[pd.Timedelta]") + assert_type(s.astype("m8[s]"), "pd.Series[pd.Timedelta]") + assert_type(s.astype("m8[ms]"), "pd.Series[pd.Timedelta]") + assert_type(s.astype("m8[us]"), "pd.Series[pd.Timedelta]") + assert_type(s.astype("m8[μs]"), "pd.Series[pd.Timedelta]") + assert_type(s.astype("m8[ns]"), "pd.Series[pd.Timedelta]") + assert_type(s.astype("m8[ps]"), "pd.Series[pd.Timedelta]") + assert_type(s.astype("m8[fs]"), "pd.Series[pd.Timedelta]") + assert_type(s.astype("m8[as]"), "pd.Series[pd.Timedelta]") # numpy timedelta64 type codes - assert_type(s.astype(" None: check(assert_type(series / delta, "pd.Series[float]"), pd.Series, float) check(assert_type(series / [delta], "pd.Series[float]"), pd.Series, float) - check(assert_type(series / 1, "TimedeltaSeries"), pd.Series, pd.Timedelta) - check(assert_type(series / [1], "TimedeltaSeries"), pd.Series, pd.Timedelta) + check(assert_type(series / 1, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(series / [1], "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(series // delta, "pd.Series[int]"), pd.Series, np.longlong) check(assert_type(series // [delta], "pd.Series[int]"), pd.Series, int) - check(assert_type(series // 1, "TimedeltaSeries"), pd.Series, pd.Timedelta) - check(assert_type(series // [1], "TimedeltaSeries"), pd.Series, pd.Timedelta) + check(assert_type(series // 1, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check( + assert_type(series // [1], "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta + ) check(assert_type(delta / series, "pd.Series[float]"), pd.Series, float) check(assert_type([delta] / series, "pd.Series[float]"), pd.Series, float) @@ -3235,10 +3231,10 @@ def test_timedelta_div() -> None: check(assert_type([delta] // series, "pd.Series[int]"), pd.Series, np.signedinteger) if TYPE_CHECKING_INVALID_USAGE: - 1 / series # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - [1] / series # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - 1 // series # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - [1] // series # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + 1 / series + [1] / series + 1 // series + [1] // series def test_rank() -> None: @@ -3346,7 +3342,7 @@ def test_timedeltaseries_operators() -> None: pd.Timestamp, ) check( - assert_type(series + datetime.timedelta(1), TimedeltaSeries), + assert_type(series + datetime.timedelta(1), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta, ) @@ -3356,7 +3352,7 @@ def test_timedeltaseries_operators() -> None: pd.Timestamp, ) check( - assert_type(series - datetime.timedelta(1), TimedeltaSeries), + assert_type(series - datetime.timedelta(1), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta, ) @@ -3508,7 +3504,7 @@ def test_diff() -> None: pd.Series( [datetime.datetime.now().date(), datetime.datetime.now().date()] ).diff(), - "TimedeltaSeries", + "pd.Series[pd.Timedelta]", ), pd.Series, pd.Timedelta, @@ -3517,7 +3513,7 @@ def test_diff() -> None: # timestamp -> timedelta times = pd.Series([pd.Timestamp(0), pd.Timestamp(1)]) check( - assert_type(times.diff(), "TimedeltaSeries"), + assert_type(times.diff(), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta, index_to_check_for_type=-1, @@ -3525,7 +3521,8 @@ def test_diff() -> None: # timedelta -> timedelta64 check( assert_type( - pd.Series([pd.Timedelta(0), pd.Timedelta(1)]).diff(), "TimedeltaSeries" + pd.Series([pd.Timedelta(0), pd.Timedelta(1)]).diff(), + "pd.Series[pd.Timedelta]", ), pd.Series, pd.Timedelta, @@ -3606,22 +3603,22 @@ def test_operator_constistency() -> None: # created for #748 s = pd.Series([1, 2, 3]) check( - assert_type(s * np.timedelta64(1, "s"), "TimedeltaSeries"), + assert_type(s * np.timedelta64(1, "s"), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta, ) check( - assert_type(np.timedelta64(1, "s") * s, "TimedeltaSeries"), + assert_type(np.timedelta64(1, "s") * s, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta, ) check( - assert_type(s.mul(np.timedelta64(1, "s")), "TimedeltaSeries"), + assert_type(s.mul(np.timedelta64(1, "s")), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta, ) check( - assert_type(s.rmul(np.timedelta64(1, "s")), "TimedeltaSeries"), + assert_type(s.rmul(np.timedelta64(1, "s")), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta, ) @@ -3899,7 +3896,7 @@ def test_series_items() -> None: 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(s.cumsum(), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check( assert_type(pd.Timestamp(0) + s.cumsum(), "pd.Series[pd.Timestamp]"), pd.Series, diff --git a/tests/test_timefuncs.py b/tests/test_timefuncs.py index 67de2b7ae..d2b73a8b3 100644 --- a/tests/test_timefuncs.py +++ b/tests/test_timefuncs.py @@ -4,7 +4,6 @@ from typing import ( TYPE_CHECKING, Optional, - cast, ) from dateutil.relativedelta import ( @@ -50,7 +49,6 @@ if TYPE_CHECKING: from pandas.core.series import PeriodSeries # noqa: F401 - from pandas.core.series import TimedeltaSeries # noqa: F401 from tests import np_ndarray_bool @@ -183,26 +181,26 @@ 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 - check(assert_type(r3, "TimedeltaSeries"), pd.Series, pd.Timedelta) + check(assert_type(r3, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) r4 = pd.Timedelta(5, "days") / r1 check(assert_type(r4, "pd.Series[float]"), pd.Series, float) 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) + check(assert_type(r6, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) tsp1 = pd.Timestamp("2022-03-05") dt1 = dt.datetime(2022, 9, 1, 12, 5, 30) r7 = ts1 - tsp1 - check(assert_type(r7, "TimedeltaSeries"), pd.Series, pd.Timedelta) + check(assert_type(r7, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) r8 = ts1 - dt1 - check(assert_type(r8, "TimedeltaSeries"), pd.Series, pd.Timedelta) + check(assert_type(r8, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) def test_timestamp_dateoffset_arithmetic() -> None: @@ -223,17 +221,9 @@ def test_datetimeindex_plus_timedelta() -> None: dti = pd.to_datetime(["2022-03-08", "2022-03-15"]) td_s = pd.to_timedelta(pd.Series([10, 20]), "minutes") dti_td_s = dti + td_s - check( - assert_type(dti_td_s, "pd.Series[pd.Timestamp]"), - pd.Series, - pd.Timestamp, - ) + check(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, "pd.Series[pd.Timestamp]"), - pd.Series, - pd.Timestamp, - ) + check(assert_type(td_dti_s, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) tdi = pd.to_timedelta([10, 20], "minutes") dti_tdi_dti = dti + tdi check(assert_type(dti_tdi_dti, "pd.DatetimeIndex"), pd.DatetimeIndex) @@ -258,11 +248,7 @@ def test_datetimeindex_minus_timedelta() -> None: dti = pd.to_datetime(["2022-03-08", "2022-03-15"]) td_s = pd.to_timedelta(pd.Series([10, 20]), "minutes") dti_td_s = dti - td_s - check( - assert_type(dti_td_s, "pd.Series[pd.Timestamp]"), - pd.Series, - pd.Timestamp, - ) + check(assert_type(dti_td_s, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) tdi = pd.to_timedelta([10, 20], "minutes") dti_tdi_dti = dti - tdi check(assert_type(dti_tdi_dti, "pd.DatetimeIndex"), pd.DatetimeIndex) @@ -292,11 +278,7 @@ def test_timestamp_plus_timedelta_series() -> None: def test_timedelta_series_mult() -> None: df = pd.DataFrame({"x": [1, 3, 5], "y": [2, 2, 6]}) std = (df["x"] < df["y"]) * pd.Timedelta(10, "minutes") - check( - assert_type(std, "TimedeltaSeries"), - pd.Series, - pd.Timedelta, - ) + check(assert_type(std, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) def test_timedelta_series_sum() -> None: @@ -357,16 +339,14 @@ def test_to_datetime_nat() -> None: ) check( assert_type( - pd.to_datetime("2021-03-01", errors="coerce"), - "pd.Timestamp | NaTType", + pd.to_datetime("2021-03-01", errors="coerce"), "pd.Timestamp | NaTType" ), pd.Timestamp, ) check( assert_type( - pd.to_datetime("not a date", errors="coerce"), - "pd.Timestamp | NaTType", + pd.to_datetime("not a date", errors="coerce"), "pd.Timestamp | NaTType" ), NaTType, ) @@ -425,11 +405,7 @@ def test_series_dt_accessors() -> None: dt.datetime, ) s0_local = s0.dt.tz_localize("UTC") - check( - assert_type(s0_local, "pd.Series[pd.Timestamp]"), - pd.Series, - pd.Timestamp, - ) + check(assert_type(s0_local, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) check( assert_type(s0.dt.tz_localize(None), "pd.Series[pd.Timestamp]"), pd.Series, @@ -567,7 +543,9 @@ def test_series_dt_accessors() -> None: i2 = pd.timedelta_range(start="1 day", periods=10) check(assert_type(i2, pd.TimedeltaIndex), pd.TimedeltaIndex) - check(assert_type(i2.to_series(), "TimedeltaSeries"), pd.Series, pd.Timedelta) + check( + assert_type(i2.to_series(), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta + ) s2 = pd.Series(i2) @@ -584,12 +562,28 @@ def test_series_dt_accessors() -> None: check(assert_type(s2.dt.to_pytimedelta(), np.ndarray), np.ndarray) 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 Series[Timestamp] and TimedeltaSeries + # Checks for general Series other than pd.Series[pd.Timestamp] and pd.Series[pd.Timedelta] s4 = pd.Series([pd.Timestamp("2024-01-01"), pd.Timestamp("2024-01-02")]) @@ -615,29 +609,26 @@ def test_series_dt_accessors() -> None: pd.Timestamp, ) - s5 = cast( - "pd.Series[pd.Timedelta]", - pd.Series([pd.Timedelta("1 day"), pd.Timedelta("2 days")]), - ) + s5 = pd.Series([pd.Timedelta("1 day"), pd.Timedelta("2 days")]) check(assert_type(s5.dt.unit, TimeUnit), str) check( - assert_type(s5.dt.as_unit("s"), "pd.Series[pd.Timedelta]"), # type: ignore[assert-type] + 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]"), # type: ignore[assert-type] + 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]"), # type: ignore[assert-type] + 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]"), # type: ignore[assert-type] + assert_type(s5.dt.as_unit("ns"), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta, ) @@ -989,8 +980,8 @@ def test_to_timedelta_scalar() -> None: def test_to_timedelta_series() -> None: s = pd.Series([10, 20, 30, 40]) s2 = pd.Series(["10ms", "20ms", "30ms"]) - check(assert_type(pd.to_timedelta(s, "ms"), "TimedeltaSeries"), pd.Series) - check(assert_type(pd.to_timedelta(s2), "TimedeltaSeries"), pd.Series) + check(assert_type(pd.to_timedelta(s, "ms"), "pd.Series[pd.Timedelta]"), pd.Series) + check(assert_type(pd.to_timedelta(s2), "pd.Series[pd.Timedelta]"), pd.Series) def test_to_timedelta_index() -> None: @@ -1261,9 +1252,7 @@ def test_to_datetime_array() -> None: pd.DatetimeIndex, ) pd.to_datetime( - pd.Index([2451544.5, 2451545.5, 2451546.5]), - unit="D", - origin="julian", + pd.Index([2451544.5, 2451545.5, 2451546.5]), unit="D", origin="julian" ) check( assert_type( @@ -1399,7 +1388,7 @@ 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, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) # GH 758 @@ -1409,8 +1398,8 @@ def test_timedelta64_and_arithmatic_operator() -> None: td = np.timedelta64(1, "D") 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[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type((s3 + td), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type((s3 / td), "pd.Series[float]"), pd.Series, float) if TYPE_CHECKING_INVALID_USAGE: r1 = s1 * td # type: ignore[var-annotated] @@ -1502,31 +1491,19 @@ def test_dateoffset_weekday() -> None: def test_date_range_unit(): check( - assert_type( - pd.date_range("1/1/2022", "2/1/2022", unit="s"), - pd.DatetimeIndex, - ), + assert_type(pd.date_range("1/1/2022", "2/1/2022", unit="s"), pd.DatetimeIndex), pd.DatetimeIndex, ) check( - assert_type( - pd.date_range("1/1/2022", "2/1/2022", unit="ms"), - pd.DatetimeIndex, - ), + assert_type(pd.date_range("1/1/2022", "2/1/2022", unit="ms"), pd.DatetimeIndex), pd.DatetimeIndex, ) check( - assert_type( - pd.date_range("1/1/2022", "2/1/2022", unit="us"), - pd.DatetimeIndex, - ), + assert_type(pd.date_range("1/1/2022", "2/1/2022", unit="us"), pd.DatetimeIndex), pd.DatetimeIndex, ) check( - assert_type( - pd.date_range("1/1/2022", "2/1/2022", unit="ns"), - pd.DatetimeIndex, - ), + assert_type(pd.date_range("1/1/2022", "2/1/2022", unit="ns"), pd.DatetimeIndex), pd.DatetimeIndex, ) @@ -1552,4 +1529,4 @@ 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) From 48a72c3ad3dbdc020b47a5f0fe20d1f0766797d4 Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Mon, 22 Sep 2025 17:31:24 +0200 Subject: [PATCH 03/13] feat: add --- pandas-stubs/core/series.pyi | 16 +- tests/series/arithmetic/timedelta/__init__.py | 0 tests/series/arithmetic/timedelta/test_add.py | 148 ++++++++++++++++++ tests/series/arithmetic/timestamp/test_add.py | 26 ++- 4 files changed, 186 insertions(+), 4 deletions(-) create mode 100644 tests/series/arithmetic/timedelta/__init__.py create mode 100644 tests/series/arithmetic/timedelta/test_add.py diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index 1d36f5270..f92f5b3c4 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -1922,7 +1922,12 @@ class Series(IndexOpsMixin[S1], NDFrame): def add( self: Series[Timedelta], other: ( - datetime | np.datetime64 | np_ndarray_dt | DatetimeIndex | Series[Timestamp] + datetime + | Sequence[datetime] + | np.datetime64 + | np_ndarray_dt + | DatetimeIndex + | Series[Timestamp] ), level: Level | None = None, fill_value: float | None = None, @@ -1933,6 +1938,7 @@ class Series(IndexOpsMixin[S1], NDFrame): self: Series[Timedelta], other: ( timedelta + | Sequence[timedelta] | np.timedelta64 | np_ndarray_td | TimedeltaIndex @@ -2222,7 +2228,12 @@ class Series(IndexOpsMixin[S1], NDFrame): def radd( self: Series[Timedelta], other: ( - datetime | np.datetime64 | np_ndarray_dt | DatetimeIndex | Series[Timestamp] + datetime + | Sequence[datetime] + | np.datetime64 + | np_ndarray_dt + | DatetimeIndex + | Series[Timestamp] ), level: Level | None = None, fill_value: float | None = None, @@ -2233,6 +2244,7 @@ class Series(IndexOpsMixin[S1], NDFrame): self: Series[Timedelta], other: ( timedelta + | Sequence[timedelta] | np.timedelta64 | np_ndarray_td | TimedeltaIndex diff --git a/tests/series/arithmetic/timedelta/__init__.py b/tests/series/arithmetic/timedelta/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/series/arithmetic/timedelta/test_add.py b/tests/series/arithmetic/timedelta/test_add.py new file mode 100644 index 000000000..8a7873677 --- /dev/null +++ b/tests/series/arithmetic/timedelta/test_add.py @@ -0,0 +1,148 @@ +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 assert_type + +from tests import ( + TYPE_CHECKING_INVALID_USAGE, + check, +) + +left = pd.Series([pd.Timedelta(1, "s")]) # left operand + + +def test_add_py_scalar() -> None: + """Test pd.Series[pd.Timedelta] + Python native scalars""" + s = datetime(2025, 8, 20) + d = timedelta(seconds=1) + + check(assert_type(left + s, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(left + d, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(s + left, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(d + left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(left.add(s), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(left.add(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(left.radd(s), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(left.radd(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + +def test_add_numpy_scalar() -> None: + """Test pd.Series[pd.Timedelta] + numpy scalars""" + s = np.datetime64("2025-08-20") + d = np.timedelta64(1, "s") + + check(assert_type(left + s, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(left + d, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(s + left, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(d + left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(left.add(s), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(left.add(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(left.radd(s), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(left.radd(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + +def test_add_pd_scalar() -> None: + """Test pd.Series[pd.Timedelta] + pandas scalars""" + s = pd.Timestamp("2025-08-20") + d = pd.Timedelta(seconds=1) + + check(assert_type(left + s, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(left + d, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(s + left, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(d + left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(left.add(s), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(left.add(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(left.radd(s), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(left.radd(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + +def test_add_py_sequence() -> None: + """Test pd.Series[pd.Timedelta] + Python native sequence""" + s = [datetime(2025, 8, 20)] + d = [timedelta(seconds=1)] + + if TYPE_CHECKING_INVALID_USAGE: + # Series[Timedelta] + Sequence[datetime] should work, see pandas-dev/pandas#62353 + _0 = left + s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + # Series[Timedelta] + Sequence[timedelta] should work, see pandas-dev/pandas#62353 + _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] + + check(assert_type(left.add(s), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(left.add(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(left.radd(s), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(left.radd(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + +def test_add_numpy_array() -> None: + """Test pd.Series[pd.Timedelta] + 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, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(left + d, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + # `numpy` typing gives the corresponding `ndarray`s in the static type + # checking, where our `__radd__` cannot override. At runtime, they return + # `Series`. + check(assert_type(s + left, "npt.NDArray[np.datetime64]"), pd.Series, pd.Timestamp) + check(assert_type(d + left, "npt.NDArray[np.timedelta64]"), pd.Series, pd.Timedelta) + + check(assert_type(left.add(s), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(left.add(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(left.radd(s), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(left.radd(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + +def test_add_pd_index() -> None: + """Test pd.Series[pd.Timedelta] + pandas Index""" + s = pd.Index([pd.Timestamp("2025-08-20")]) + d = pd.Index([pd.Timedelta(seconds=1)]) + + check(assert_type(left + s, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(left + d, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(s + left, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(d + left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(left.add(s), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(left.add(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(left.radd(s), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(left.radd(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + +def test_add_pd_series() -> None: + """Test pd.Series[pd.Timedelta] + 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.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(left + d, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(s + left, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(d + left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(left.add(s), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(left.add(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(left.radd(s), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(left.radd(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) diff --git a/tests/series/arithmetic/timestamp/test_add.py b/tests/series/arithmetic/timestamp/test_add.py index 7e308b4f6..1fe9a8441 100644 --- a/tests/series/arithmetic/timestamp/test_add.py +++ b/tests/series/arithmetic/timestamp/test_add.py @@ -100,11 +100,11 @@ def test_add_py_sequence() -> None: if TYPE_CHECKING_INVALID_USAGE: left.add(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] - left.add(d) + 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] - left.radd(d) + check(assert_type(left.radd(d), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) def test_add_numpy_array() -> None: @@ -134,6 +134,28 @@ def test_add_numpy_array() -> None: check(assert_type(left.radd(d), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) +def test_add_pd_index() -> None: + """Test pd.Series[pd.Timestamp] + pandas Index""" + s = pd.Index([pd.Timestamp("2025-08-20")]) + d = pd.Index([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) + + def test_add_pd_series() -> None: """Test pd.Series[pd.Timestamp] + pandas Series""" s = pd.Series([pd.Timestamp("2025-08-20")]) From 61b83cef1c12a8af554a8d578ecc08bfb8fe137c Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Mon, 22 Sep 2025 23:22:02 +0200 Subject: [PATCH 04/13] feat(test): sub --- pandas-stubs/core/series.pyi | 2 + tests/indexes/arithmetic/bool/test_add.py | 4 +- tests/indexes/arithmetic/bool/test_sub.py | 4 +- tests/indexes/arithmetic/complex/test_add.py | 4 +- tests/indexes/arithmetic/complex/test_sub.py | 4 +- tests/indexes/arithmetic/float/test_add.py | 4 +- tests/indexes/arithmetic/float/test_sub.py | 4 +- tests/indexes/arithmetic/int/test_add.py | 4 +- tests/indexes/arithmetic/int/test_sub.py | 4 +- tests/indexes/arithmetic/str/test_add.py | 4 +- tests/indexes/arithmetic/test_add.py | 4 +- tests/indexes/arithmetic/test_sub.py | 4 +- tests/series/arithmetic/bool/test_add.py | 4 +- tests/series/arithmetic/bool/test_mul.py | 4 +- tests/series/arithmetic/bool/test_sub.py | 4 +- tests/series/arithmetic/bool/test_truediv.py | 4 +- tests/series/arithmetic/complex/test_add.py | 4 +- tests/series/arithmetic/complex/test_mul.py | 4 +- tests/series/arithmetic/complex/test_sub.py | 4 +- .../series/arithmetic/complex/test_truediv.py | 4 +- tests/series/arithmetic/float/test_add.py | 4 +- tests/series/arithmetic/float/test_mul.py | 4 +- tests/series/arithmetic/float/test_sub.py | 4 +- tests/series/arithmetic/float/test_truediv.py | 4 +- tests/series/arithmetic/int/test_add.py | 4 +- tests/series/arithmetic/int/test_mul.py | 4 +- tests/series/arithmetic/int/test_sub.py | 4 +- tests/series/arithmetic/int/test_truediv.py | 4 +- tests/series/arithmetic/str/test_add.py | 4 +- tests/series/arithmetic/test_add.py | 4 +- tests/series/arithmetic/test_mul.py | 4 +- tests/series/arithmetic/test_sub.py | 4 +- tests/series/arithmetic/test_truediv.py | 4 +- tests/series/arithmetic/timedelta/test_add.py | 6 +- tests/series/arithmetic/timedelta/test_sub.py | 163 ++++++++++++++++++ tests/series/arithmetic/timestamp/test_add.py | 6 +- tests/series/arithmetic/timestamp/test_sub.py | 24 ++- tests/test_timefuncs.py | 10 -- 38 files changed, 257 insertions(+), 82 deletions(-) create mode 100644 tests/series/arithmetic/timedelta/test_sub.py diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index f92f5b3c4..82b23a6d1 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -3098,6 +3098,8 @@ class Series(IndexOpsMixin[S1], NDFrame): ), ) -> Series[Timestamp]: ... @overload + def __sub__(self: Series[Timedelta], other: np_ndarray_dt) -> Never: ... + @overload def __sub__( self: Series[Timedelta], other: ( diff --git a/tests/indexes/arithmetic/bool/test_add.py b/tests/indexes/arithmetic/bool/test_add.py index 8389ad367..b212c2676 100644 --- a/tests/indexes/arithmetic/bool/test_add.py +++ b/tests/indexes/arithmetic/bool/test_add.py @@ -26,7 +26,7 @@ def test_add_py_scalar() -> None: def test_add_py_sequence() -> None: - """Test pd.Index[bool] + Python native sequence""" + """Test pd.Index[bool] + Python native sequences""" b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] check(assert_type(left + b, "pd.Index[bool]"), pd.Index, np.bool_) @@ -41,7 +41,7 @@ def test_add_py_sequence() -> None: def test_add_numpy_array() -> None: - """Test pd.Index[bool] + numpy array""" + """Test pd.Index[bool] + numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/indexes/arithmetic/bool/test_sub.py b/tests/indexes/arithmetic/bool/test_sub.py index c36d0916a..4bc27fd04 100644 --- a/tests/indexes/arithmetic/bool/test_sub.py +++ b/tests/indexes/arithmetic/bool/test_sub.py @@ -32,7 +32,7 @@ def test_sub_py_scalar() -> None: def test_sub_py_sequence() -> None: - """Test pd.Index[bool] - Python native sequence""" + """Test pd.Index[bool] - Python native sequences""" b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] if TYPE_CHECKING_INVALID_USAGE: @@ -49,7 +49,7 @@ def test_sub_py_sequence() -> None: def test_sub_numpy_array() -> None: - """Test pd.Index[bool] - numpy array""" + """Test pd.Index[bool] - numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/indexes/arithmetic/complex/test_add.py b/tests/indexes/arithmetic/complex/test_add.py index 0d9662dc2..ae6d35b9b 100644 --- a/tests/indexes/arithmetic/complex/test_add.py +++ b/tests/indexes/arithmetic/complex/test_add.py @@ -25,7 +25,7 @@ def test_add_py_scalar() -> None: def test_add_py_sequence() -> None: - """Test pd.Index[complex] + Python native sequence""" + """Test pd.Index[complex] + Python native sequences""" b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] check(assert_type(left + b, "pd.Index[complex]"), pd.Index, np.complexfloating) @@ -40,7 +40,7 @@ def test_add_py_sequence() -> None: def test_add_numpy_array() -> None: - """Test pd.Index[complex] + numpy array""" + """Test pd.Index[complex] + numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/indexes/arithmetic/complex/test_sub.py b/tests/indexes/arithmetic/complex/test_sub.py index a31a2cc88..114370096 100644 --- a/tests/indexes/arithmetic/complex/test_sub.py +++ b/tests/indexes/arithmetic/complex/test_sub.py @@ -27,7 +27,7 @@ def test_sub_py_scalar() -> None: def test_sub_py_sequence() -> None: - """Test pd.Index[complex] - Python native sequence""" + """Test pd.Index[complex] - Python native sequences""" b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] check(assert_type(left - b, "pd.Index[complex]"), pd.Index, np.complexfloating) @@ -42,7 +42,7 @@ def test_sub_py_sequence() -> None: def test_sub_numpy_array() -> None: - """Test pd.Index[complex] - numpy array""" + """Test pd.Index[complex] - numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/indexes/arithmetic/float/test_add.py b/tests/indexes/arithmetic/float/test_add.py index b882fd6fe..737717f6f 100644 --- a/tests/indexes/arithmetic/float/test_add.py +++ b/tests/indexes/arithmetic/float/test_add.py @@ -25,7 +25,7 @@ def test_add_py_scalar() -> None: def test_add_py_sequence() -> None: - """Test pd.Index[float] + Python native sequence""" + """Test pd.Index[float] + Python native sequences""" b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] check(assert_type(left + b, "pd.Index[float]"), pd.Index, np.floating) @@ -40,7 +40,7 @@ def test_add_py_sequence() -> None: def test_add_numpy_array() -> None: - """Test pd.Index[float] + numpy array""" + """Test pd.Index[float] + numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/indexes/arithmetic/float/test_sub.py b/tests/indexes/arithmetic/float/test_sub.py index 8c589df3c..28c1267ec 100644 --- a/tests/indexes/arithmetic/float/test_sub.py +++ b/tests/indexes/arithmetic/float/test_sub.py @@ -27,7 +27,7 @@ def test_sub_py_scalar() -> None: def test_sub_py_sequence() -> None: - """Test pd.Index[float] - Python native sequence""" + """Test pd.Index[float] - Python native sequences""" b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] check(assert_type(left - b, "pd.Index[float]"), pd.Index, np.floating) @@ -42,7 +42,7 @@ def test_sub_py_sequence() -> None: def test_sub_numpy_array() -> None: - """Test pd.Index[float] - numpy array""" + """Test pd.Index[float] - numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/indexes/arithmetic/int/test_add.py b/tests/indexes/arithmetic/int/test_add.py index 126898b46..d24242aa0 100644 --- a/tests/indexes/arithmetic/int/test_add.py +++ b/tests/indexes/arithmetic/int/test_add.py @@ -25,7 +25,7 @@ def test_add_py_scalar() -> None: def test_add_py_sequence() -> None: - """Test pd.Index[int] + Python native sequence""" + """Test pd.Index[int] + Python native sequences""" b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] check(assert_type(left + b, "pd.Index[int]"), pd.Index, np.integer) @@ -40,7 +40,7 @@ def test_add_py_sequence() -> None: def test_add_numpy_array() -> None: - """Test pd.Index[int] + numpy array""" + """Test pd.Index[int] + numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/indexes/arithmetic/int/test_sub.py b/tests/indexes/arithmetic/int/test_sub.py index edea4de21..a85b8b3c4 100644 --- a/tests/indexes/arithmetic/int/test_sub.py +++ b/tests/indexes/arithmetic/int/test_sub.py @@ -27,7 +27,7 @@ def test_sub_py_scalar() -> None: def test_sub_py_sequence() -> None: - """Test pd.Index[int] - Python native sequence""" + """Test pd.Index[int] - Python native sequences""" b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] check(assert_type(left - b, "pd.Index[int]"), pd.Index, np.integer) @@ -42,7 +42,7 @@ def test_sub_py_sequence() -> None: def test_sub_numpy_array() -> None: - """Test pd.Index[int] - numpy array""" + """Test pd.Index[int] - numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/indexes/arithmetic/str/test_add.py b/tests/indexes/arithmetic/str/test_add.py index d985a2c93..4b4b249bc 100644 --- a/tests/indexes/arithmetic/str/test_add.py +++ b/tests/indexes/arithmetic/str/test_add.py @@ -32,7 +32,7 @@ def test_add_py_scalar() -> None: def test_add_py_sequence() -> None: - """Test pd.Index[str] + Python native sequence""" + """Test pd.Index[str] + Python native sequences""" i = [3, 5, 8] r0 = ["a", "bc", "def"] r1 = tuple(r0) @@ -49,7 +49,7 @@ def test_add_py_sequence() -> None: def test_add_numpy_array() -> None: - """Test pd.Index[str] + numpy array""" + """Test pd.Index[str] + numpy arrays""" i = np.array([3, 5, 8], np.int64) r0 = np.array(["a", "bc", "def"], np.str_) diff --git a/tests/indexes/arithmetic/test_add.py b/tests/indexes/arithmetic/test_add.py index b4f2194af..89bfd0653 100644 --- a/tests/indexes/arithmetic/test_add.py +++ b/tests/indexes/arithmetic/test_add.py @@ -33,7 +33,7 @@ def test_add_i_py_scalar() -> None: def test_add_i_py_sequence() -> None: - """Test pd.Index[Any] (int) + Python native sequence""" + """Test pd.Index[Any] (int) + Python native sequences""" b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] check(assert_type(left_i + b, pd.Index), pd.Index) @@ -48,7 +48,7 @@ def test_add_i_py_sequence() -> None: def test_add_i_numpy_array() -> None: - """Test pd.Index[Any] (int) + numpy array""" + """Test pd.Index[Any] (int) + numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/indexes/arithmetic/test_sub.py b/tests/indexes/arithmetic/test_sub.py index 0a6217006..b5188a5a2 100644 --- a/tests/indexes/arithmetic/test_sub.py +++ b/tests/indexes/arithmetic/test_sub.py @@ -29,7 +29,7 @@ def test_sub_i_py_scalar() -> None: def test_sub_i_py_sequence() -> None: - """Test pd.Index[Any] (int) - Python native sequence""" + """Test pd.Index[Any] (int) - Python native sequences""" b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] check(assert_type(left_i - b, pd.Index), pd.Index) @@ -44,7 +44,7 @@ def test_sub_i_py_sequence() -> None: def test_sub_i_numpy_array() -> None: - """Test pd.Index[Any] (int) - numpy array""" + """Test pd.Index[Any] (int) - numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/series/arithmetic/bool/test_add.py b/tests/series/arithmetic/bool/test_add.py index 81c2bf13a..ce2ec70af 100644 --- a/tests/series/arithmetic/bool/test_add.py +++ b/tests/series/arithmetic/bool/test_add.py @@ -36,7 +36,7 @@ def test_add_py_scalar() -> None: def test_add_py_sequence() -> None: - """Test pd.Series[bool] + Python native sequence""" + """Test pd.Series[bool] + Python native sequences""" b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] check(assert_type(left + b, "pd.Series[bool]"), pd.Series, np.bool_) @@ -63,7 +63,7 @@ def test_add_py_sequence() -> None: def test_add_numpy_array() -> None: - """Test pd.Series[bool] + numpy array""" + """Test pd.Series[bool] + numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/series/arithmetic/bool/test_mul.py b/tests/series/arithmetic/bool/test_mul.py index 9b3c96ee1..218f12f9a 100644 --- a/tests/series/arithmetic/bool/test_mul.py +++ b/tests/series/arithmetic/bool/test_mul.py @@ -36,7 +36,7 @@ def test_mul_py_scalar() -> None: def test_mul_py_sequence() -> None: - """Test pd.Series[bool] * Python native sequence""" + """Test pd.Series[bool] * Python native sequences""" b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] check(assert_type(left * b, "pd.Series[bool]"), pd.Series, np.bool_) @@ -63,7 +63,7 @@ def test_mul_py_sequence() -> None: def test_mul_numpy_array() -> None: - """Test pd.Series[bool] * numpy array""" + """Test pd.Series[bool] * numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/series/arithmetic/bool/test_sub.py b/tests/series/arithmetic/bool/test_sub.py index c5f0e1ec0..df67743bb 100644 --- a/tests/series/arithmetic/bool/test_sub.py +++ b/tests/series/arithmetic/bool/test_sub.py @@ -46,7 +46,7 @@ def test_sub_py_scalar() -> None: def test_sub_py_sequence() -> None: - """Test pd.Series[bool] - Python native sequence""" + """Test pd.Series[bool] - Python native sequences""" b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] if TYPE_CHECKING_INVALID_USAGE: @@ -77,7 +77,7 @@ def test_sub_py_sequence() -> None: def test_sub_numpy_array() -> None: - """Test pd.Series[bool] - numpy array""" + """Test pd.Series[bool] - numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/series/arithmetic/bool/test_truediv.py b/tests/series/arithmetic/bool/test_truediv.py index 1bcc8008e..0a09c4a9b 100644 --- a/tests/series/arithmetic/bool/test_truediv.py +++ b/tests/series/arithmetic/bool/test_truediv.py @@ -66,7 +66,7 @@ def test_truediv_py_scalar() -> None: def test_truediv_py_sequence() -> None: - """Test pd.Series[bool] / Python native sequence""" + """Test pd.Series[bool] / Python native sequences""" b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] check(assert_type(left / b, "pd.Series[float]"), pd.Series, np.floating) @@ -111,7 +111,7 @@ def test_truediv_py_sequence() -> None: def test_truediv_numpy_array() -> None: - """Test pd.Series[bool] / numpy array""" + """Test pd.Series[bool] / numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/series/arithmetic/complex/test_add.py b/tests/series/arithmetic/complex/test_add.py index e92ea5cea..a782b4d63 100644 --- a/tests/series/arithmetic/complex/test_add.py +++ b/tests/series/arithmetic/complex/test_add.py @@ -42,7 +42,7 @@ def test_add_py_scalar() -> None: def test_add_py_sequence() -> None: - """Test pd.Series[complex] + Python native sequence""" + """Test pd.Series[complex] + Python native sequences""" b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] check(assert_type(left + b, "pd.Series[complex]"), pd.Series, np.complexfloating) @@ -75,7 +75,7 @@ def test_add_py_sequence() -> None: def test_add_numpy_array() -> None: - """Test pd.Series[complex] + numpy array""" + """Test pd.Series[complex] + numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/series/arithmetic/complex/test_mul.py b/tests/series/arithmetic/complex/test_mul.py index 206e1b82c..4f58e28e2 100644 --- a/tests/series/arithmetic/complex/test_mul.py +++ b/tests/series/arithmetic/complex/test_mul.py @@ -42,7 +42,7 @@ def test_mul_py_scalar() -> None: def test_mul_py_sequence() -> None: - """Test pd.Series[complex] * Python native sequence""" + """Test pd.Series[complex] * Python native sequences""" b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] check(assert_type(left * b, "pd.Series[complex]"), pd.Series, np.complexfloating) @@ -75,7 +75,7 @@ def test_mul_py_sequence() -> None: def test_mul_numpy_array() -> None: - """Test pd.Series[complex] * numpy array""" + """Test pd.Series[complex] * numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/series/arithmetic/complex/test_sub.py b/tests/series/arithmetic/complex/test_sub.py index b1daa4541..102f65309 100644 --- a/tests/series/arithmetic/complex/test_sub.py +++ b/tests/series/arithmetic/complex/test_sub.py @@ -44,7 +44,7 @@ def test_sub_py_scalar() -> None: def test_sub_py_sequence() -> None: - """Test pd.Series[complex] - Python native sequence""" + """Test pd.Series[complex] - Python native sequences""" b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] check(assert_type(left - b, "pd.Series[complex]"), pd.Series, np.complexfloating) @@ -77,7 +77,7 @@ def test_sub_py_sequence() -> None: def test_sub_numpy_array() -> None: - """Test pd.Series[complex] - numpy array""" + """Test pd.Series[complex] - numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/series/arithmetic/complex/test_truediv.py b/tests/series/arithmetic/complex/test_truediv.py index 38a8b9096..ae194fe70 100644 --- a/tests/series/arithmetic/complex/test_truediv.py +++ b/tests/series/arithmetic/complex/test_truediv.py @@ -84,7 +84,7 @@ def test_truediv_py_scalar() -> None: def test_truediv_py_sequence() -> None: - """Test pd.Series[complex] / Python native sequence""" + """Test pd.Series[complex] / Python native sequences""" b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] check(assert_type(left / b, "pd.Series[complex]"), pd.Series, np.complexfloating) @@ -159,7 +159,7 @@ def test_truediv_py_sequence() -> None: def test_truediv_numpy_array() -> None: - """Test pd.Series[complex] / numpy array""" + """Test pd.Series[complex] / numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/series/arithmetic/float/test_add.py b/tests/series/arithmetic/float/test_add.py index 5126f8d79..5feeb50be 100644 --- a/tests/series/arithmetic/float/test_add.py +++ b/tests/series/arithmetic/float/test_add.py @@ -36,7 +36,7 @@ def test_add_py_scalar() -> None: def test_add_py_sequence() -> None: - """Test pd.Series[float] + Python native sequence""" + """Test pd.Series[float] + Python native sequences""" b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] check(assert_type(left + b, "pd.Series[float]"), pd.Series, np.floating) @@ -63,7 +63,7 @@ def test_add_py_sequence() -> None: def test_add_numpy_array() -> None: - """Test pd.Series[float] + numpy array""" + """Test pd.Series[float] + numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/series/arithmetic/float/test_mul.py b/tests/series/arithmetic/float/test_mul.py index 9472d5335..84e702c51 100644 --- a/tests/series/arithmetic/float/test_mul.py +++ b/tests/series/arithmetic/float/test_mul.py @@ -36,7 +36,7 @@ def test_mul_py_scalar() -> None: def test_mul_py_sequence() -> None: - """Test pd.Series[float] * Python native sequence""" + """Test pd.Series[float] * Python native sequences""" b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] check(assert_type(left * b, "pd.Series[float]"), pd.Series, np.floating) @@ -63,7 +63,7 @@ def test_mul_py_sequence() -> None: def test_mul_numpy_array() -> None: - """Test pd.Series[float] * numpy array""" + """Test pd.Series[float] * numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/series/arithmetic/float/test_sub.py b/tests/series/arithmetic/float/test_sub.py index d4722b3f1..08abcd178 100644 --- a/tests/series/arithmetic/float/test_sub.py +++ b/tests/series/arithmetic/float/test_sub.py @@ -38,7 +38,7 @@ def test_sub_py_scalar() -> None: def test_sub_py_sequence() -> None: - """Test pd.Series[float] - Python native sequence""" + """Test pd.Series[float] - Python native sequences""" b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] check(assert_type(left - b, "pd.Series[float]"), pd.Series, np.floating) @@ -65,7 +65,7 @@ def test_sub_py_sequence() -> None: def test_sub_numpy_array() -> None: - """Test pd.Series[float] - numpy array""" + """Test pd.Series[float] - numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/series/arithmetic/float/test_truediv.py b/tests/series/arithmetic/float/test_truediv.py index fc0dc9023..d10fb0123 100644 --- a/tests/series/arithmetic/float/test_truediv.py +++ b/tests/series/arithmetic/float/test_truediv.py @@ -54,7 +54,7 @@ def test_truediv_py_scalar() -> None: def test_truediv_py_sequence() -> None: - """Test pd.Series[float] / Python native sequence""" + """Test pd.Series[float] / Python native sequences""" b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] check(assert_type(left / b, "pd.Series[float]"), pd.Series, np.floating) @@ -99,7 +99,7 @@ def test_truediv_py_sequence() -> None: def test_truediv_numpy_array() -> None: - """Test pd.Series[float] / numpy array""" + """Test pd.Series[float] / numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/series/arithmetic/int/test_add.py b/tests/series/arithmetic/int/test_add.py index cac8eadb6..ef25fd8c3 100644 --- a/tests/series/arithmetic/int/test_add.py +++ b/tests/series/arithmetic/int/test_add.py @@ -36,7 +36,7 @@ def test_add_py_scalar() -> None: def test_add_py_sequence() -> None: - """Test pd.Series[int] + Python native sequence""" + """Test pd.Series[int] + Python native sequences""" b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] check(assert_type(left + b, "pd.Series[int]"), pd.Series, np.integer) @@ -63,7 +63,7 @@ def test_add_py_sequence() -> None: def test_add_numpy_array() -> None: - """Test pd.Series[int] + numpy array""" + """Test pd.Series[int] + numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/series/arithmetic/int/test_mul.py b/tests/series/arithmetic/int/test_mul.py index 2018de06e..e61982506 100644 --- a/tests/series/arithmetic/int/test_mul.py +++ b/tests/series/arithmetic/int/test_mul.py @@ -36,7 +36,7 @@ def test_mul_py_scalar() -> None: def test_mul_py_sequence() -> None: - """Test pd.Series[int] * Python native sequence""" + """Test pd.Series[int] * Python native sequences""" b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] check(assert_type(left * b, "pd.Series[int]"), pd.Series, np.integer) @@ -63,7 +63,7 @@ def test_mul_py_sequence() -> None: def test_mul_numpy_array() -> None: - """Test pd.Series[int] * numpy array""" + """Test pd.Series[int] * numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/series/arithmetic/int/test_sub.py b/tests/series/arithmetic/int/test_sub.py index 75fc96a62..360886881 100644 --- a/tests/series/arithmetic/int/test_sub.py +++ b/tests/series/arithmetic/int/test_sub.py @@ -38,7 +38,7 @@ def test_sub_py_scalar() -> None: def test_sub_py_sequence() -> None: - """Test pd.Series[int] - Python native sequence""" + """Test pd.Series[int] - Python native sequences""" b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] check(assert_type(left - b, "pd.Series[int]"), pd.Series, np.integer) @@ -65,7 +65,7 @@ def test_sub_py_sequence() -> None: def test_sub_numpy_array() -> None: - """Test pd.Series[int] - numpy array""" + """Test pd.Series[int] - numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/series/arithmetic/int/test_truediv.py b/tests/series/arithmetic/int/test_truediv.py index a6d7f2a37..a17dea9a1 100644 --- a/tests/series/arithmetic/int/test_truediv.py +++ b/tests/series/arithmetic/int/test_truediv.py @@ -54,7 +54,7 @@ def test_truediv_py_scalar() -> None: def test_truediv_py_sequence() -> None: - """Test pd.Series[int] / Python native sequence""" + """Test pd.Series[int] / Python native sequences""" b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] check(assert_type(left / b, "pd.Series[float]"), pd.Series, np.floating) @@ -99,7 +99,7 @@ def test_truediv_py_sequence() -> None: def test_truediv_numpy_array() -> None: - """Test pd.Series[int] / numpy array""" + """Test pd.Series[int] / numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/series/arithmetic/str/test_add.py b/tests/series/arithmetic/str/test_add.py index 9ac84ea71..917e504c6 100644 --- a/tests/series/arithmetic/str/test_add.py +++ b/tests/series/arithmetic/str/test_add.py @@ -40,7 +40,7 @@ def test_add_py_scalar() -> None: def test_add_py_sequence() -> None: - """Test pd.Series[str] + Python native sequence""" + """Test pd.Series[str] + Python native sequences""" i = [3, 5, 8] r0 = ["a", "bc", "def"] r1 = tuple(r0) @@ -67,7 +67,7 @@ def test_add_py_sequence() -> None: def test_add_numpy_array() -> None: - """Test pd.Series[str] + numpy array""" + """Test pd.Series[str] + numpy arrays""" i = np.array([3, 5, 8], np.int64) r0 = np.array(["a", "bc", "def"], np.str_) diff --git a/tests/series/arithmetic/test_add.py b/tests/series/arithmetic/test_add.py index d06367c13..689ab5751 100644 --- a/tests/series/arithmetic/test_add.py +++ b/tests/series/arithmetic/test_add.py @@ -40,7 +40,7 @@ def test_add_i_py_scalar() -> None: def test_add_i_py_sequence() -> None: - """Test pd.Series[Any] (int) + Python native sequence""" + """Test pd.Series[Any] (int) + Python native sequences""" # mypy believe it is already list[Any], whereas pyright gives list[bool | int | complex] a = cast(list[Any], [True, 3, 5j]) # type: ignore[redundant-cast] b = [True, False, True] @@ -74,7 +74,7 @@ def test_add_i_py_sequence() -> None: def test_add_i_numpy_array() -> None: - """Test pd.Series[Any] (int) + numpy array""" + """Test pd.Series[Any] (int) + numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/series/arithmetic/test_mul.py b/tests/series/arithmetic/test_mul.py index 71cc4962d..01c86e9df 100644 --- a/tests/series/arithmetic/test_mul.py +++ b/tests/series/arithmetic/test_mul.py @@ -38,7 +38,7 @@ def test_mul_py_scalar() -> None: def test_mul_py_sequence() -> None: - """Test pd.Series[Any] (int) * Python native sequence""" + """Test pd.Series[Any] (int) * Python native sequences""" b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] check(assert_type(left_i * b, pd.Series), pd.Series) @@ -63,7 +63,7 @@ def test_mul_py_sequence() -> None: def test_mul_numpy_array() -> None: - """Test pd.Series[Any] (int) * numpy array""" + """Test pd.Series[Any] (int) * numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/series/arithmetic/test_sub.py b/tests/series/arithmetic/test_sub.py index 37d9c58fc..d2e70c77d 100644 --- a/tests/series/arithmetic/test_sub.py +++ b/tests/series/arithmetic/test_sub.py @@ -47,7 +47,7 @@ def test_sub_i_py_scalar() -> None: def test_sub_i_py_sequence() -> None: - """Test pd.Series[Any] (int) - Python native sequence""" + """Test pd.Series[Any] (int) - Python native sequences""" b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] check(assert_type(left_i - b, pd.Series), pd.Series) @@ -72,7 +72,7 @@ def test_sub_i_py_sequence() -> None: def test_sub_i_numpy_array() -> None: - """Test pd.Series[Any] (int) - numpy array""" + """Test pd.Series[Any] (int) - numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/series/arithmetic/test_truediv.py b/tests/series/arithmetic/test_truediv.py index e0f0cbf87..3fb747cee 100644 --- a/tests/series/arithmetic/test_truediv.py +++ b/tests/series/arithmetic/test_truediv.py @@ -50,7 +50,7 @@ def test_truediv_py_scalar() -> None: def test_truediv_py_sequence() -> None: - """Test pd.Series[Any] (int) / Python native sequence""" + """Test pd.Series[Any] (int) / Python native sequences""" b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] check(assert_type(left_i / b, pd.Series), pd.Series) @@ -85,7 +85,7 @@ def test_truediv_py_sequence() -> None: def test_truediv_numpy_array() -> None: - """Test pd.Series[Any] (int) / numpy array""" + """Test pd.Series[Any] (int) / numpy arrays""" b = np.array([True, False, True], np.bool_) i = np.array([2, 3, 5], np.int64) f = np.array([1.0, 2.0, 3.0], np.float64) diff --git a/tests/series/arithmetic/timedelta/test_add.py b/tests/series/arithmetic/timedelta/test_add.py index 8a7873677..4aee2bd02 100644 --- a/tests/series/arithmetic/timedelta/test_add.py +++ b/tests/series/arithmetic/timedelta/test_add.py @@ -71,7 +71,7 @@ def test_add_pd_scalar() -> None: def test_add_py_sequence() -> None: - """Test pd.Series[pd.Timedelta] + Python native sequence""" + """Test pd.Series[pd.Timedelta] + Python native sequences""" s = [datetime(2025, 8, 20)] d = [timedelta(seconds=1)] @@ -92,7 +92,7 @@ def test_add_py_sequence() -> None: def test_add_numpy_array() -> None: - """Test pd.Series[pd.Timedelta] + numpy array""" + """Test pd.Series[pd.Timedelta] + numpy arrays""" s = np.array([np.datetime64("2025-08-20")], np.datetime64) d = np.array([np.timedelta64(1, "s")], np.timedelta64) @@ -113,7 +113,7 @@ def test_add_numpy_array() -> None: def test_add_pd_index() -> None: - """Test pd.Series[pd.Timedelta] + pandas Index""" + """Test pd.Series[pd.Timedelta] + pandas Indexes""" s = pd.Index([pd.Timestamp("2025-08-20")]) d = pd.Index([pd.Timedelta(seconds=1)]) diff --git a/tests/series/arithmetic/timedelta/test_sub.py b/tests/series/arithmetic/timedelta/test_sub.py new file mode 100644 index 000000000..c50abed21 --- /dev/null +++ b/tests/series/arithmetic/timedelta/test_sub.py @@ -0,0 +1,163 @@ +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.Timedelta(1, "s")]) # left operand + + +def test_sub_py_scalar() -> None: + """Test pd.Series[pd.Timedelta] - 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.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(s - left, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(d - left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + if TYPE_CHECKING_INVALID_USAGE: + left.sub(s) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.sub(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(left.rsub(s), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(left.rsub(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + +def test_sub_numpy_scalar() -> None: + """Test pd.Series[pd.Timedelta] - 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.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(s - left, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(d - left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + if TYPE_CHECKING_INVALID_USAGE: + left.sub(s) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.sub(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(left.rsub(s), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(left.rsub(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + +def test_sub_pd_scalar() -> None: + """Test pd.Series[pd.Timedelta] - 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.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(s - left, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(d - left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + if TYPE_CHECKING_INVALID_USAGE: + left.sub(s) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.sub(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(left.rsub(s), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(left.rsub(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + +def test_sub_py_sequence() -> None: + """Test pd.Series[pd.Timedelta] - Python native sequences""" + s = [datetime(2025, 8, 20)] + d = [timedelta(seconds=1)] + + if TYPE_CHECKING_INVALID_USAGE: + _0 = left - s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + # Series[Timedelta] - Sequence[timedelta] should work, see pandas-dev/pandas#62353 + _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] + + if TYPE_CHECKING_INVALID_USAGE: + left.sub(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.sub(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(left.rsub(s), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(left.rsub(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + +def test_sub_numpy_array() -> None: + """Test pd.Series[pd.Timedelta] - numpy arrays""" + 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.Timedelta]"), 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`. + check(assert_type(s - left, "npt.NDArray[np.datetime64]"), pd.Series, pd.Timestamp) + check(assert_type(d - left, "npt.NDArray[np.timedelta64]"), pd.Series, pd.Timedelta) + + if TYPE_CHECKING_INVALID_USAGE: + left.sub(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.sub(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(left.rsub(s), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(left.rsub(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + +def test_sub_pd_index() -> None: + """Test pd.Series[pd.Timedelta] - pandas Indexes""" + s = pd.Index([pd.Timestamp("2025-08-20")]) + d = pd.Index([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.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(s - left, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(d - left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + if TYPE_CHECKING_INVALID_USAGE: + left.sub(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.sub(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(left.rsub(s), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(left.rsub(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + +def test_sub_pd_series() -> None: + """Test pd.Series[pd.Timedelta] - 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.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(s - left, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(d - left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + if TYPE_CHECKING_INVALID_USAGE: + left.sub(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.sub(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(left.rsub(s), "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(left.rsub(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) diff --git a/tests/series/arithmetic/timestamp/test_add.py b/tests/series/arithmetic/timestamp/test_add.py index 1fe9a8441..3efdffe82 100644 --- a/tests/series/arithmetic/timestamp/test_add.py +++ b/tests/series/arithmetic/timestamp/test_add.py @@ -86,7 +86,7 @@ def test_add_pd_scalar() -> None: def test_add_py_sequence() -> None: - """Test pd.Series[pd.Timestamp] + Python native sequence""" + """Test pd.Series[pd.Timestamp] + Python native sequences""" s = [datetime(2025, 8, 20)] d = [timedelta(seconds=1)] @@ -108,7 +108,7 @@ def test_add_py_sequence() -> None: def test_add_numpy_array() -> None: - """Test pd.Series[pd.Timestamp] + numpy array""" + """Test pd.Series[pd.Timestamp] + numpy arrays""" s = np.array([np.datetime64("2025-08-20")], np.datetime64) d = np.array([np.timedelta64(1, "s")], np.timedelta64) @@ -135,7 +135,7 @@ def test_add_numpy_array() -> None: def test_add_pd_index() -> None: - """Test pd.Series[pd.Timestamp] + pandas Index""" + """Test pd.Series[pd.Timestamp] + pandas Indexes""" s = pd.Index([pd.Timestamp("2025-08-20")]) d = pd.Index([pd.Timedelta(seconds=1)]) diff --git a/tests/series/arithmetic/timestamp/test_sub.py b/tests/series/arithmetic/timestamp/test_sub.py index 80e2942f6..c680e30eb 100644 --- a/tests/series/arithmetic/timestamp/test_sub.py +++ b/tests/series/arithmetic/timestamp/test_sub.py @@ -77,7 +77,7 @@ def test_sub_pd_scalar() -> None: def test_sub_py_sequence() -> None: - """Test pd.Series[pd.Timestamp] - Python native sequence""" + """Test pd.Series[pd.Timestamp] - Python native sequences""" s = [datetime(2025, 8, 20)] d = [timedelta(seconds=1)] @@ -99,7 +99,7 @@ def test_sub_py_sequence() -> None: def test_sub_numpy_array() -> None: - """Test pd.Series[pd.Timestamp] - numpy array""" + """Test pd.Series[pd.Timestamp] - numpy arrays""" s = np.array([np.datetime64("2025-08-20")], np.datetime64) d = np.array([np.timedelta64(1, "s")], np.timedelta64) @@ -121,6 +121,26 @@ def test_sub_numpy_array() -> None: left.rsub(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] +def test_sub_pd_index() -> None: + """Test pd.Series[pd.Timestamp] - pandas Indexes""" + s = pd.Index([pd.Timestamp("2025-08-20")]) + d = pd.Index([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), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left - d, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + check(assert_type(left.rsub(s), "pd.Series[pd.Timedelta]"), 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")]) diff --git a/tests/test_timefuncs.py b/tests/test_timefuncs.py index ca443729f..45b645346 100644 --- a/tests/test_timefuncs.py +++ b/tests/test_timefuncs.py @@ -190,11 +190,8 @@ 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, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) r2 = r1 / td1 check(assert_type(r2, "pd.Series[float]"), pd.Series, float) - r3 = r1 - td1 - check(assert_type(r3, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) r4 = pd.Timedelta(5, "days") / r1 check(assert_type(r4, "pd.Series[float]"), pd.Series, float) sb = pd.Series([1, 2]) == pd.Series([1, 3]) @@ -208,13 +205,6 @@ def test_timestamp_timedelta_series_arithmetic() -> None: r6 = r1 * 4 check(assert_type(r6, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) - tsp1 = pd.Timestamp("2022-03-05") - dt1 = dt.datetime(2022, 9, 1, 12, 5, 30) - r7 = ts1 - tsp1 - check(assert_type(r7, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) - r8 = ts1 - dt1 - check(assert_type(r8, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) - def test_timestamp_dateoffset_arithmetic() -> None: ts = pd.Timestamp("2022-03-18") From 09aeaf73b6e8aaa7fcf5073e606999f77dc93080 Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Tue, 23 Sep 2025 13:35:05 +0200 Subject: [PATCH 05/13] feat(test): mul --- pandas-stubs/core/arraylike.pyi | 8 - pandas-stubs/core/frame.pyi | 2 + pandas-stubs/core/indexes/base.pyi | 5 +- pandas-stubs/core/indexes/timedeltas.pyi | 4 +- pandas-stubs/core/series.pyi | 8 +- tests/indexes/arithmetic/bool/test_add.py | 2 +- tests/indexes/arithmetic/bool/test_sub.py | 2 +- tests/indexes/arithmetic/complex/test_add.py | 2 +- tests/indexes/arithmetic/complex/test_sub.py | 2 +- tests/indexes/arithmetic/float/test_add.py | 2 +- tests/indexes/arithmetic/float/test_sub.py | 2 +- tests/indexes/arithmetic/int/test_add.py | 2 +- tests/indexes/arithmetic/int/test_sub.py | 2 +- tests/indexes/arithmetic/str/test_add.py | 2 +- tests/indexes/arithmetic/test_add.py | 2 +- tests/indexes/arithmetic/test_sub.py | 2 +- tests/series/arithmetic/bool/test_add.py | 24 +-- tests/series/arithmetic/bool/test_sub.py | 24 +-- tests/series/arithmetic/complex/test_add.py | 24 +-- tests/series/arithmetic/complex/test_sub.py | 36 ++++ tests/series/arithmetic/float/test_add.py | 24 +-- tests/series/arithmetic/float/test_sub.py | 30 +++ tests/series/arithmetic/int/test_add.py | 24 +-- tests/series/arithmetic/int/test_sub.py | 30 +++ tests/series/arithmetic/str/test_add.py | 16 +- tests/series/arithmetic/test_add.py | 28 +-- tests/series/arithmetic/test_sub.py | 33 ++++ tests/series/arithmetic/timedelta/test_add.py | 4 +- tests/series/arithmetic/timedelta/test_mul.py | 172 ++++++++++++++++++ tests/series/arithmetic/timedelta/test_sub.py | 4 +- tests/series/arithmetic/timestamp/test_add.py | 4 +- tests/series/arithmetic/timestamp/test_sub.py | 4 +- tests/test_natype.py | 2 +- tests/test_timefuncs.py | 6 - 34 files changed, 416 insertions(+), 122 deletions(-) create mode 100644 tests/series/arithmetic/timedelta/test_mul.py diff --git a/pandas-stubs/core/arraylike.pyi b/pandas-stubs/core/arraylike.pyi index bdceaf21d..45f5f0fc8 100644 --- a/pandas-stubs/core/arraylike.pyi +++ b/pandas-stubs/core/arraylike.pyi @@ -19,14 +19,6 @@ class OpsMixin: def __rxor__(self, other: Any) -> Self: ... # ------------------------------------------------------------- # Arithmetic Methods - def __mul__(self, other: Any) -> Self: ... - def __rmul__(self, other: Any) -> Self: ... - # Handled by subclasses that specify only the valid values - # that can be passed - # def __truediv__(self, other: Any) -> Self: ... - # def __rtruediv__(self, other: Any) -> Self: ... - # def __floordiv__(self, other: Any) -> Self: ... - # def __rfloordiv__(self, other: Any) -> Self: ... def __mod__(self, other: Any) -> Self: ... def __rmod__(self, other: Any) -> Self: ... def __divmod__(self, other: Any) -> tuple[Self, Self]: ... diff --git a/pandas-stubs/core/frame.pyi b/pandas-stubs/core/frame.pyi index 27fb80f45..5c370d6eb 100644 --- a/pandas-stubs/core/frame.pyi +++ b/pandas-stubs/core/frame.pyi @@ -1806,6 +1806,8 @@ class DataFrame(NDFrame, OpsMixin, _GetItemHack): level: Level | None = ..., fill_value: float | None = None, ) -> Self: ... + def __mul__(self, other: Any) -> Self: ... + def __rmul__(self, other: Any) -> Self: ... @final def add_prefix(self, prefix: _str, axis: Axis | None = None) -> Self: ... @final diff --git a/pandas-stubs/core/indexes/base.pyi b/pandas-stubs/core/indexes/base.pyi index d327a47f0..f72f8e43a 100644 --- a/pandas-stubs/core/indexes/base.pyi +++ b/pandas-stubs/core/indexes/base.pyi @@ -630,7 +630,7 @@ class Index(IndexOpsMixin[S1]): @overload def __sub__(self: Index[Never], other: DatetimeIndex) -> Never: ... @overload - def __sub__(self: Index[Never], other: complex | NumListLike | Index) -> Index: ... + def __sub__(self: Index[Never], other: complex | _ListLike | Index) -> Index: ... @overload def __sub__(self, other: Index[Never]) -> Index: ... @overload @@ -770,7 +770,8 @@ class Index(IndexOpsMixin[S1]): self: Index[int] | Index[float], other: timedelta ) -> TimedeltaIndex: ... @overload - def __mul__(self, other: Any) -> Self: ... + def __mul__(self, other: S1 | Sequence[S1] | Index[S1]) -> Self: ... + def __rmul__(self, other: S1 | Sequence[S1] | Index[S1]) -> Self: ... def __floordiv__( self, other: ( diff --git a/pandas-stubs/core/indexes/timedeltas.pyi b/pandas-stubs/core/indexes/timedeltas.pyi index 42a6fb1a2..0b3392f7c 100644 --- a/pandas-stubs/core/indexes/timedeltas.pyi +++ b/pandas-stubs/core/indexes/timedeltas.pyi @@ -62,9 +62,9 @@ class TimedeltaIndex( def __sub__( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] self, other: dt.timedelta | np.timedelta64 | np_ndarray_td | Self ) -> Self: ... - def __mul__(self, other: num) -> Self: ... + def __mul__(self, other: float) -> Self: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] @overload # type: ignore[override] - def __truediv__(self, other: num | Sequence[float]) -> Self: ... + def __truediv__(self, other: float | Sequence[float]) -> Self: ... @overload def __truediv__( # pyright: ignore[reportIncompatibleMethodOverride] self, other: dt.timedelta | Sequence[dt.timedelta] diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index 82b23a6d1..2d38cd691 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -2457,7 +2457,7 @@ class Series(IndexOpsMixin[S1], NDFrame): self, other: S1 | _ListLike | Series[S1] | datetime | timedelta | date ) -> Series[_bool]: ... @overload - def __mul__( + def __mul__( # type: ignore[overload-overlap] self: Series[Never], other: complex | NumListLike | Series ) -> Series: ... @overload @@ -2532,6 +2532,8 @@ class Series(IndexOpsMixin[S1], NDFrame): ), ) -> Series[Timedelta]: ... @overload + def __mul__(self: Series[Timedelta], other: np_ndarray_complex) -> Never: ... + @overload def __mul__( self: Series[Timedelta], other: ( @@ -2704,7 +2706,7 @@ class Series(IndexOpsMixin[S1], NDFrame): axis: AxisIndex | None = 0, ) -> Series[Timedelta]: ... @overload - def __rmul__( + def __rmul__( # type: ignore[overload-overlap] self: Series[Never], other: complex | NumListLike | Series ) -> Series: ... @overload @@ -2778,6 +2780,8 @@ class Series(IndexOpsMixin[S1], NDFrame): ), ) -> Series[Timedelta]: ... @overload + def __rmul__(self: Series[Timedelta], other: np_ndarray_complex) -> Never: ... + @overload def __rmul__( self: Series[Timedelta], other: ( diff --git a/tests/indexes/arithmetic/bool/test_add.py b/tests/indexes/arithmetic/bool/test_add.py index b212c2676..f9bd52b9f 100644 --- a/tests/indexes/arithmetic/bool/test_add.py +++ b/tests/indexes/arithmetic/bool/test_add.py @@ -66,7 +66,7 @@ def test_add_numpy_array() -> None: def test_add_pd_index() -> None: - """Test pd.Index[bool] + pandas index""" + """Test pd.Index[bool] + pandas indexes""" b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) f = pd.Index([1.0, 2.0, 3.0]) diff --git a/tests/indexes/arithmetic/bool/test_sub.py b/tests/indexes/arithmetic/bool/test_sub.py index 4bc27fd04..b0ce9cea2 100644 --- a/tests/indexes/arithmetic/bool/test_sub.py +++ b/tests/indexes/arithmetic/bool/test_sub.py @@ -76,7 +76,7 @@ def test_sub_numpy_array() -> None: def test_sub_pd_index() -> None: - """Test pd.Index[bool] - pandas index""" + """Test pd.Index[bool] - pandas indexes""" b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) f = pd.Index([1.0, 2.0, 3.0]) diff --git a/tests/indexes/arithmetic/complex/test_add.py b/tests/indexes/arithmetic/complex/test_add.py index ae6d35b9b..22a251156 100644 --- a/tests/indexes/arithmetic/complex/test_add.py +++ b/tests/indexes/arithmetic/complex/test_add.py @@ -67,7 +67,7 @@ def test_add_numpy_array() -> None: def test_add_pd_index() -> None: - """Test pd.Index[complex] + pandas index""" + """Test pd.Index[complex] + pandas indexes""" b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) f = pd.Index([1.0, 2.0, 3.0]) diff --git a/tests/indexes/arithmetic/complex/test_sub.py b/tests/indexes/arithmetic/complex/test_sub.py index 114370096..4130c35e5 100644 --- a/tests/indexes/arithmetic/complex/test_sub.py +++ b/tests/indexes/arithmetic/complex/test_sub.py @@ -69,7 +69,7 @@ def test_sub_numpy_array() -> None: def test_sub_pd_index() -> None: - """Test pd.Index[complex] - pandas index""" + """Test pd.Index[complex] - pandas indexes""" b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) f = pd.Index([1.0, 2.0, 3.0]) diff --git a/tests/indexes/arithmetic/float/test_add.py b/tests/indexes/arithmetic/float/test_add.py index 737717f6f..86f5b3256 100644 --- a/tests/indexes/arithmetic/float/test_add.py +++ b/tests/indexes/arithmetic/float/test_add.py @@ -65,7 +65,7 @@ def test_add_numpy_array() -> None: def test_add_pd_index() -> None: - """Test pd.Index[float] + pandas index""" + """Test pd.Index[float] + pandas indexes""" b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) f = pd.Index([1.0, 2.0, 3.0]) diff --git a/tests/indexes/arithmetic/float/test_sub.py b/tests/indexes/arithmetic/float/test_sub.py index 28c1267ec..e9a709f02 100644 --- a/tests/indexes/arithmetic/float/test_sub.py +++ b/tests/indexes/arithmetic/float/test_sub.py @@ -67,7 +67,7 @@ def test_sub_numpy_array() -> None: def test_sub_pd_index() -> None: - """Test pd.Index[float] - pandas index""" + """Test pd.Index[float] - pandas indexes""" b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) f = pd.Index([1.0, 2.0, 3.0]) diff --git a/tests/indexes/arithmetic/int/test_add.py b/tests/indexes/arithmetic/int/test_add.py index d24242aa0..5fac65e11 100644 --- a/tests/indexes/arithmetic/int/test_add.py +++ b/tests/indexes/arithmetic/int/test_add.py @@ -65,7 +65,7 @@ def test_add_numpy_array() -> None: def test_add_pd_index() -> None: - """Test pd.Index[int] + pandas index""" + """Test pd.Index[int] + pandas indexes""" b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) f = pd.Index([1.0, 2.0, 3.0]) diff --git a/tests/indexes/arithmetic/int/test_sub.py b/tests/indexes/arithmetic/int/test_sub.py index a85b8b3c4..783371459 100644 --- a/tests/indexes/arithmetic/int/test_sub.py +++ b/tests/indexes/arithmetic/int/test_sub.py @@ -67,7 +67,7 @@ def test_sub_numpy_array() -> None: def test_sub_pd_index() -> None: - """Test pd.Index[int] - pandas index""" + """Test pd.Index[int] - pandas indexes""" b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) f = pd.Index([1.0, 2.0, 3.0]) diff --git a/tests/indexes/arithmetic/str/test_add.py b/tests/indexes/arithmetic/str/test_add.py index 4b4b249bc..aa26052df 100644 --- a/tests/indexes/arithmetic/str/test_add.py +++ b/tests/indexes/arithmetic/str/test_add.py @@ -75,7 +75,7 @@ def test_add_numpy_array() -> None: def test_add_pd_index() -> None: - """Test pd.Index[str] + pandas index""" + """Test pd.Index[str] + pandas indexes""" i = pd.Index([3, 5, 8]) r0 = pd.Index(["a", "bc", "def"]) diff --git a/tests/indexes/arithmetic/test_add.py b/tests/indexes/arithmetic/test_add.py index 89bfd0653..76ad1f40a 100644 --- a/tests/indexes/arithmetic/test_add.py +++ b/tests/indexes/arithmetic/test_add.py @@ -82,7 +82,7 @@ def test_add_i_numpy_array() -> None: def test_add_i_pd_index() -> None: - """Test pd.Index[Any] (int) + pandas index""" + """Test pd.Index[Any] (int) + pandas indexes""" a = pd.MultiIndex.from_tuples([(1,), (2,), (3,)]).levels[0] b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) diff --git a/tests/indexes/arithmetic/test_sub.py b/tests/indexes/arithmetic/test_sub.py index b5188a5a2..8129f0b05 100644 --- a/tests/indexes/arithmetic/test_sub.py +++ b/tests/indexes/arithmetic/test_sub.py @@ -78,7 +78,7 @@ def test_sub_i_numpy_array() -> None: def test_sub_i_pd_index() -> None: - """Test pd.Index[Any] (int) - pandas index""" + """Test pd.Index[Any] (int) - pandas indexes""" a = pd.MultiIndex.from_tuples([(1,), (2,), (3,)]).levels[0] b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) diff --git a/tests/series/arithmetic/bool/test_add.py b/tests/series/arithmetic/bool/test_add.py index ce2ec70af..59b0a8586 100644 --- a/tests/series/arithmetic/bool/test_add.py +++ b/tests/series/arithmetic/bool/test_add.py @@ -99,12 +99,12 @@ def test_add_numpy_array() -> None: ) -def test_add_pd_series() -> None: - """Test pd.Series[bool] + pandas series""" - b = pd.Series([True, False, True]) - i = pd.Series([2, 3, 5]) - f = pd.Series([1.0, 2.0, 3.0]) - c = pd.Series([1.1j, 2.2j, 4.1j]) +def test_add_pd_index() -> None: + """Test pd.Series[bool] + pandas indexes""" + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) check(assert_type(left + b, "pd.Series[bool]"), pd.Series, np.bool_) check(assert_type(left + i, "pd.Series[int]"), pd.Series, np.integer) @@ -129,12 +129,12 @@ def test_add_pd_series() -> None: ) -def test_add_pd_index() -> None: - """Test pd.Series[bool] + pandas index""" - b = pd.Index([True, False, True]) - i = pd.Index([2, 3, 5]) - f = pd.Index([1.0, 2.0, 3.0]) - c = pd.Index([1.1j, 2.2j, 4.1j]) +def test_add_pd_series() -> None: + """Test pd.Series[bool] + pandas series""" + b = pd.Series([True, False, True]) + i = pd.Series([2, 3, 5]) + f = pd.Series([1.0, 2.0, 3.0]) + c = pd.Series([1.1j, 2.2j, 4.1j]) check(assert_type(left + b, "pd.Series[bool]"), pd.Series, np.bool_) check(assert_type(left + i, "pd.Series[int]"), pd.Series, np.integer) diff --git a/tests/series/arithmetic/bool/test_sub.py b/tests/series/arithmetic/bool/test_sub.py index df67743bb..d2a7f0a1c 100644 --- a/tests/series/arithmetic/bool/test_sub.py +++ b/tests/series/arithmetic/bool/test_sub.py @@ -117,12 +117,12 @@ def test_sub_numpy_array() -> None: ) -def test_sub_pd_series() -> None: - """Test pd.Series[bool] - pandas series""" - b = pd.Series([True, False, True]) - i = pd.Series([2, 3, 5]) - f = pd.Series([1.0, 2.0, 3.0]) - c = pd.Series([1.1j, 2.2j, 4.1j]) +def test_sub_pd_index() -> None: + """Test pd.Series[bool] - pandas indexes""" + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) if TYPE_CHECKING_INVALID_USAGE: _0 = left - b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] @@ -151,12 +151,12 @@ def test_sub_pd_series() -> None: ) -def test_sub_pd_index() -> None: - """Test pd.Series[bool] - pandas index""" - b = pd.Index([True, False, True]) - i = pd.Index([2, 3, 5]) - f = pd.Index([1.0, 2.0, 3.0]) - c = pd.Index([1.1j, 2.2j, 4.1j]) +def test_sub_pd_series() -> None: + """Test pd.Series[bool] - pandas series""" + b = pd.Series([True, False, True]) + i = pd.Series([2, 3, 5]) + f = pd.Series([1.0, 2.0, 3.0]) + c = pd.Series([1.1j, 2.2j, 4.1j]) if TYPE_CHECKING_INVALID_USAGE: _0 = left - b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] diff --git a/tests/series/arithmetic/complex/test_add.py b/tests/series/arithmetic/complex/test_add.py index a782b4d63..85c6b3a2d 100644 --- a/tests/series/arithmetic/complex/test_add.py +++ b/tests/series/arithmetic/complex/test_add.py @@ -119,12 +119,12 @@ def test_add_numpy_array() -> None: ) -def test_add_pd_series() -> None: - """Test pd.Series[complex] + pandas series""" - b = pd.Series([True, False, True]) - i = pd.Series([2, 3, 5]) - f = pd.Series([1.0, 2.0, 3.0]) - c = pd.Series([1.1j, 2.2j, 4.1j]) +def test_add_pd_index() -> None: + """Test pd.Series[complex] + pandas indexes""" + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) check(assert_type(left + b, "pd.Series[complex]"), pd.Series, np.complexfloating) check(assert_type(left + i, "pd.Series[complex]"), pd.Series, np.complexfloating) @@ -155,12 +155,12 @@ def test_add_pd_series() -> None: ) -def test_add_pd_index() -> None: - """Test pd.Series[complex] + pandas index""" - b = pd.Index([True, False, True]) - i = pd.Index([2, 3, 5]) - f = pd.Index([1.0, 2.0, 3.0]) - c = pd.Index([1.1j, 2.2j, 4.1j]) +def test_add_pd_series() -> None: + """Test pd.Series[complex] + pandas series""" + b = pd.Series([True, False, True]) + i = pd.Series([2, 3, 5]) + f = pd.Series([1.0, 2.0, 3.0]) + c = pd.Series([1.1j, 2.2j, 4.1j]) check(assert_type(left + b, "pd.Series[complex]"), pd.Series, np.complexfloating) check(assert_type(left + i, "pd.Series[complex]"), pd.Series, np.complexfloating) diff --git a/tests/series/arithmetic/complex/test_sub.py b/tests/series/arithmetic/complex/test_sub.py index 102f65309..4f688da2e 100644 --- a/tests/series/arithmetic/complex/test_sub.py +++ b/tests/series/arithmetic/complex/test_sub.py @@ -121,6 +121,42 @@ def test_sub_numpy_array() -> None: ) +def test_sub_pd_index() -> None: + """Test pd.Series[complex] - pandas indexes""" + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) + + check(assert_type(left - b, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left - i, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left - f, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left - c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(b - left, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(i - left, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(f - left, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(c - left, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.sub(b), "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left.sub(i), "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left.sub(f), "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left.sub(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check( + assert_type(left.rsub(b), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + check( + assert_type(left.rsub(i), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + check( + assert_type(left.rsub(f), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + check( + assert_type(left.rsub(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + + def test_sub_pd_series() -> None: """Test pd.Series[complex] - pandas series""" b = pd.Series([True, False, True]) diff --git a/tests/series/arithmetic/float/test_add.py b/tests/series/arithmetic/float/test_add.py index 5feeb50be..75b180009 100644 --- a/tests/series/arithmetic/float/test_add.py +++ b/tests/series/arithmetic/float/test_add.py @@ -99,12 +99,12 @@ def test_add_numpy_array() -> None: ) -def test_add_pd_series() -> None: - """Test pd.Series[float] + pandas series""" - b = pd.Series([True, False, True]) - i = pd.Series([2, 3, 5]) - f = pd.Series([1.0, 2.0, 3.0]) - c = pd.Series([1.1j, 2.2j, 4.1j]) +def test_add_pd_index() -> None: + """Test pd.Series[float] + pandas indexes""" + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) check(assert_type(left + b, "pd.Series[float]"), pd.Series, np.floating) check(assert_type(left + i, "pd.Series[float]"), pd.Series, np.floating) @@ -129,12 +129,12 @@ def test_add_pd_series() -> None: ) -def test_add_pd_index() -> None: - """Test pd.Series[float] + pandas index""" - b = pd.Index([True, False, True]) - i = pd.Index([2, 3, 5]) - f = pd.Index([1.0, 2.0, 3.0]) - c = pd.Index([1.1j, 2.2j, 4.1j]) +def test_add_pd_series() -> None: + """Test pd.Series[float] + pandas series""" + b = pd.Series([True, False, True]) + i = pd.Series([2, 3, 5]) + f = pd.Series([1.0, 2.0, 3.0]) + c = pd.Series([1.1j, 2.2j, 4.1j]) check(assert_type(left + b, "pd.Series[float]"), pd.Series, np.floating) check(assert_type(left + i, "pd.Series[float]"), pd.Series, np.floating) diff --git a/tests/series/arithmetic/float/test_sub.py b/tests/series/arithmetic/float/test_sub.py index 08abcd178..d3b251493 100644 --- a/tests/series/arithmetic/float/test_sub.py +++ b/tests/series/arithmetic/float/test_sub.py @@ -101,6 +101,36 @@ def test_sub_numpy_array() -> None: ) +def test_sub_pd_index() -> None: + """Test pd.Series[float] - pandas indexes""" + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) + + check(assert_type(left - b, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left - i, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left - f, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left - c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(b - left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(i - left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(f - left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(c - left, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.sub(b), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.sub(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.sub(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.sub(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.rsub(b), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.rsub(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.rsub(f), "pd.Series[float]"), pd.Series, np.floating) + check( + assert_type(left.rsub(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + + def test_sub_pd_series() -> None: """Test pd.Series[float] - pandas series""" b = pd.Series([True, False, True]) diff --git a/tests/series/arithmetic/int/test_add.py b/tests/series/arithmetic/int/test_add.py index ef25fd8c3..5847a0149 100644 --- a/tests/series/arithmetic/int/test_add.py +++ b/tests/series/arithmetic/int/test_add.py @@ -99,12 +99,12 @@ def test_add_numpy_array() -> None: ) -def test_add_pd_series() -> None: - """Test pd.Series[int] + pandas series""" - b = pd.Series([True, False, True]) - i = pd.Series([2, 3, 5]) - f = pd.Series([1.0, 2.0, 3.0]) - c = pd.Series([1.1j, 2.2j, 4.1j]) +def test_add_pd_index() -> None: + """Test pd.Series[int] + pandas indexes""" + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) check(assert_type(left + b, "pd.Series[int]"), pd.Series, np.integer) check(assert_type(left + i, "pd.Series[int]"), pd.Series, np.integer) @@ -129,12 +129,12 @@ def test_add_pd_series() -> None: ) -def test_add_pd_index() -> None: - """Test pd.Series[int] + pandas index""" - b = pd.Index([True, False, True]) - i = pd.Index([2, 3, 5]) - f = pd.Index([1.0, 2.0, 3.0]) - c = pd.Index([1.1j, 2.2j, 4.1j]) +def test_add_pd_series() -> None: + """Test pd.Series[int] + pandas series""" + b = pd.Series([True, False, True]) + i = pd.Series([2, 3, 5]) + f = pd.Series([1.0, 2.0, 3.0]) + c = pd.Series([1.1j, 2.2j, 4.1j]) check(assert_type(left + b, "pd.Series[int]"), pd.Series, np.integer) check(assert_type(left + i, "pd.Series[int]"), pd.Series, np.integer) diff --git a/tests/series/arithmetic/int/test_sub.py b/tests/series/arithmetic/int/test_sub.py index 360886881..4a9170c3d 100644 --- a/tests/series/arithmetic/int/test_sub.py +++ b/tests/series/arithmetic/int/test_sub.py @@ -101,6 +101,36 @@ def test_sub_numpy_array() -> None: ) +def test_sub_pd_index() -> None: + """Test pd.Series[int] - pandas indexes""" + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) + + check(assert_type(left - b, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left - i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left - f, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left - c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(b - left, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(i - left, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(f - left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(c - left, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.sub(b), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.sub(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.sub(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.sub(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.rsub(b), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.rsub(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.rsub(f), "pd.Series[float]"), pd.Series, np.floating) + check( + assert_type(left.rsub(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + + def test_sub_pd_series() -> None: """Test pd.Series[int] - pandas series""" b = pd.Series([True, False, True]) diff --git a/tests/series/arithmetic/str/test_add.py b/tests/series/arithmetic/str/test_add.py index 917e504c6..34ecf4c0d 100644 --- a/tests/series/arithmetic/str/test_add.py +++ b/tests/series/arithmetic/str/test_add.py @@ -100,10 +100,10 @@ def test_add_numpy_array() -> None: check(assert_type(left.radd(r0), "pd.Series[str]"), pd.Series, str) -def test_add_pd_series() -> None: - """Test pd.Series[str] + pandas series""" - i = pd.Series([3, 5, 8]) - r0 = pd.Series(["a", "bc", "def"]) +def test_add_pd_index() -> None: + """Test pd.Series[str] + pandas indexes""" + i = pd.Index([3, 5, 8]) + r0 = pd.Index(["a", "bc", "def"]) if TYPE_CHECKING_INVALID_USAGE: _0 = left + i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] @@ -122,10 +122,10 @@ def test_add_pd_series() -> None: check(assert_type(left.radd(r0), "pd.Series[str]"), pd.Series, str) -def test_add_pd_index() -> None: - """Test pd.Series[str] + pandas index""" - i = pd.Index([3, 5, 8]) - r0 = pd.Index(["a", "bc", "def"]) +def test_add_pd_series() -> None: + """Test pd.Series[str] + pandas series""" + i = pd.Series([3, 5, 8]) + r0 = pd.Series(["a", "bc", "def"]) if TYPE_CHECKING_INVALID_USAGE: _0 = left + i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] diff --git a/tests/series/arithmetic/test_add.py b/tests/series/arithmetic/test_add.py index 689ab5751..7cb268c69 100644 --- a/tests/series/arithmetic/test_add.py +++ b/tests/series/arithmetic/test_add.py @@ -117,13 +117,13 @@ def test_add_i_numpy_array() -> None: check(assert_type(left_i.radd(c), pd.Series), pd.Series) -def test_add_i_pd_series() -> None: - """Test pd.Series[Any] (int) + pandas series""" - a = pd.DataFrame({"a": [1, 2, 3]})["a"] - b = pd.Series([True, False, True]) - i = pd.Series([2, 3, 5]) - f = pd.Series([1.0, 2.0, 3.0]) - c = pd.Series([1.1j, 2.2j, 4.1j]) +def test_add_i_pd_index() -> None: + """Test pd.Series[Any] (int) + pandas indexes""" + a = pd.MultiIndex.from_tuples([(1,), (2,), (3,)]).levels[0] + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) check(assert_type(left_i + a, pd.Series), pd.Series) check(assert_type(left_i + b, pd.Series), pd.Series) @@ -150,13 +150,13 @@ def test_add_i_pd_series() -> None: check(assert_type(left_i.radd(c), pd.Series), pd.Series) -def test_add_i_pd_index() -> None: - """Test pd.Series[Any] (int) + pandas index""" - a = pd.MultiIndex.from_tuples([(1,), (2,), (3,)]).levels[0] - b = pd.Index([True, False, True]) - i = pd.Index([2, 3, 5]) - f = pd.Index([1.0, 2.0, 3.0]) - c = pd.Index([1.1j, 2.2j, 4.1j]) +def test_add_i_pd_series() -> None: + """Test pd.Series[Any] (int) + pandas series""" + a = pd.DataFrame({"a": [1, 2, 3]})["a"] + b = pd.Series([True, False, True]) + i = pd.Series([2, 3, 5]) + f = pd.Series([1.0, 2.0, 3.0]) + c = pd.Series([1.1j, 2.2j, 4.1j]) check(assert_type(left_i + a, pd.Series), pd.Series) check(assert_type(left_i + b, pd.Series), pd.Series) diff --git a/tests/series/arithmetic/test_sub.py b/tests/series/arithmetic/test_sub.py index d2e70c77d..a07b35658 100644 --- a/tests/series/arithmetic/test_sub.py +++ b/tests/series/arithmetic/test_sub.py @@ -115,6 +115,39 @@ def test_sub_i_numpy_array() -> None: check(assert_type(left_i.rsub(c), pd.Series), pd.Series) +def test_sub_i_pd_index() -> None: + """Test pd.Series[Any] (int) - pandas indexes""" + a = pd.MultiIndex.from_tuples([(1,), (2,), (3,)]).levels[0] + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) + + check(assert_type(left_i - a, pd.Series), pd.Series) + check(assert_type(left_i - b, pd.Series), pd.Series) + check(assert_type(left_i - i, pd.Series), pd.Series) + check(assert_type(left_i - f, pd.Series), pd.Series) + check(assert_type(left_i - c, pd.Series), pd.Series) + + check(assert_type(a - left_i, pd.Series), pd.Series) + check(assert_type(b - left_i, pd.Series), pd.Series) + check(assert_type(i - left_i, pd.Series), pd.Series) + check(assert_type(f - left_i, pd.Series), pd.Series) + check(assert_type(c - left_i, pd.Series), pd.Series) + + check(assert_type(left_i.sub(a), pd.Series), pd.Series) + check(assert_type(left_i.sub(b), pd.Series), pd.Series) + check(assert_type(left_i.sub(i), pd.Series), pd.Series) + check(assert_type(left_i.sub(f), pd.Series), pd.Series) + check(assert_type(left_i.sub(c), pd.Series), pd.Series) + + check(assert_type(left_i.rsub(a), pd.Series), pd.Series) + check(assert_type(left_i.rsub(b), pd.Series), pd.Series) + check(assert_type(left_i.rsub(i), pd.Series), pd.Series) + check(assert_type(left_i.rsub(f), pd.Series), pd.Series) + check(assert_type(left_i.rsub(c), pd.Series), pd.Series) + + def test_sub_i_pd_series() -> None: """Test pd.Series[Any] (int) - pandas series""" a = pd.DataFrame({"a": [1, 2, 3]})["a"] diff --git a/tests/series/arithmetic/timedelta/test_add.py b/tests/series/arithmetic/timedelta/test_add.py index 4aee2bd02..671767546 100644 --- a/tests/series/arithmetic/timedelta/test_add.py +++ b/tests/series/arithmetic/timedelta/test_add.py @@ -113,7 +113,7 @@ def test_add_numpy_array() -> None: def test_add_pd_index() -> None: - """Test pd.Series[pd.Timedelta] + pandas Indexes""" + """Test pd.Series[pd.Timedelta] + pandas indexes""" s = pd.Index([pd.Timestamp("2025-08-20")]) d = pd.Index([pd.Timedelta(seconds=1)]) @@ -131,7 +131,7 @@ def test_add_pd_index() -> None: def test_add_pd_series() -> None: - """Test pd.Series[pd.Timedelta] + pandas Series""" + """Test pd.Series[pd.Timedelta] + pandas series""" s = pd.Series([pd.Timestamp("2025-08-20")]) d = pd.Series([pd.Timedelta(seconds=1)]) diff --git a/tests/series/arithmetic/timedelta/test_mul.py b/tests/series/arithmetic/timedelta/test_mul.py new file mode 100644 index 000000000..0a67cb618 --- /dev/null +++ b/tests/series/arithmetic/timedelta/test_mul.py @@ -0,0 +1,172 @@ +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.Timedelta(1, "s")]) # left operand + + +def test_mul_py_scalar() -> None: + """Test pd.Series[pd.Timedelta] * Python native scalars""" + b, i, f, c = True, 1, 1.0, 1j + + check(assert_type(left * b, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left * i, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left * f, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + _0 = left * c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + check(assert_type(b * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(i * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(f * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + _1 = c * left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + check(assert_type(left.mul(b), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left.mul(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left.mul(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + left.mul(c) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + + check(assert_type(left.rmul(b), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left.rmul(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left.rmul(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + left.rmul(c) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + + +def test_mul_py_sequence() -> None: + """Test pd.Series[pd.Timedelta] * Python native sequences""" + b, i, f, c = [True], [2], [1.5], [1.7j] + + check(assert_type(left * b, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left * i, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left * f, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + _0 = left * c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + check(assert_type(b * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(i * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(f * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + _1 = c * left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + check(assert_type(left.mul(b), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left.mul(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left.mul(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + left.mul(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + check(assert_type(left.rmul(b), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left.rmul(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left.rmul(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + left.rmul(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + +def test_mul_numpy_array() -> None: + """Test pd.Series[pd.Timedelta] * numpy arrays""" + b = np.array([True], np.bool_) + i = np.array([2], np.int64) + f = np.array([1.5], np.float64) + c = np.array([1.7j], np.complex128) + + check(assert_type(left * b, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left * i, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left * f, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + assert_type(left * c, Never) + + # `numpy` typing gives the corresponding `ndarray`s in the static type + # checking, where our `__rmul__` cannot override. At runtime, they return + # `Series` with the correct element type. + check(assert_type(b * left, "npt.NDArray[np.bool_]"), pd.Series, pd.Timedelta) + check(assert_type(i * left, "npt.NDArray[np.int64]"), pd.Series, pd.Timedelta) + check(assert_type(f * left, "npt.NDArray[np.float64]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + # We made it Never, but numpy takes over + assert_type(c * left, "npt.NDArray[np.complex128]") + + check(assert_type(left.mul(b), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left.mul(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left.mul(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + left.mul(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + check(assert_type(left.rmul(b), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left.rmul(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left.rmul(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + left.rmul(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + +def test_mul_pd_index() -> None: + """Test pd.Series[pd.Timedelta] * pandas indexes""" + b = pd.Index([True]) + i = pd.Index([2]) + f = pd.Index([1.5]) + c = pd.Index([1.7j]) + + check(assert_type(left * b, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left * i, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left * f, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + _0 = left * c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + check(assert_type(b * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(i * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(f * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + _1 = c * left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + check(assert_type(left.mul(b), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left.mul(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left.mul(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + left.mul(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + check(assert_type(left.rmul(b), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left.rmul(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left.rmul(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + left.rmul(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + +def test_mul_pd_series() -> None: + """Test pd.Series[pd.Timedelta] * pandas series""" + b = pd.Series([True]) + i = pd.Series([2]) + f = pd.Series([1.5]) + c = pd.Series([1.7j]) + + check(assert_type(left * b, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left * i, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left * f, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + _0 = left * c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + check(assert_type(b * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(i * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(f * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + _1 = c * left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + check(assert_type(left.mul(b), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left.mul(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left.mul(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + left.mul(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + check(assert_type(left.rmul(b), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left.rmul(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left.rmul(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + left.rmul(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] diff --git a/tests/series/arithmetic/timedelta/test_sub.py b/tests/series/arithmetic/timedelta/test_sub.py index c50abed21..bedacae1e 100644 --- a/tests/series/arithmetic/timedelta/test_sub.py +++ b/tests/series/arithmetic/timedelta/test_sub.py @@ -124,7 +124,7 @@ def test_sub_numpy_array() -> None: def test_sub_pd_index() -> None: - """Test pd.Series[pd.Timedelta] - pandas Indexes""" + """Test pd.Series[pd.Timedelta] - pandas indexes""" s = pd.Index([pd.Timestamp("2025-08-20")]) d = pd.Index([pd.Timedelta(seconds=1)]) @@ -144,7 +144,7 @@ def test_sub_pd_index() -> None: def test_sub_pd_series() -> None: - """Test pd.Series[pd.Timedelta] - pandas Series""" + """Test pd.Series[pd.Timedelta] - pandas series""" s = pd.Series([pd.Timestamp("2025-08-20")]) d = pd.Series([pd.Timedelta(seconds=1)]) diff --git a/tests/series/arithmetic/timestamp/test_add.py b/tests/series/arithmetic/timestamp/test_add.py index 3efdffe82..ebee459e9 100644 --- a/tests/series/arithmetic/timestamp/test_add.py +++ b/tests/series/arithmetic/timestamp/test_add.py @@ -135,7 +135,7 @@ def test_add_numpy_array() -> None: def test_add_pd_index() -> None: - """Test pd.Series[pd.Timestamp] + pandas Indexes""" + """Test pd.Series[pd.Timestamp] + pandas indexes""" s = pd.Index([pd.Timestamp("2025-08-20")]) d = pd.Index([pd.Timedelta(seconds=1)]) @@ -157,7 +157,7 @@ def test_add_pd_index() -> None: def test_add_pd_series() -> None: - """Test pd.Series[pd.Timestamp] + pandas Series""" + """Test pd.Series[pd.Timestamp] + pandas series""" s = pd.Series([pd.Timestamp("2025-08-20")]) d = pd.Series([pd.Timedelta(seconds=1)]) diff --git a/tests/series/arithmetic/timestamp/test_sub.py b/tests/series/arithmetic/timestamp/test_sub.py index c680e30eb..b041f9e5a 100644 --- a/tests/series/arithmetic/timestamp/test_sub.py +++ b/tests/series/arithmetic/timestamp/test_sub.py @@ -122,7 +122,7 @@ def test_sub_numpy_array() -> None: def test_sub_pd_index() -> None: - """Test pd.Series[pd.Timestamp] - pandas Indexes""" + """Test pd.Series[pd.Timestamp] - pandas indexes""" s = pd.Index([pd.Timestamp("2025-08-20")]) d = pd.Index([pd.Timedelta(seconds=1)]) @@ -142,7 +142,7 @@ def test_sub_pd_index() -> None: def test_sub_pd_series() -> None: - """Test pd.Series[pd.Timestamp] - pandas Series""" + """Test pd.Series[pd.Timestamp] - pandas series""" s = pd.Series([pd.Timestamp("2025-08-20")]) d = pd.Series([pd.Timedelta(seconds=1)]) diff --git a/tests/test_natype.py b/tests/test_natype.py index e4a02055f..bef677d66 100644 --- a/tests/test_natype.py +++ b/tests/test_natype.py @@ -43,7 +43,7 @@ def test_arithmetic() -> None: # __rmul__ check(assert_type(s_int * na, pd.Series), pd.Series) - check(assert_type(idx_int * na, "pd.Index[int]"), pd.Index) + check(assert_type(idx_int * na, pd.Index), pd.Index) check(assert_type(1 * na, NAType), NAType) # __matmul__ diff --git a/tests/test_timefuncs.py b/tests/test_timefuncs.py index 45b645346..06e3e1474 100644 --- a/tests/test_timefuncs.py +++ b/tests/test_timefuncs.py @@ -1713,18 +1713,12 @@ 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, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) td1 = pd.Timedelta(1, "D") - check(assert_type(s2 - td1, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) # GH 758 s4 = s1.astype(object) check(assert_type(s4 - td1, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) td = np.timedelta64(1, "D") - 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), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) - check(assert_type((s3 + td), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type((s3 / td), "pd.Series[float]"), pd.Series, float) if TYPE_CHECKING_INVALID_USAGE: r1 = s1 * td # type: ignore[operator] # pyright: ignore[reportOperatorIssue] From a916a31a2dc8a60b4dee1603fbe8e71d0f3039c6 Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Wed, 24 Sep 2025 21:23:17 +0200 Subject: [PATCH 06/13] feat(test): truediv --- pandas-stubs/core/indexes/base.pyi | 44 +-- pandas-stubs/core/series.pyi | 186 ++++++--- tests/indexes/arithmetic/bool/test_add.py | 2 +- tests/indexes/arithmetic/bool/test_sub.py | 2 +- tests/indexes/arithmetic/complex/test_add.py | 2 +- tests/indexes/arithmetic/complex/test_sub.py | 2 +- tests/indexes/arithmetic/float/test_add.py | 2 +- tests/indexes/arithmetic/float/test_sub.py | 2 +- tests/indexes/arithmetic/int/test_add.py | 2 +- tests/indexes/arithmetic/int/test_sub.py | 2 +- tests/indexes/arithmetic/str/test_add.py | 2 +- tests/indexes/arithmetic/test_add.py | 2 +- tests/indexes/arithmetic/test_sub.py | 2 +- tests/series/arithmetic/bool/test_add.py | 4 +- tests/series/arithmetic/bool/test_mul.py | 32 +- tests/series/arithmetic/bool/test_sub.py | 4 +- tests/series/arithmetic/bool/test_truediv.py | 56 ++- tests/series/arithmetic/complex/test_add.py | 4 +- tests/series/arithmetic/complex/test_mul.py | 38 +- tests/series/arithmetic/complex/test_sub.py | 4 +- .../series/arithmetic/complex/test_truediv.py | 80 +++- tests/series/arithmetic/float/test_add.py | 4 +- tests/series/arithmetic/float/test_mul.py | 32 +- tests/series/arithmetic/float/test_sub.py | 4 +- tests/series/arithmetic/float/test_truediv.py | 50 ++- tests/series/arithmetic/int/test_add.py | 4 +- tests/series/arithmetic/int/test_mul.py | 32 +- tests/series/arithmetic/int/test_sub.py | 4 +- tests/series/arithmetic/int/test_truediv.py | 50 ++- tests/series/arithmetic/str/test_add.py | 4 +- tests/series/arithmetic/test_add.py | 4 +- tests/series/arithmetic/test_mul.py | 35 +- tests/series/arithmetic/test_sub.py | 4 +- tests/series/arithmetic/test_truediv.py | 47 ++- tests/series/arithmetic/timedelta/test_add.py | 4 +- tests/series/arithmetic/timedelta/test_mul.py | 27 +- tests/series/arithmetic/timedelta/test_sub.py | 4 +- .../arithmetic/timedelta/test_truediv.py | 367 ++++++++++++++++++ tests/series/arithmetic/timestamp/test_add.py | 4 +- tests/series/arithmetic/timestamp/test_sub.py | 4 +- tests/test_timefuncs.py | 15 - 41 files changed, 1020 insertions(+), 153 deletions(-) create mode 100644 tests/series/arithmetic/timedelta/test_truediv.py diff --git a/pandas-stubs/core/indexes/base.pyi b/pandas-stubs/core/indexes/base.pyi index f72f8e43a..926785756 100644 --- a/pandas-stubs/core/indexes/base.pyi +++ b/pandas-stubs/core/indexes/base.pyi @@ -770,47 +770,23 @@ class Index(IndexOpsMixin[S1]): self: Index[int] | Index[float], other: timedelta ) -> TimedeltaIndex: ... @overload - def __mul__(self, other: S1 | Sequence[S1] | Index[S1]) -> Self: ... - def __rmul__(self, other: S1 | Sequence[S1] | Index[S1]) -> Self: ... + def __mul__( + self, other: float | Sequence[float] | Index[int] | Index[float] + ) -> Self: ... + def __rmul__( + self, other: float | Sequence[float] | Index[int] | Index[float] + ) -> Self: ... def __floordiv__( - self, - other: ( - float - | IndexOpsMixin[int] - | IndexOpsMixin[float] - | Sequence[int] - | Sequence[float] - ), + self, other: float | Sequence[float] | Index[int] | Index[float] ) -> Self: ... def __rfloordiv__( - self, - other: ( - float - | IndexOpsMixin[int] - | IndexOpsMixin[float] - | Sequence[int] - | Sequence[float] - ), + self, other: float | Sequence[float] | Index[int] | Index[float] ) -> Self: ... def __truediv__( - self, - other: ( - float - | IndexOpsMixin[int] - | IndexOpsMixin[float] - | Sequence[int] - | Sequence[float] - ), + self, other: float | Sequence[float] | Index[int] | Index[float] ) -> Self: ... def __rtruediv__( - self, - other: ( - float - | IndexOpsMixin[int] - | IndexOpsMixin[float] - | Sequence[int] - | Sequence[float] - ), + self, other: float | Sequence[float] | Index[int] | Index[float] ) -> Self: ... def infer_objects(self, copy: bool = True) -> Self: ... diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index 2d38cd691..68917a501 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -2458,14 +2458,14 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Series[_bool]: ... @overload def __mul__( # type: ignore[overload-overlap] - self: Series[Never], other: complex | NumListLike | Series + self: Series[Never], other: complex | NumListLike | Index | Series ) -> Series: ... @overload - def __mul__(self, other: Series[Never]) -> Series: ... + def __mul__(self, other: Index[Never] | Series[Never]) -> Series: ... @overload def __mul__( self: Series[bool], - other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], ) -> Series[T_COMPLEX]: ... @overload def __mul__(self: Series[bool], other: np_ndarray_bool) -> Series[bool]: ... @@ -2477,13 +2477,18 @@ class Series(IndexOpsMixin[S1], NDFrame): def __mul__( self: Series[int], other: ( - bool | Sequence[bool] | np_ndarray_bool | np_ndarray_anyint | Series[bool] + bool + | Sequence[bool] + | np_ndarray_bool + | np_ndarray_anyint + | Index[bool] + | Series[bool] ), ) -> Series[int]: ... @overload def __mul__( self: Series[int], - other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], ) -> Series[T_COMPLEX]: ... @overload def __mul__(self: Series[int], other: np_ndarray_float) -> Series[float]: ... @@ -2496,13 +2501,14 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float + | Index[T_INT] | Series[T_INT] ), ) -> Series[float]: ... @overload def __mul__( self: Series[float], - other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], ) -> Series[T_COMPLEX]: ... @overload def __mul__( @@ -2513,6 +2519,7 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float + | Index[T_COMPLEX] | Series[T_COMPLEX] ), ) -> Series[complex]: ... @@ -2553,7 +2560,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def mul( self: Series[Never], - other: complex | _ListLike | Series, + other: complex | _ListLike | Index | Series, level: Level | None = None, fill_value: float | None = None, axis: int = 0, @@ -2561,7 +2568,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def mul( self, - other: Series[Never], + other: Index[Never] | Series[Never], level: Level | None = None, fill_value: float | None = None, axis: int = 0, @@ -2569,7 +2576,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def mul( self: Series[bool], - other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], level: Level | None = None, fill_value: float | None = None, axis: int = 0, @@ -2602,7 +2609,12 @@ class Series(IndexOpsMixin[S1], NDFrame): def mul( self: Series[int], other: ( - bool | Sequence[bool] | np_ndarray_bool | np_ndarray_anyint | Series[bool] + bool + | Sequence[bool] + | np_ndarray_bool + | np_ndarray_anyint + | Index[bool] + | Series[bool] ), level: Level | None = None, fill_value: float | None = None, @@ -2611,7 +2623,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def mul( self: Series[int], - other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], level: Level | None = None, fill_value: float | None = None, axis: int = 0, @@ -2633,6 +2645,7 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float + | Index[T_INT] | Series[T_INT] ), level: Level | None = None, @@ -2642,7 +2655,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def mul( self: Series[float], - other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], level: Level | None = None, fill_value: float | None = None, axis: int = 0, @@ -2656,6 +2669,7 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float + | Index[T_COMPLEX] | Series[T_COMPLEX] ), level: Level | None = None, @@ -2707,14 +2721,14 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Series[Timedelta]: ... @overload def __rmul__( # type: ignore[overload-overlap] - self: Series[Never], other: complex | NumListLike | Series + self: Series[Never], other: complex | NumListLike | Index | Series ) -> Series: ... @overload - def __rmul__(self, other: Series[Never]) -> Series: ... + def __rmul__(self, other: Index[Never] | Series[Never]) -> Series: ... @overload def __rmul__( self: Series[bool], - other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], ) -> Series[T_COMPLEX]: ... @overload def __rmul__(self: Series[bool], other: np_ndarray_bool) -> Series[bool]: ... @@ -2726,12 +2740,18 @@ class Series(IndexOpsMixin[S1], NDFrame): def __rmul__( self: Series[int], other: ( - bool | Sequence[bool] | np_ndarray_bool | np_ndarray_anyint | Series[bool] + bool + | Sequence[bool] + | np_ndarray_bool + | np_ndarray_anyint + | Index[bool] + | Series[bool] ), ) -> Series[int]: ... @overload def __rmul__( - self: Series[int], other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX] + self: Series[int], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], ) -> Series[T_COMPLEX]: ... @overload def __rmul__(self: Series[int], other: np_ndarray_float) -> Series[float]: ... @@ -2744,13 +2764,14 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float + | Index[T_INT] | Series[T_INT] ), ) -> Series[float]: ... @overload def __rmul__( self: Series[float], - other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], ) -> Series[T_COMPLEX]: ... @overload def __rmul__( @@ -2761,6 +2782,7 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float + | Index[T_COMPLEX] | Series[T_COMPLEX] ), ) -> Series[complex]: ... @@ -2801,7 +2823,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def rmul( self: Series[Never], - other: complex | _ListLike | Series, + other: complex | _ListLike | Index | Series, level: Level | None = None, fill_value: float | None = None, axis: int = 0, @@ -2809,7 +2831,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def rmul( self, - other: Series[Never], + other: Index[Never] | Series[Never], level: Level | None = None, fill_value: float | None = None, axis: int = 0, @@ -2817,7 +2839,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def rmul( self: Series[bool], - other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], level: Level | None = None, fill_value: float | None = None, axis: int = 0, @@ -2850,7 +2872,12 @@ class Series(IndexOpsMixin[S1], NDFrame): def rmul( self: Series[int], other: ( - bool | Sequence[bool] | np_ndarray_bool | np_ndarray_anyint | Series[bool] + bool + | Sequence[bool] + | np_ndarray_bool + | np_ndarray_anyint + | Index[bool] + | Series[bool] ), level: Level | None = None, fill_value: float | None = None, @@ -2859,7 +2886,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def rmul( self: Series[int], - other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], level: Level | None = None, fill_value: float | None = None, axis: int = 0, @@ -2881,6 +2908,7 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float + | Index[T_INT] | Series[T_INT] ), level: Level | None = None, @@ -2890,7 +2918,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def rmul( self: Series[float], - other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], level: Level | None = None, fill_value: float | None = None, axis: int = 0, @@ -2904,6 +2932,7 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float + | Index[T_COMPLEX] | Series[T_COMPLEX] ), level: Level | None = None, @@ -3597,10 +3626,10 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Series[Timedelta]: ... @overload def __truediv__( # type: ignore[overload-overlap] - self: Series[Never], other: complex | NumListLike | Series + self: Series[Never], other: complex | NumListLike | Index | Series ) -> Series: ... @overload - def __truediv__(self, other: Series[Never]) -> Series: ... + def __truediv__(self, other: Index[Never] | Series[Never]) -> Series: ... @overload def __truediv__(self: Series[bool], other: np_ndarray_bool) -> Never: ... @overload @@ -3612,6 +3641,8 @@ class Series(IndexOpsMixin[S1], NDFrame): | Sequence[float] | np_ndarray_anyint | np_ndarray_float + | Index[int] + | Index[float] | Series[int] | Series[float] ), @@ -3619,7 +3650,9 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def __truediv__( self: Series[bool], - other: Just[complex] | Sequence[Just[complex]] | Series[complex], + other: ( + Just[complex] | Sequence[Just[complex]] | Index[complex] | Series[complex] + ), ) -> Series[complex]: ... @overload def __truediv__( @@ -3630,13 +3663,14 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float + | Index[T_INT] | Series[T_INT] ), ) -> Series[float]: ... @overload def __truediv__( self: Series[int], - other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], ) -> Series[T_COMPLEX]: ... @overload def __truediv__( @@ -3647,13 +3681,14 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float + | Index[T_INT] | Series[T_INT] ), ) -> Series[float]: ... @overload def __truediv__( self: Series[float], - other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], ) -> Series[T_COMPLEX]: ... @overload def __truediv__( @@ -3664,6 +3699,7 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float + | Index[T_COMPLEX] | Series[T_COMPLEX] ), ) -> Series[complex]: ... @@ -3674,9 +3710,25 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def __truediv__( self: Series[Timedelta], - other: float | Sequence[float] | Series[int] | Series[float], + other: ( + Just[int] + | Just[float] + | Sequence[Just[int]] + | Sequence[Just[float]] + | np_ndarray_anyint + | np_ndarray_float + | Index[int] + | Index[float] + | Series[int] + | Series[float] + ), ) -> Series[Timedelta]: ... @overload + def __truediv__( + self: Series[Timedelta], + other: np_ndarray_bool | np_ndarray_complex | np_ndarray_dt, + ) -> Never: ... + @overload def __truediv__( self: Series[Timedelta], other: ( @@ -3693,7 +3745,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def truediv( self: Series[Never], - other: complex | _ListLike | Series, + other: complex | _ListLike | Index | Series, level: Level | None = None, fill_value: float | None = None, axis: AxisIndex = 0, @@ -3701,7 +3753,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def truediv( self, - other: Series[Never], + other: Index[Never] | Series[Never], level: Level | None = None, fill_value: float | None = None, axis: AxisIndex = 0, @@ -3715,6 +3767,8 @@ class Series(IndexOpsMixin[S1], NDFrame): | Sequence[float] | np_ndarray_anyint | np_ndarray_float + | Index[int] + | Index[float] | Series[int] | Series[float] ), @@ -3725,7 +3779,9 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def truediv( self: Series[bool], - other: Just[complex] | Sequence[Just[complex]] | Series[complex], + other: ( + Just[complex] | Sequence[Just[complex]] | Index[complex] | Series[complex] + ), level: Level | None = None, fill_value: float | None = None, axis: AxisIndex = 0, @@ -3739,6 +3795,7 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float + | Index[T_INT] | Series[T_INT] ), level: Level | None = None, @@ -3748,7 +3805,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def truediv( self: Series[int], - other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], level: Level | None = None, fill_value: float | None = None, axis: AxisIndex = 0, @@ -3762,6 +3819,7 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float + | Index[T_INT] | Series[T_INT] ), level: Level | None = None, @@ -3771,7 +3829,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def truediv( self: Series[float], - other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], level: Level | None = None, fill_value: float | None = None, axis: AxisIndex = 0, @@ -3785,6 +3843,7 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float + | Index[T_COMPLEX] | Series[T_COMPLEX] ), level: Level | None = None, @@ -3802,7 +3861,18 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def truediv( self: Series[Timedelta], - other: float | Sequence[float] | Series[int] | Series[float], + other: ( + Just[int] + | Just[float] + | Sequence[Just[int]] + | Sequence[Just[float]] + | np_ndarray_anyint + | np_ndarray_float + | Index[int] + | Index[float] + | Series[int] + | Series[float] + ), level: Level | None = None, fill_value: float | None = None, axis: AxisIndex = 0, @@ -3821,7 +3891,7 @@ class Series(IndexOpsMixin[S1], NDFrame): level: Level | None = None, fill_value: float | None = None, axis: AxisIndex = 0, - ) -> Series[Timedelta]: ... + ) -> Series[float]: ... @overload def truediv( self, @@ -3833,10 +3903,10 @@ class Series(IndexOpsMixin[S1], NDFrame): div = truediv @overload def __rtruediv__( # type: ignore[overload-overlap] - self: Series[Never], other: complex | NumListLike | Series + self: Series[Never], other: complex | NumListLike | Index | Series ) -> Series: ... @overload - def __rtruediv__(self, other: Series[Never]) -> Series: ... + def __rtruediv__(self, other: Index[Never] | Series[Never]) -> Series: ... @overload def __rtruediv__(self: Series[bool], other: np_ndarray_bool) -> Never: ... @overload @@ -3848,6 +3918,8 @@ class Series(IndexOpsMixin[S1], NDFrame): | Sequence[float] | np_ndarray_anyint | np_ndarray_float + | Index[int] + | Index[float] | Series[int] | Series[float] ), @@ -3855,7 +3927,9 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def __rtruediv__( self: Series[bool], - other: Just[complex] | Sequence[Just[complex]] | Series[complex], + other: ( + Just[complex] | Sequence[Just[complex]] | Index[complex] | Series[complex] + ), ) -> Series[complex]: ... @overload def __rtruediv__( @@ -3866,12 +3940,14 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float + | Index[T_INT] | Series[T_INT] ), ) -> Series[float]: ... @overload def __rtruediv__( - self: Series[int], other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX] + self: Series[int], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], ) -> Series[T_COMPLEX]: ... @overload def __rtruediv__( @@ -3882,13 +3958,14 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float + | Index[T_INT] | Series[T_INT] ), ) -> Series[float]: ... @overload def __rtruediv__( self: Series[float], - other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], ) -> Series[T_COMPLEX]: ... @overload def __rtruediv__( @@ -3899,6 +3976,7 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float + | Index[T_COMPLEX] | Series[T_COMPLEX] ), ) -> Series[complex]: ... @@ -3907,6 +3985,13 @@ class Series(IndexOpsMixin[S1], NDFrame): self: Series[T_COMPLEX], other: np_ndarray_complex ) -> Series[complex]: ... @overload + def __rtruediv__( + self: Series[Timedelta], + other: ( + np_ndarray_bool | np_ndarray_anyint | np_ndarray_float | np_ndarray_complex + ), + ) -> Never: ... + @overload def __rtruediv__( self: Series[Timedelta], other: ( @@ -3923,7 +4008,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def rtruediv( self: Series[Never], - other: complex | _ListLike | Series, + other: complex | _ListLike | Index | Series, level: Level | None = None, fill_value: float | None = None, axis: AxisIndex = 0, @@ -3931,7 +4016,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def rtruediv( self, - other: Series[Never], + other: Index[Never] | Series[Never], level: Level | None = None, fill_value: float | None = None, axis: AxisIndex = 0, @@ -3945,6 +4030,8 @@ class Series(IndexOpsMixin[S1], NDFrame): | Sequence[float] | np_ndarray_anyint | np_ndarray_float + | Index[int] + | Index[float] | Series[int] | Series[float] ), @@ -3955,7 +4042,9 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def rtruediv( self: Series[bool], - other: Just[complex] | Sequence[Just[complex]] | Series[complex], + other: ( + Just[complex] | Sequence[Just[complex]] | Index[complex] | Series[complex] + ), level: Level | None = None, fill_value: float | None = None, axis: AxisIndex = 0, @@ -3969,6 +4058,7 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float + | Index[T_INT] | Series[T_INT] ), level: Level | None = None, @@ -3978,7 +4068,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def rtruediv( self: Series[int], - other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], level: Level | None = None, fill_value: float | None = None, axis: AxisIndex = 0, @@ -3992,6 +4082,7 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float + | Index[T_INT] | Series[T_INT] ), level: Level | None = None, @@ -4001,7 +4092,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def rtruediv( self: Series[float], - other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], level: Level | None = None, fill_value: float | None = None, axis: AxisIndex = 0, @@ -4015,6 +4106,7 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float + | Index[T_COMPLEX] | Series[T_COMPLEX] ), level: Level | None = None, diff --git a/tests/indexes/arithmetic/bool/test_add.py b/tests/indexes/arithmetic/bool/test_add.py index f9bd52b9f..3255a6e7c 100644 --- a/tests/indexes/arithmetic/bool/test_add.py +++ b/tests/indexes/arithmetic/bool/test_add.py @@ -66,7 +66,7 @@ def test_add_numpy_array() -> None: def test_add_pd_index() -> None: - """Test pd.Index[bool] + pandas indexes""" + """Test pd.Index[bool] + pandas Indexes""" b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) f = pd.Index([1.0, 2.0, 3.0]) diff --git a/tests/indexes/arithmetic/bool/test_sub.py b/tests/indexes/arithmetic/bool/test_sub.py index b0ce9cea2..faac659dd 100644 --- a/tests/indexes/arithmetic/bool/test_sub.py +++ b/tests/indexes/arithmetic/bool/test_sub.py @@ -76,7 +76,7 @@ def test_sub_numpy_array() -> None: def test_sub_pd_index() -> None: - """Test pd.Index[bool] - pandas indexes""" + """Test pd.Index[bool] - pandas Indexes""" b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) f = pd.Index([1.0, 2.0, 3.0]) diff --git a/tests/indexes/arithmetic/complex/test_add.py b/tests/indexes/arithmetic/complex/test_add.py index 22a251156..bf3f6a4c2 100644 --- a/tests/indexes/arithmetic/complex/test_add.py +++ b/tests/indexes/arithmetic/complex/test_add.py @@ -67,7 +67,7 @@ def test_add_numpy_array() -> None: def test_add_pd_index() -> None: - """Test pd.Index[complex] + pandas indexes""" + """Test pd.Index[complex] + pandas Indexes""" b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) f = pd.Index([1.0, 2.0, 3.0]) diff --git a/tests/indexes/arithmetic/complex/test_sub.py b/tests/indexes/arithmetic/complex/test_sub.py index 4130c35e5..8df2892d1 100644 --- a/tests/indexes/arithmetic/complex/test_sub.py +++ b/tests/indexes/arithmetic/complex/test_sub.py @@ -69,7 +69,7 @@ def test_sub_numpy_array() -> None: def test_sub_pd_index() -> None: - """Test pd.Index[complex] - pandas indexes""" + """Test pd.Index[complex] - pandas Indexes""" b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) f = pd.Index([1.0, 2.0, 3.0]) diff --git a/tests/indexes/arithmetic/float/test_add.py b/tests/indexes/arithmetic/float/test_add.py index 86f5b3256..ce5a84f1f 100644 --- a/tests/indexes/arithmetic/float/test_add.py +++ b/tests/indexes/arithmetic/float/test_add.py @@ -65,7 +65,7 @@ def test_add_numpy_array() -> None: def test_add_pd_index() -> None: - """Test pd.Index[float] + pandas indexes""" + """Test pd.Index[float] + pandas Indexes""" b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) f = pd.Index([1.0, 2.0, 3.0]) diff --git a/tests/indexes/arithmetic/float/test_sub.py b/tests/indexes/arithmetic/float/test_sub.py index e9a709f02..c35a7a5a6 100644 --- a/tests/indexes/arithmetic/float/test_sub.py +++ b/tests/indexes/arithmetic/float/test_sub.py @@ -67,7 +67,7 @@ def test_sub_numpy_array() -> None: def test_sub_pd_index() -> None: - """Test pd.Index[float] - pandas indexes""" + """Test pd.Index[float] - pandas Indexes""" b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) f = pd.Index([1.0, 2.0, 3.0]) diff --git a/tests/indexes/arithmetic/int/test_add.py b/tests/indexes/arithmetic/int/test_add.py index 5fac65e11..2d3cc7c1d 100644 --- a/tests/indexes/arithmetic/int/test_add.py +++ b/tests/indexes/arithmetic/int/test_add.py @@ -65,7 +65,7 @@ def test_add_numpy_array() -> None: def test_add_pd_index() -> None: - """Test pd.Index[int] + pandas indexes""" + """Test pd.Index[int] + pandas Indexes""" b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) f = pd.Index([1.0, 2.0, 3.0]) diff --git a/tests/indexes/arithmetic/int/test_sub.py b/tests/indexes/arithmetic/int/test_sub.py index 783371459..dfc151b2e 100644 --- a/tests/indexes/arithmetic/int/test_sub.py +++ b/tests/indexes/arithmetic/int/test_sub.py @@ -67,7 +67,7 @@ def test_sub_numpy_array() -> None: def test_sub_pd_index() -> None: - """Test pd.Index[int] - pandas indexes""" + """Test pd.Index[int] - pandas Indexes""" b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) f = pd.Index([1.0, 2.0, 3.0]) diff --git a/tests/indexes/arithmetic/str/test_add.py b/tests/indexes/arithmetic/str/test_add.py index aa26052df..d4783f98f 100644 --- a/tests/indexes/arithmetic/str/test_add.py +++ b/tests/indexes/arithmetic/str/test_add.py @@ -75,7 +75,7 @@ def test_add_numpy_array() -> None: def test_add_pd_index() -> None: - """Test pd.Index[str] + pandas indexes""" + """Test pd.Index[str] + pandas Indexes""" i = pd.Index([3, 5, 8]) r0 = pd.Index(["a", "bc", "def"]) diff --git a/tests/indexes/arithmetic/test_add.py b/tests/indexes/arithmetic/test_add.py index 76ad1f40a..c7c415b46 100644 --- a/tests/indexes/arithmetic/test_add.py +++ b/tests/indexes/arithmetic/test_add.py @@ -82,7 +82,7 @@ def test_add_i_numpy_array() -> None: def test_add_i_pd_index() -> None: - """Test pd.Index[Any] (int) + pandas indexes""" + """Test pd.Index[Any] (int) + pandas Indexes""" a = pd.MultiIndex.from_tuples([(1,), (2,), (3,)]).levels[0] b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) diff --git a/tests/indexes/arithmetic/test_sub.py b/tests/indexes/arithmetic/test_sub.py index 8129f0b05..98ee8b8b5 100644 --- a/tests/indexes/arithmetic/test_sub.py +++ b/tests/indexes/arithmetic/test_sub.py @@ -78,7 +78,7 @@ def test_sub_i_numpy_array() -> None: def test_sub_i_pd_index() -> None: - """Test pd.Index[Any] (int) - pandas indexes""" + """Test pd.Index[Any] (int) - pandas Indexes""" a = pd.MultiIndex.from_tuples([(1,), (2,), (3,)]).levels[0] b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) diff --git a/tests/series/arithmetic/bool/test_add.py b/tests/series/arithmetic/bool/test_add.py index 59b0a8586..cd3959d08 100644 --- a/tests/series/arithmetic/bool/test_add.py +++ b/tests/series/arithmetic/bool/test_add.py @@ -100,7 +100,7 @@ def test_add_numpy_array() -> None: def test_add_pd_index() -> None: - """Test pd.Series[bool] + pandas indexes""" + """Test pd.Series[bool] + pandas Indexes""" b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) f = pd.Index([1.0, 2.0, 3.0]) @@ -130,7 +130,7 @@ def test_add_pd_index() -> None: def test_add_pd_series() -> None: - """Test pd.Series[bool] + pandas series""" + """Test pd.Series[bool] + pandas Series""" b = pd.Series([True, False, True]) i = pd.Series([2, 3, 5]) f = pd.Series([1.0, 2.0, 3.0]) diff --git a/tests/series/arithmetic/bool/test_mul.py b/tests/series/arithmetic/bool/test_mul.py index 218f12f9a..c7e76e917 100644 --- a/tests/series/arithmetic/bool/test_mul.py +++ b/tests/series/arithmetic/bool/test_mul.py @@ -99,8 +99,38 @@ def test_mul_numpy_array() -> None: ) +def test_mul_pd_index() -> None: + """Test pd.Series[bool] * pandas Indexes""" + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) + + check(assert_type(left * b, "pd.Series[bool]"), pd.Series, np.bool_) + check(assert_type(left * i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left * f, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left * c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(b * left, "pd.Series[bool]"), pd.Series, np.bool_) + check(assert_type(i * left, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(f * left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(c * left, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.mul(b), "pd.Series[bool]"), pd.Series, np.bool_) + check(assert_type(left.mul(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.mul(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.mul(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.rmul(b), "pd.Series[bool]"), pd.Series, np.bool_) + check(assert_type(left.rmul(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.rmul(f), "pd.Series[float]"), pd.Series, np.floating) + check( + assert_type(left.rmul(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + + def test_mul_pd_series() -> None: - """Test pd.Series[bool] * pandas series""" + """Test pd.Series[bool] * pandas Series""" b = pd.Series([True, False, True]) i = pd.Series([2, 3, 5]) f = pd.Series([1.0, 2.0, 3.0]) diff --git a/tests/series/arithmetic/bool/test_sub.py b/tests/series/arithmetic/bool/test_sub.py index d2a7f0a1c..6517e253f 100644 --- a/tests/series/arithmetic/bool/test_sub.py +++ b/tests/series/arithmetic/bool/test_sub.py @@ -118,7 +118,7 @@ def test_sub_numpy_array() -> None: def test_sub_pd_index() -> None: - """Test pd.Series[bool] - pandas indexes""" + """Test pd.Series[bool] - pandas Indexes""" b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) f = pd.Index([1.0, 2.0, 3.0]) @@ -152,7 +152,7 @@ def test_sub_pd_index() -> None: def test_sub_pd_series() -> None: - """Test pd.Series[bool] - pandas series""" + """Test pd.Series[bool] - pandas Series""" b = pd.Series([True, False, True]) i = pd.Series([2, 3, 5]) f = pd.Series([1.0, 2.0, 3.0]) diff --git a/tests/series/arithmetic/bool/test_truediv.py b/tests/series/arithmetic/bool/test_truediv.py index 0a09c4a9b..41c0e1a52 100644 --- a/tests/series/arithmetic/bool/test_truediv.py +++ b/tests/series/arithmetic/bool/test_truediv.py @@ -171,8 +171,62 @@ def test_truediv_numpy_array() -> None: ) +def test_truediv_pd_index() -> None: + """Test pd.Series[bool] / pandas Indexes""" + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) + + if TYPE_CHECKING_INVALID_USAGE: + _0 = left / b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left / i, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left / f, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left / c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + if TYPE_CHECKING_INVALID_USAGE: + _1 = b / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(i / left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(f / left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(c / left, "pd.Series[complex]"), pd.Series, np.complexfloating) + + if TYPE_CHECKING_INVALID_USAGE: + left.truediv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.truediv(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.truediv(f), "pd.Series[float]"), pd.Series, np.floating) + check( + assert_type(left.truediv(c), "pd.Series[complex]"), + pd.Series, + np.complexfloating, + ) + + if TYPE_CHECKING_INVALID_USAGE: + left.div(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.div(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.div(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.div(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + if TYPE_CHECKING_INVALID_USAGE: + left.rtruediv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rtruediv(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.rtruediv(f), "pd.Series[float]"), pd.Series, np.floating) + check( + assert_type(left.rtruediv(c), "pd.Series[complex]"), + pd.Series, + np.complexfloating, + ) + + if TYPE_CHECKING_INVALID_USAGE: + left.rdiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rdiv(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.rdiv(f), "pd.Series[float]"), pd.Series, np.floating) + check( + assert_type(left.rdiv(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + + def test_truediv_pd_series() -> None: - """Test pd.Series[bool] / pandas series""" + """Test pd.Series[bool] / pandas Series""" b = pd.Series([True, False, True]) i = pd.Series([2, 3, 5]) f = pd.Series([1.0, 2.0, 3.0]) diff --git a/tests/series/arithmetic/complex/test_add.py b/tests/series/arithmetic/complex/test_add.py index 85c6b3a2d..4e0338979 100644 --- a/tests/series/arithmetic/complex/test_add.py +++ b/tests/series/arithmetic/complex/test_add.py @@ -120,7 +120,7 @@ def test_add_numpy_array() -> None: def test_add_pd_index() -> None: - """Test pd.Series[complex] + pandas indexes""" + """Test pd.Series[complex] + pandas Indexes""" b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) f = pd.Index([1.0, 2.0, 3.0]) @@ -156,7 +156,7 @@ def test_add_pd_index() -> None: def test_add_pd_series() -> None: - """Test pd.Series[complex] + pandas series""" + """Test pd.Series[complex] + pandas Series""" b = pd.Series([True, False, True]) i = pd.Series([2, 3, 5]) f = pd.Series([1.0, 2.0, 3.0]) diff --git a/tests/series/arithmetic/complex/test_mul.py b/tests/series/arithmetic/complex/test_mul.py index 4f58e28e2..e36a822c6 100644 --- a/tests/series/arithmetic/complex/test_mul.py +++ b/tests/series/arithmetic/complex/test_mul.py @@ -119,8 +119,44 @@ def test_mul_numpy_array() -> None: ) +def test_mul_pd_index() -> None: + """Test pd.Series[complex] * pandas Indexes""" + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) + + check(assert_type(left * b, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left * i, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left * f, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left * c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(b * left, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(i * left, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(f * left, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(c * left, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.mul(b), "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left.mul(i), "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left.mul(f), "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left.mul(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check( + assert_type(left.rmul(b), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + check( + assert_type(left.rmul(i), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + check( + assert_type(left.rmul(f), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + check( + assert_type(left.rmul(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + + def test_mul_pd_series() -> None: - """Test pd.Series[complex] * pandas series""" + """Test pd.Series[complex] * pandas Series""" b = pd.Series([True, False, True]) i = pd.Series([2, 3, 5]) f = pd.Series([1.0, 2.0, 3.0]) diff --git a/tests/series/arithmetic/complex/test_sub.py b/tests/series/arithmetic/complex/test_sub.py index 4f688da2e..a58c31ae3 100644 --- a/tests/series/arithmetic/complex/test_sub.py +++ b/tests/series/arithmetic/complex/test_sub.py @@ -122,7 +122,7 @@ def test_sub_numpy_array() -> None: def test_sub_pd_index() -> None: - """Test pd.Series[complex] - pandas indexes""" + """Test pd.Series[complex] - pandas Indexes""" b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) f = pd.Index([1.0, 2.0, 3.0]) @@ -158,7 +158,7 @@ def test_sub_pd_index() -> None: def test_sub_pd_series() -> None: - """Test pd.Series[complex] - pandas series""" + """Test pd.Series[complex] - pandas Series""" b = pd.Series([True, False, True]) i = pd.Series([2, 3, 5]) f = pd.Series([1.0, 2.0, 3.0]) diff --git a/tests/series/arithmetic/complex/test_truediv.py b/tests/series/arithmetic/complex/test_truediv.py index ae194fe70..9d564659c 100644 --- a/tests/series/arithmetic/complex/test_truediv.py +++ b/tests/series/arithmetic/complex/test_truediv.py @@ -249,8 +249,86 @@ def test_truediv_numpy_array() -> None: ) +def test_truediv_pd_index() -> None: + """Test pd.Series[complex] / pandas Indexes""" + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) + + check(assert_type(left / b, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left / i, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left / f, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left / c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(b / left, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(i / left, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(f / left, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(c / left, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check( + assert_type(left.truediv(b), "pd.Series[complex]"), + pd.Series, + np.complexfloating, + ) + check( + assert_type(left.truediv(i), "pd.Series[complex]"), + pd.Series, + np.complexfloating, + ) + check( + assert_type(left.truediv(f), "pd.Series[complex]"), + pd.Series, + np.complexfloating, + ) + check( + assert_type(left.truediv(c), "pd.Series[complex]"), + pd.Series, + np.complexfloating, + ) + + check(assert_type(left.div(b), "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left.div(i), "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left.div(f), "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left.div(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check( + assert_type(left.rtruediv(b), "pd.Series[complex]"), + pd.Series, + np.complexfloating, + ) + check( + assert_type(left.rtruediv(i), "pd.Series[complex]"), + pd.Series, + np.complexfloating, + ) + check( + assert_type(left.rtruediv(f), "pd.Series[complex]"), + pd.Series, + np.complexfloating, + ) + check( + assert_type(left.rtruediv(c), "pd.Series[complex]"), + pd.Series, + np.complexfloating, + ) + + check( + assert_type(left.rdiv(b), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + check( + assert_type(left.rdiv(i), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + check( + assert_type(left.rdiv(f), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + check( + assert_type(left.rdiv(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + + def test_truediv_pd_series() -> None: - """Test pd.Series[complex] / pandas series""" + """Test pd.Series[complex] / pandas Series""" b = pd.Series([True, False, True]) i = pd.Series([2, 3, 5]) f = pd.Series([1.0, 2.0, 3.0]) diff --git a/tests/series/arithmetic/float/test_add.py b/tests/series/arithmetic/float/test_add.py index 75b180009..6318ebf24 100644 --- a/tests/series/arithmetic/float/test_add.py +++ b/tests/series/arithmetic/float/test_add.py @@ -100,7 +100,7 @@ def test_add_numpy_array() -> None: def test_add_pd_index() -> None: - """Test pd.Series[float] + pandas indexes""" + """Test pd.Series[float] + pandas Indexes""" b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) f = pd.Index([1.0, 2.0, 3.0]) @@ -130,7 +130,7 @@ def test_add_pd_index() -> None: def test_add_pd_series() -> None: - """Test pd.Series[float] + pandas series""" + """Test pd.Series[float] + pandas Series""" b = pd.Series([True, False, True]) i = pd.Series([2, 3, 5]) f = pd.Series([1.0, 2.0, 3.0]) diff --git a/tests/series/arithmetic/float/test_mul.py b/tests/series/arithmetic/float/test_mul.py index 84e702c51..f4afe08d2 100644 --- a/tests/series/arithmetic/float/test_mul.py +++ b/tests/series/arithmetic/float/test_mul.py @@ -99,8 +99,38 @@ def test_mul_numpy_array() -> None: ) +def test_mul_pd_index() -> None: + """Test pd.Series[float] * pandas Indexes""" + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) + + check(assert_type(left * b, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left * i, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left * f, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left * c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(b * left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(i * left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(f * left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(c * left, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.mul(b), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.mul(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.mul(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.mul(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.rmul(b), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.rmul(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.rmul(f), "pd.Series[float]"), pd.Series, np.floating) + check( + assert_type(left.rmul(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + + def test_mul_pd_series() -> None: - """Test pd.Series[float] * pandas series""" + """Test pd.Series[float] * pandas Series""" b = pd.Series([True, False, True]) i = pd.Series([2, 3, 5]) f = pd.Series([1.0, 2.0, 3.0]) diff --git a/tests/series/arithmetic/float/test_sub.py b/tests/series/arithmetic/float/test_sub.py index d3b251493..afad8dab5 100644 --- a/tests/series/arithmetic/float/test_sub.py +++ b/tests/series/arithmetic/float/test_sub.py @@ -102,7 +102,7 @@ def test_sub_numpy_array() -> None: def test_sub_pd_index() -> None: - """Test pd.Series[float] - pandas indexes""" + """Test pd.Series[float] - pandas Indexes""" b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) f = pd.Index([1.0, 2.0, 3.0]) @@ -132,7 +132,7 @@ def test_sub_pd_index() -> None: def test_sub_pd_series() -> None: - """Test pd.Series[float] - pandas series""" + """Test pd.Series[float] - pandas Series""" b = pd.Series([True, False, True]) i = pd.Series([2, 3, 5]) f = pd.Series([1.0, 2.0, 3.0]) diff --git a/tests/series/arithmetic/float/test_truediv.py b/tests/series/arithmetic/float/test_truediv.py index d10fb0123..3add54e9e 100644 --- a/tests/series/arithmetic/float/test_truediv.py +++ b/tests/series/arithmetic/float/test_truediv.py @@ -153,8 +153,56 @@ def test_truediv_numpy_array() -> None: ) +def test_truediv_pd_index() -> None: + """Test pd.Series[float] / pandas Indexes""" + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) + + check(assert_type(left / b, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left / i, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left / f, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left / c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(b / left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(i / left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(f / left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(c / left, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.truediv(b), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.truediv(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.truediv(f), "pd.Series[float]"), pd.Series, np.floating) + check( + assert_type(left.truediv(c), "pd.Series[complex]"), + pd.Series, + np.complexfloating, + ) + + check(assert_type(left.div(b), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.div(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.div(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.div(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.rtruediv(b), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.rtruediv(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.rtruediv(f), "pd.Series[float]"), pd.Series, np.floating) + check( + assert_type(left.rtruediv(c), "pd.Series[complex]"), + pd.Series, + np.complexfloating, + ) + + check(assert_type(left.rdiv(b), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.rdiv(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.rdiv(f), "pd.Series[float]"), pd.Series, np.floating) + check( + assert_type(left.rdiv(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + + def test_truediv_pd_series() -> None: - """Test pd.Series[float] / pandas series""" + """Test pd.Series[float] / pandas Series""" b = pd.Series([True, False, True]) i = pd.Series([2, 3, 5]) f = pd.Series([1.0, 2.0, 3.0]) diff --git a/tests/series/arithmetic/int/test_add.py b/tests/series/arithmetic/int/test_add.py index 5847a0149..8f544374a 100644 --- a/tests/series/arithmetic/int/test_add.py +++ b/tests/series/arithmetic/int/test_add.py @@ -100,7 +100,7 @@ def test_add_numpy_array() -> None: def test_add_pd_index() -> None: - """Test pd.Series[int] + pandas indexes""" + """Test pd.Series[int] + pandas Indexes""" b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) f = pd.Index([1.0, 2.0, 3.0]) @@ -130,7 +130,7 @@ def test_add_pd_index() -> None: def test_add_pd_series() -> None: - """Test pd.Series[int] + pandas series""" + """Test pd.Series[int] + pandas Series""" b = pd.Series([True, False, True]) i = pd.Series([2, 3, 5]) f = pd.Series([1.0, 2.0, 3.0]) diff --git a/tests/series/arithmetic/int/test_mul.py b/tests/series/arithmetic/int/test_mul.py index e61982506..b15d91256 100644 --- a/tests/series/arithmetic/int/test_mul.py +++ b/tests/series/arithmetic/int/test_mul.py @@ -99,8 +99,38 @@ def test_mul_numpy_array() -> None: ) +def test_mul_pd_index() -> None: + """Test pd.Series[int] * pandas Indexes""" + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) + + check(assert_type(left * b, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left * i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left * f, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left * c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(b * left, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(i * left, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(f * left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(c * left, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.mul(b), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.mul(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.mul(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.mul(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.rmul(b), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.rmul(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.rmul(f), "pd.Series[float]"), pd.Series, np.floating) + check( + assert_type(left.rmul(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + + def test_mul_pd_series() -> None: - """Test pd.Series[int] * pandas series""" + """Test pd.Series[int] * pandas Series""" b = pd.Series([True, False, True]) i = pd.Series([2, 3, 5]) f = pd.Series([1.0, 2.0, 3.0]) diff --git a/tests/series/arithmetic/int/test_sub.py b/tests/series/arithmetic/int/test_sub.py index 4a9170c3d..28bcdd4f0 100644 --- a/tests/series/arithmetic/int/test_sub.py +++ b/tests/series/arithmetic/int/test_sub.py @@ -102,7 +102,7 @@ def test_sub_numpy_array() -> None: def test_sub_pd_index() -> None: - """Test pd.Series[int] - pandas indexes""" + """Test pd.Series[int] - pandas Indexes""" b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) f = pd.Index([1.0, 2.0, 3.0]) @@ -132,7 +132,7 @@ def test_sub_pd_index() -> None: def test_sub_pd_series() -> None: - """Test pd.Series[int] - pandas series""" + """Test pd.Series[int] - pandas Series""" b = pd.Series([True, False, True]) i = pd.Series([2, 3, 5]) f = pd.Series([1.0, 2.0, 3.0]) diff --git a/tests/series/arithmetic/int/test_truediv.py b/tests/series/arithmetic/int/test_truediv.py index a17dea9a1..f9f665408 100644 --- a/tests/series/arithmetic/int/test_truediv.py +++ b/tests/series/arithmetic/int/test_truediv.py @@ -153,8 +153,56 @@ def test_truediv_numpy_array() -> None: ) +def test_truediv_pd_index() -> None: + """Test pd.Series[int] / pandas Indexes""" + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) + + check(assert_type(left / b, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left / i, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left / f, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left / c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(b / left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(i / left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(f / left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(c / left, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.truediv(b), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.truediv(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.truediv(f), "pd.Series[float]"), pd.Series, np.floating) + check( + assert_type(left.truediv(c), "pd.Series[complex]"), + pd.Series, + np.complexfloating, + ) + + check(assert_type(left.div(b), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.div(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.div(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.div(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.rtruediv(b), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.rtruediv(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.rtruediv(f), "pd.Series[float]"), pd.Series, np.floating) + check( + assert_type(left.rtruediv(c), "pd.Series[complex]"), + pd.Series, + np.complexfloating, + ) + + check(assert_type(left.rdiv(b), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.rdiv(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.rdiv(f), "pd.Series[float]"), pd.Series, np.floating) + check( + assert_type(left.rdiv(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + + def test_truediv_pd_series() -> None: - """Test pd.Series[int] / pandas series""" + """Test pd.Series[int] / pandas Series""" b = pd.Series([True, False, True]) i = pd.Series([2, 3, 5]) f = pd.Series([1.0, 2.0, 3.0]) diff --git a/tests/series/arithmetic/str/test_add.py b/tests/series/arithmetic/str/test_add.py index 34ecf4c0d..d9b2ec6fd 100644 --- a/tests/series/arithmetic/str/test_add.py +++ b/tests/series/arithmetic/str/test_add.py @@ -101,7 +101,7 @@ def test_add_numpy_array() -> None: def test_add_pd_index() -> None: - """Test pd.Series[str] + pandas indexes""" + """Test pd.Series[str] + pandas Indexes""" i = pd.Index([3, 5, 8]) r0 = pd.Index(["a", "bc", "def"]) @@ -123,7 +123,7 @@ def test_add_pd_index() -> None: def test_add_pd_series() -> None: - """Test pd.Series[str] + pandas series""" + """Test pd.Series[str] + pandas Series""" i = pd.Series([3, 5, 8]) r0 = pd.Series(["a", "bc", "def"]) diff --git a/tests/series/arithmetic/test_add.py b/tests/series/arithmetic/test_add.py index 7cb268c69..b1094ed71 100644 --- a/tests/series/arithmetic/test_add.py +++ b/tests/series/arithmetic/test_add.py @@ -118,7 +118,7 @@ def test_add_i_numpy_array() -> None: def test_add_i_pd_index() -> None: - """Test pd.Series[Any] (int) + pandas indexes""" + """Test pd.Series[Any] (int) + pandas Indexes""" a = pd.MultiIndex.from_tuples([(1,), (2,), (3,)]).levels[0] b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) @@ -151,7 +151,7 @@ def test_add_i_pd_index() -> None: def test_add_i_pd_series() -> None: - """Test pd.Series[Any] (int) + pandas series""" + """Test pd.Series[Any] (int) + pandas Series""" a = pd.DataFrame({"a": [1, 2, 3]})["a"] b = pd.Series([True, False, True]) i = pd.Series([2, 3, 5]) diff --git a/tests/series/arithmetic/test_mul.py b/tests/series/arithmetic/test_mul.py index 01c86e9df..f89633416 100644 --- a/tests/series/arithmetic/test_mul.py +++ b/tests/series/arithmetic/test_mul.py @@ -106,8 +106,41 @@ def test_mul_numpy_array() -> None: check(assert_type(left_i.rmul(c), pd.Series), pd.Series) +def test_mul_pd_index() -> None: + """Test pd.Series[Any] (int) * pandas Indexes""" + a = pd.MultiIndex.from_tuples([(1,), (2,), (3,)]).levels[0] + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) + + check(assert_type(left_i * a, pd.Series), pd.Series) + check(assert_type(left_i * b, pd.Series), pd.Series) + check(assert_type(left_i * i, pd.Series), pd.Series) + check(assert_type(left_i * f, pd.Series), pd.Series) + check(assert_type(left_i * c, pd.Series), pd.Series) + + check(assert_type(a * left_i, pd.Series), pd.Series) + check(assert_type(b * left_i, pd.Series), pd.Series) + check(assert_type(i * left_i, pd.Series), pd.Series) + check(assert_type(f * left_i, pd.Series), pd.Series) + check(assert_type(c * left_i, pd.Series), pd.Series) + + check(assert_type(left_i.mul(a), pd.Series), pd.Series) + check(assert_type(left_i.mul(b), pd.Series), pd.Series) + check(assert_type(left_i.mul(i), pd.Series), pd.Series) + check(assert_type(left_i.mul(f), pd.Series), pd.Series) + check(assert_type(left_i.mul(c), pd.Series), pd.Series) + + check(assert_type(left_i.rmul(a), pd.Series), pd.Series) + check(assert_type(left_i.rmul(b), pd.Series), pd.Series) + check(assert_type(left_i.rmul(i), pd.Series), pd.Series) + check(assert_type(left_i.rmul(f), pd.Series), pd.Series) + check(assert_type(left_i.rmul(c), pd.Series), pd.Series) + + def test_mul_pd_series() -> None: - """Test pd.Series[Any] (int) * pandas series""" + """Test pd.Series[Any] (int) * pandas Series""" a = pd.DataFrame({"a": [1, 2, 3]})["a"] b = pd.Series([True, False, True]) i = pd.Series([2, 3, 5]) diff --git a/tests/series/arithmetic/test_sub.py b/tests/series/arithmetic/test_sub.py index a07b35658..21398e881 100644 --- a/tests/series/arithmetic/test_sub.py +++ b/tests/series/arithmetic/test_sub.py @@ -116,7 +116,7 @@ def test_sub_i_numpy_array() -> None: def test_sub_i_pd_index() -> None: - """Test pd.Series[Any] (int) - pandas indexes""" + """Test pd.Series[Any] (int) - pandas Indexes""" a = pd.MultiIndex.from_tuples([(1,), (2,), (3,)]).levels[0] b = pd.Index([True, False, True]) i = pd.Index([2, 3, 5]) @@ -149,7 +149,7 @@ def test_sub_i_pd_index() -> None: def test_sub_i_pd_series() -> None: - """Test pd.Series[Any] (int) - pandas series""" + """Test pd.Series[Any] (int) - pandas Series""" a = pd.DataFrame({"a": [1, 2, 3]})["a"] b = pd.Series([True, False, True]) i = pd.Series([2, 3, 5]) diff --git a/tests/series/arithmetic/test_truediv.py b/tests/series/arithmetic/test_truediv.py index 3fb747cee..9baa2c49b 100644 --- a/tests/series/arithmetic/test_truediv.py +++ b/tests/series/arithmetic/test_truediv.py @@ -138,8 +138,53 @@ def test_truediv_numpy_array() -> None: check(assert_type(left_i.rdiv(c), pd.Series), pd.Series) +def test_truediv_pd_index() -> None: + """Test pd.Series[Any] (int) / pandas Indexes""" + a = pd.MultiIndex.from_tuples([(1,), (2,), (3,)]).levels[0] + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) + + check(assert_type(left_i / a, pd.Series), pd.Series) + check(assert_type(left_i / b, pd.Series), pd.Series) + check(assert_type(left_i / i, pd.Series), pd.Series) + check(assert_type(left_i / f, pd.Series), pd.Series) + check(assert_type(left_i / c, pd.Series), pd.Series) + + check(assert_type(a / left_i, pd.Series), pd.Series) + check(assert_type(b / left_i, pd.Series), pd.Series) + check(assert_type(i / left_i, pd.Series), pd.Series) + check(assert_type(f / left_i, pd.Series), pd.Series) + check(assert_type(c / left_i, pd.Series), pd.Series) + + check(assert_type(left_i.truediv(a), pd.Series), pd.Series) + check(assert_type(left_i.truediv(b), pd.Series), pd.Series) + check(assert_type(left_i.truediv(i), pd.Series), pd.Series) + check(assert_type(left_i.truediv(f), pd.Series), pd.Series) + check(assert_type(left_i.truediv(c), pd.Series), pd.Series) + + check(assert_type(left_i.div(a), pd.Series), pd.Series) + check(assert_type(left_i.div(b), pd.Series), pd.Series) + check(assert_type(left_i.div(i), pd.Series), pd.Series) + check(assert_type(left_i.div(f), pd.Series), pd.Series) + check(assert_type(left_i.div(c), pd.Series), pd.Series) + + check(assert_type(left_i.rtruediv(a), pd.Series), pd.Series) + check(assert_type(left_i.rtruediv(b), pd.Series), pd.Series) + check(assert_type(left_i.rtruediv(i), pd.Series), pd.Series) + check(assert_type(left_i.rtruediv(f), pd.Series), pd.Series) + check(assert_type(left_i.rtruediv(c), pd.Series), pd.Series) + + check(assert_type(left_i.rdiv(a), pd.Series), pd.Series) + check(assert_type(left_i.rdiv(b), pd.Series), pd.Series) + check(assert_type(left_i.rdiv(i), pd.Series), pd.Series) + check(assert_type(left_i.rdiv(f), pd.Series), pd.Series) + check(assert_type(left_i.rdiv(c), pd.Series), pd.Series) + + def test_truediv_pd_series() -> None: - """Test pd.Series[Any] (int) / pandas series""" + """Test pd.Series[Any] (int) / pandas Series""" a = pd.DataFrame({"a": [1, 2, 3]})["a"] b = pd.Series([True, False, True]) i = pd.Series([2, 3, 5]) diff --git a/tests/series/arithmetic/timedelta/test_add.py b/tests/series/arithmetic/timedelta/test_add.py index 671767546..4aee2bd02 100644 --- a/tests/series/arithmetic/timedelta/test_add.py +++ b/tests/series/arithmetic/timedelta/test_add.py @@ -113,7 +113,7 @@ def test_add_numpy_array() -> None: def test_add_pd_index() -> None: - """Test pd.Series[pd.Timedelta] + pandas indexes""" + """Test pd.Series[pd.Timedelta] + pandas Indexes""" s = pd.Index([pd.Timestamp("2025-08-20")]) d = pd.Index([pd.Timedelta(seconds=1)]) @@ -131,7 +131,7 @@ def test_add_pd_index() -> None: def test_add_pd_series() -> None: - """Test pd.Series[pd.Timedelta] + pandas series""" + """Test pd.Series[pd.Timedelta] + pandas Series""" s = pd.Series([pd.Timestamp("2025-08-20")]) d = pd.Series([pd.Timedelta(seconds=1)]) diff --git a/tests/series/arithmetic/timedelta/test_mul.py b/tests/series/arithmetic/timedelta/test_mul.py index 0a67cb618..4cf585cd4 100644 --- a/tests/series/arithmetic/timedelta/test_mul.py +++ b/tests/series/arithmetic/timedelta/test_mul.py @@ -7,6 +7,7 @@ ) from tests import ( + PD_LTE_23, TYPE_CHECKING_INVALID_USAGE, check, ) @@ -109,7 +110,7 @@ def test_mul_numpy_array() -> None: def test_mul_pd_index() -> None: - """Test pd.Series[pd.Timedelta] * pandas indexes""" + """Test pd.Series[pd.Timedelta] * pandas Indexes""" b = pd.Index([True]) i = pd.Index([2]) f = pd.Index([1.5]) @@ -141,31 +142,45 @@ def test_mul_pd_index() -> None: def test_mul_pd_series() -> None: - """Test pd.Series[pd.Timedelta] * pandas series""" + """Test pd.Series[pd.Timedelta] * pandas Series""" b = pd.Series([True]) i = pd.Series([2]) f = pd.Series([1.5]) c = pd.Series([1.7j]) - check(assert_type(left * b, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + # pandas-dev/pandas#62316 + if PD_LTE_23: + check(assert_type(left * b, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(left * i, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(left * f, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) if TYPE_CHECKING_INVALID_USAGE: _0 = left * c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - check(assert_type(b * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + # pandas-dev/pandas#62316 + if PD_LTE_23: + check(assert_type(b * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(i * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(f * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) if TYPE_CHECKING_INVALID_USAGE: _1 = c * left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - check(assert_type(left.mul(b), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + # pandas-dev/pandas#62316 + if PD_LTE_23: + check( + assert_type(left.mul(b), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta + ) check(assert_type(left.mul(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(left.mul(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) if TYPE_CHECKING_INVALID_USAGE: left.mul(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] - check(assert_type(left.rmul(b), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + # pandas-dev/pandas#62316 + if PD_LTE_23: + check( + assert_type(left.rmul(b), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) check(assert_type(left.rmul(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(left.rmul(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) if TYPE_CHECKING_INVALID_USAGE: diff --git a/tests/series/arithmetic/timedelta/test_sub.py b/tests/series/arithmetic/timedelta/test_sub.py index bedacae1e..c50abed21 100644 --- a/tests/series/arithmetic/timedelta/test_sub.py +++ b/tests/series/arithmetic/timedelta/test_sub.py @@ -124,7 +124,7 @@ def test_sub_numpy_array() -> None: def test_sub_pd_index() -> None: - """Test pd.Series[pd.Timedelta] - pandas indexes""" + """Test pd.Series[pd.Timedelta] - pandas Indexes""" s = pd.Index([pd.Timestamp("2025-08-20")]) d = pd.Index([pd.Timedelta(seconds=1)]) @@ -144,7 +144,7 @@ def test_sub_pd_index() -> None: def test_sub_pd_series() -> None: - """Test pd.Series[pd.Timedelta] - pandas series""" + """Test pd.Series[pd.Timedelta] - pandas Series""" s = pd.Series([pd.Timestamp("2025-08-20")]) d = pd.Series([pd.Timedelta(seconds=1)]) diff --git a/tests/series/arithmetic/timedelta/test_truediv.py b/tests/series/arithmetic/timedelta/test_truediv.py new file mode 100644 index 000000000..a19662e53 --- /dev/null +++ b/tests/series/arithmetic/timedelta/test_truediv.py @@ -0,0 +1,367 @@ +from datetime import ( + datetime, + timedelta, +) +from typing import Any + +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.Timedelta(1, "s")]) # left operand + + +def test_truediv_py_scalar() -> None: + """Test pd.Series[pd.Timedelta] / Python native scalars""" + b, i, f, c = True, 1, 1.0, 1j + s, d = datetime(2025, 9, 24), timedelta(seconds=1) + + if TYPE_CHECKING_INVALID_USAGE: + _0 = left / b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left / i, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left / f, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + _1 = left / c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _2 = left / s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left / d, "pd.Series[float]"), pd.Series, np.floating) + + if TYPE_CHECKING_INVALID_USAGE: + _3 = b / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _4 = i / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _5 = f / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _6 = c / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _7 = s / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d / left, "pd.Series[float]"), pd.Series, np.floating) + + if TYPE_CHECKING_INVALID_USAGE: + left.truediv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left.truediv(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta + ) + check( + assert_type(left.truediv(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta + ) + if TYPE_CHECKING_INVALID_USAGE: + left.truediv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.truediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.truediv(d), "pd.Series[float]"), pd.Series, np.floating) + + if TYPE_CHECKING_INVALID_USAGE: + left.div(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.div(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left.div(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + left.div(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.div(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.div(d), "pd.Series[float]"), pd.Series, np.floating) + + if TYPE_CHECKING_INVALID_USAGE: + left.rtruediv(b) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rtruediv(i) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rtruediv(f) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rtruediv(c) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rtruediv(s) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rtruediv(d), "pd.Series[float]"), pd.Series, np.floating) + + if TYPE_CHECKING_INVALID_USAGE: + left.rdiv(b) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rdiv(i) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rdiv(f) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rdiv(c) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rdiv(s) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rdiv(d), "pd.Series[float]"), pd.Series, np.floating) + + +def test_truediv_py_sequence() -> None: + """Test pd.Series[pd.Timedelta] / Python native sequences""" + b, i, f, c = [True], [2], [1.5], [1.7j] + s, d = [datetime(2025, 9, 24)], [timedelta(seconds=1)] + + if TYPE_CHECKING_INVALID_USAGE: + _0 = left / b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left / i, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left / f, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + _1 = left / c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _2 = left / s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left / d, "pd.Series[float]"), pd.Series, float) + + if TYPE_CHECKING_INVALID_USAGE: + _3 = b / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _4 = i / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _5 = f / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _6 = c / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _7 = s / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d / left, "pd.Series[float]"), pd.Series, np.floating) + + if TYPE_CHECKING_INVALID_USAGE: + left.truediv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left.truediv(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta + ) + check( + assert_type(left.truediv(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta + ) + if TYPE_CHECKING_INVALID_USAGE: + left.truediv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.truediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.truediv(d), "pd.Series[float]"), pd.Series, np.floating) + + if TYPE_CHECKING_INVALID_USAGE: + left.div(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.div(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left.div(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + left.div(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.div(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.div(d), "pd.Series[float]"), pd.Series, np.floating) + + if TYPE_CHECKING_INVALID_USAGE: + left.rtruediv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rtruediv(i) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rtruediv(f) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rtruediv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rtruediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rtruediv(d), "pd.Series[float]"), pd.Series, np.floating) + + if TYPE_CHECKING_INVALID_USAGE: + left.rdiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rdiv(i) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rdiv(f) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rdiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rdiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rdiv(d), "pd.Series[float]"), pd.Series, np.floating) + + +def test_truediv_numpy_array() -> None: + """Test pd.Series[pd.Timedelta] / numpy arrays""" + b = np.array([True], np.bool_) + i = np.array([2], np.int64) + f = np.array([1.5], np.float64) + c = np.array([1.7j], np.complex128) + s = np.array([datetime(2025, 9, 24)], np.datetime64) + d = np.array([timedelta(seconds=1)], np.timedelta64) + + if TYPE_CHECKING_INVALID_USAGE: + assert_type(left / b, Never) + check(assert_type(left / i, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left / f, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + assert_type(left / c, Never) + assert_type(left / s, Never) + check(assert_type(left / d, "pd.Series[float]"), pd.Series, np.floating) + + # `numpy` typing gives the corresponding `ndarray`s in the static type + # checking, where our `__rsub__` cannot override. At runtime, they lead to + # errors or pd.Series. + if TYPE_CHECKING_INVALID_USAGE: + assert_type(b / left, "npt.NDArray[np.float64]") + assert_type(i / left, "npt.NDArray[np.float64]") + assert_type(f / left, "npt.NDArray[np.float64]") + assert_type(c / left, "npt.NDArray[np.complex128]") + assert_type(s / left, Any) + check(assert_type(d / left, "npt.NDArray[np.float64]"), pd.Series, np.floating) + + if TYPE_CHECKING_INVALID_USAGE: + left.truediv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left.truediv(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta + ) + check( + assert_type(left.truediv(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta + ) + if TYPE_CHECKING_INVALID_USAGE: + left.truediv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.truediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.truediv(d), "pd.Series[float]"), pd.Series, np.floating) + + if TYPE_CHECKING_INVALID_USAGE: + left.div(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.div(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left.div(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + left.div(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.div(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.div(d), "pd.Series[float]"), pd.Series, np.floating) + + if TYPE_CHECKING_INVALID_USAGE: + left.rtruediv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rtruediv(i) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rtruediv(f) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rtruediv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rtruediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rtruediv(d), "pd.Series[float]"), pd.Series, np.floating) + + if TYPE_CHECKING_INVALID_USAGE: + left.rdiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rdiv(i) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rdiv(f) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rdiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rdiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rdiv(d), "pd.Series[float]"), pd.Series, np.floating) + + +def test_truediv_pd_scalar() -> None: + """Test pd.Series[pd.Timedelta] / pandas scalars""" + s, d = pd.Timestamp(2025, 9, 24), 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[float]"), pd.Series, np.floating) + + if TYPE_CHECKING_INVALID_USAGE: + _1 = s / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d / left, "pd.Series[float]"), pd.Series, np.floating) + + if TYPE_CHECKING_INVALID_USAGE: + left.truediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.truediv(d), "pd.Series[float]"), pd.Series, np.floating) + + if TYPE_CHECKING_INVALID_USAGE: + left.div(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.div(d), "pd.Series[float]"), pd.Series, np.floating) + + if TYPE_CHECKING_INVALID_USAGE: + left.rtruediv(s) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rtruediv(d), "pd.Series[float]"), pd.Series, np.floating) + + if TYPE_CHECKING_INVALID_USAGE: + left.rdiv(s) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rdiv(d), "pd.Series[float]"), pd.Series, np.floating) + + +def test_truediv_pd_index() -> None: + """Test pd.Series[pd.Timedelta] / pandas Indexes""" + b = pd.Index([True]) + i = pd.Index([2]) + f = pd.Index([1.5]) + c = pd.Index([1.7j]) + s, d = pd.Index([datetime(2025, 9, 24)]), pd.Index([timedelta(seconds=1)]) + + if TYPE_CHECKING_INVALID_USAGE: + _0 = left / b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left / i, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left / f, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + _1 = left / c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _2 = left / s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left / d, "pd.Series[float]"), pd.Series, np.floating) + + if TYPE_CHECKING_INVALID_USAGE: + _3 = b / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _4 = i / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _5 = f / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _6 = c / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _7 = s / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d / left, "pd.Series[float]"), pd.Series, np.floating) + + if TYPE_CHECKING_INVALID_USAGE: + left.truediv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left.truediv(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta + ) + check( + assert_type(left.truediv(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta + ) + if TYPE_CHECKING_INVALID_USAGE: + left.truediv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.truediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.truediv(d), "pd.Series[float]"), pd.Series, np.floating) + + if TYPE_CHECKING_INVALID_USAGE: + left.div(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.div(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left.div(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + left.div(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.div(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.div(d), "pd.Series[float]"), pd.Series, np.floating) + + if TYPE_CHECKING_INVALID_USAGE: + left.rtruediv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rtruediv(i) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rtruediv(f) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rtruediv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rtruediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rtruediv(d), "pd.Series[float]"), pd.Series, np.floating) + + if TYPE_CHECKING_INVALID_USAGE: + left.rdiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rdiv(i) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rdiv(f) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rdiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rdiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rdiv(d), "pd.Series[float]"), pd.Series, np.floating) + + +def test_truediv_pd_series() -> None: + """Test pd.Series[pd.Timedelta] / pandas Series""" + b = pd.Series([True]) + i = pd.Series([2]) + f = pd.Series([1.5]) + c = pd.Series([1.7j]) + s, d = pd.Series([datetime(2025, 9, 24)]), pd.Series([timedelta(seconds=1)]) + + if TYPE_CHECKING_INVALID_USAGE: + _0 = left / b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left / i, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left / f, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + _1 = left / c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _2 = left / s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left / d, "pd.Series[float]"), pd.Series, np.floating) + + if TYPE_CHECKING_INVALID_USAGE: + _3 = b / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _4 = i / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _5 = f / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _6 = c / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _7 = s / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d / left, "pd.Series[float]"), pd.Series, np.floating) + + if TYPE_CHECKING_INVALID_USAGE: + left.truediv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left.truediv(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta + ) + check( + assert_type(left.truediv(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta + ) + if TYPE_CHECKING_INVALID_USAGE: + left.truediv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.truediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.truediv(d), "pd.Series[float]"), pd.Series, np.floating) + + if TYPE_CHECKING_INVALID_USAGE: + left.div(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.div(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left.div(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + left.div(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.div(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.div(d), "pd.Series[float]"), pd.Series, np.floating) + + if TYPE_CHECKING_INVALID_USAGE: + left.rtruediv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rtruediv(i) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rtruediv(f) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rtruediv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rtruediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rtruediv(d), "pd.Series[float]"), pd.Series, np.floating) + + if TYPE_CHECKING_INVALID_USAGE: + left.rdiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rdiv(i) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rdiv(f) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rdiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rdiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rdiv(d), "pd.Series[float]"), pd.Series, np.floating) diff --git a/tests/series/arithmetic/timestamp/test_add.py b/tests/series/arithmetic/timestamp/test_add.py index ebee459e9..3efdffe82 100644 --- a/tests/series/arithmetic/timestamp/test_add.py +++ b/tests/series/arithmetic/timestamp/test_add.py @@ -135,7 +135,7 @@ def test_add_numpy_array() -> None: def test_add_pd_index() -> None: - """Test pd.Series[pd.Timestamp] + pandas indexes""" + """Test pd.Series[pd.Timestamp] + pandas Indexes""" s = pd.Index([pd.Timestamp("2025-08-20")]) d = pd.Index([pd.Timedelta(seconds=1)]) @@ -157,7 +157,7 @@ def test_add_pd_index() -> None: def test_add_pd_series() -> None: - """Test pd.Series[pd.Timestamp] + pandas series""" + """Test pd.Series[pd.Timestamp] + pandas Series""" s = pd.Series([pd.Timestamp("2025-08-20")]) d = pd.Series([pd.Timedelta(seconds=1)]) diff --git a/tests/series/arithmetic/timestamp/test_sub.py b/tests/series/arithmetic/timestamp/test_sub.py index b041f9e5a..c680e30eb 100644 --- a/tests/series/arithmetic/timestamp/test_sub.py +++ b/tests/series/arithmetic/timestamp/test_sub.py @@ -122,7 +122,7 @@ def test_sub_numpy_array() -> None: def test_sub_pd_index() -> None: - """Test pd.Series[pd.Timestamp] - pandas indexes""" + """Test pd.Series[pd.Timestamp] - pandas Indexes""" s = pd.Index([pd.Timestamp("2025-08-20")]) d = pd.Index([pd.Timedelta(seconds=1)]) @@ -142,7 +142,7 @@ def test_sub_pd_index() -> None: def test_sub_pd_series() -> None: - """Test pd.Series[pd.Timestamp] - pandas series""" + """Test pd.Series[pd.Timestamp] - pandas Series""" s = pd.Series([pd.Timestamp("2025-08-20")]) d = pd.Series([pd.Timedelta(seconds=1)]) diff --git a/tests/test_timefuncs.py b/tests/test_timefuncs.py index 06e3e1474..c007bfafd 100644 --- a/tests/test_timefuncs.py +++ b/tests/test_timefuncs.py @@ -187,24 +187,9 @@ def test_timedelta_series_string() -> None: def test_timestamp_timedelta_series_arithmetic() -> None: ts1 = pd.to_datetime(pd.Series(["2022-03-05", "2022-03-06"])) check(assert_type(ts1.iloc[0], pd.Timestamp), pd.Timestamp) - td1 = pd.to_timedelta([2, 3], "seconds") - ts2 = pd.to_datetime(pd.Series(["2022-03-08", "2022-03-10"])) - r1 = ts1 - ts2 - r2 = r1 / td1 - check(assert_type(r2, "pd.Series[float]"), pd.Series, float) - r4 = pd.Timedelta(5, "days") / r1 - check(assert_type(r4, "pd.Series[float]"), pd.Series, float) sb = pd.Series([1, 2]) == pd.Series([1, 3]) check(assert_type(sb, "pd.Series[bool]"), pd.Series, np.bool_) - # https://github.com/pandas-dev/pandas/issues/62316 - if PD_LTE_23: - r5 = sb * r1 - check(assert_type(r5, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) - - r6 = r1 * 4 - check(assert_type(r6, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) - def test_timestamp_dateoffset_arithmetic() -> None: ts = pd.Timestamp("2022-03-18") From 9d364bef53abd6899b87aaa95984b5ceda459acd Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Wed, 24 Sep 2025 22:05:48 +0200 Subject: [PATCH 07/13] feat(test): floordiv --- pandas-stubs/core/series.pyi | 218 ++++++++++--- .../series/arithmetic/float/test_floordiv.py | 178 +++++++++++ tests/series/arithmetic/int/test_floordiv.py | 178 +++++++++++ .../arithmetic/timedelta/test_floordiv.py | 294 ++++++++++++++++++ 4 files changed, 829 insertions(+), 39 deletions(-) create mode 100644 tests/series/arithmetic/float/test_floordiv.py create mode 100644 tests/series/arithmetic/int/test_floordiv.py create mode 100644 tests/series/arithmetic/timedelta/test_floordiv.py diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index 68917a501..e90214552 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -189,6 +189,7 @@ from pandas._typing import ( WriteBuffer, _T_co, np_1darray, + np_ndarray, np_ndarray_anyint, np_ndarray_bool, np_ndarray_complex, @@ -2274,34 +2275,68 @@ class Series(IndexOpsMixin[S1], NDFrame): def __floordiv__(self, other: Index[Never] | Series[Never]) -> Series: ... @overload def __floordiv__( - self: Series[bool] | Series[int] | Series[float], + self: Series[int] | Series[float], + other: np_ndarray_bool | np_ndarray_complex | np_ndarray_dt | np_ndarray_td, + ) -> Never: ... + @overload + def __floordiv__( + self: Series[bool] | Series[complex], other: np_ndarray + ) -> Never: ... + @overload + def __floordiv__( + self: Series[int], other: ( - float - | Sequence[float] - | np_ndarray_bool + Just[int] + | Sequence[Just[int]] + | np_ndarray_anyint + | Index[int] + | Series[int] + ), + ) -> Series[int]: ... + @overload + def __floordiv__( + self: Series[int], + other: ( + Just[float] + | Sequence[Just[float]] + | np_ndarray_float + | Index[float] + | Series[float] + ), + ) -> Series[float]: ... + @overload + def __floordiv__( + self: Series[float], + other: ( + Just[int] + | Just[float] + | Sequence[Just[int]] + | Sequence[Just[float]] | np_ndarray_anyint | np_ndarray_float - | Index[bool] | Index[int] | Index[float] - | Series[bool] | Series[int] | Series[float] ), - ) -> Series[int]: ... + ) -> Series[float]: ... + @overload + def __floordiv__( + self: Series[Timedelta], + other: np_ndarray_bool | np_ndarray_complex | np_ndarray_dt, + ) -> Never: ... @overload def __floordiv__( self: Series[Timedelta], other: ( - float - | Sequence[float] - | np_ndarray_bool + Just[int] + | Just[float] + | Sequence[Just[int]] + | Sequence[Just[float]] | np_ndarray_anyint | np_ndarray_float - | Index[bool] | Index[int] | Index[float] - | Series[bool] | Series[int] | Series[float] ), @@ -2309,7 +2344,14 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def __floordiv__( self: Series[Timedelta], - other: timedelta | Sequence[timedelta] | np.timedelta64 | Series[Timedelta], + other: ( + timedelta + | Sequence[timedelta] + | np.timedelta64 + | np_ndarray_td + | TimedeltaIndex + | Series[Timedelta] + ), ) -> Series[int]: ... @overload def floordiv( @@ -2321,37 +2363,63 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Series: ... @overload def floordiv( - self: Series[bool] | Series[int] | Series[float], + self: Series[int], other: ( - float - | Sequence[float] - | np_ndarray_bool + Just[int] + | Sequence[Just[int]] + | np_ndarray_anyint + | Index[int] + | Series[int] + ), + level: Level | None = ..., + fill_value: float | None = None, + axis: AxisIndex | None = 0, + ) -> Series[int]: ... + @overload + def floordiv( + self: Series[int], + other: ( + Just[float] + | Sequence[Just[float]] + | np_ndarray_float + | Index[float] + | Series[float] + ), + level: Level | None = ..., + fill_value: float | None = None, + axis: AxisIndex | None = 0, + ) -> Series[float]: ... + @overload + def floordiv( + self: Series[float], + other: ( + Just[int] + | Just[float] + | Sequence[Just[int]] + | Sequence[Just[float]] | np_ndarray_anyint | np_ndarray_float - | Index[bool] | Index[int] | Index[float] - | Series[bool] | Series[int] | Series[float] ), level: Level | None = ..., fill_value: float | None = None, axis: AxisIndex | None = 0, - ) -> Series[int]: ... + ) -> Series[float]: ... @overload def floordiv( self: Series[Timedelta], other: ( - float - | Sequence[float] - | np_ndarray_bool + Just[int] + | Just[float] + | Sequence[Just[int]] + | Sequence[Just[float]] | np_ndarray_anyint | np_ndarray_float - | Index[bool] | Index[int] | Index[float] - | Series[bool] | Series[int] | Series[float] ), @@ -2366,6 +2434,7 @@ class Series(IndexOpsMixin[S1], NDFrame): timedelta | Sequence[timedelta] | np.timedelta64 + | np_ndarray_td | TimedeltaIndex | Series[Timedelta] ), @@ -2377,21 +2446,62 @@ class Series(IndexOpsMixin[S1], NDFrame): def __rfloordiv__(self, other: Index[Never] | Series[Never]) -> Series: ... @overload def __rfloordiv__( - self: Series[bool] | Series[int] | Series[float], + self: Series[int] | Series[float], + other: np_ndarray_bool | np_ndarray_complex | np_ndarray_dt | np_ndarray_td, + ) -> Never: ... + @overload + def __rfloordiv__( + self: Series[bool] | Series[complex], other: np_ndarray + ) -> Never: ... + @overload + def __rfloordiv__( + self: Series[int], other: ( - float - | Sequence[float] - | np_ndarray_bool + Just[int] + | Sequence[Just[int]] + | np_ndarray_anyint + | Index[int] + | Series[int] + ), + ) -> Series[int]: ... + @overload + def __rfloordiv__( + self: Series[int], + other: ( + Just[float] + | Sequence[Just[float]] + | np_ndarray_float + | Index[float] + | Series[float] + ), + ) -> Series[float]: ... + @overload + def __rfloordiv__( + self: Series[float], + other: ( + Just[int] + | Just[float] + | Sequence[Just[int]] + | Sequence[Just[float]] | np_ndarray_anyint | np_ndarray_float - | Index[bool] | Index[int] | Index[float] - | Series[bool] | Series[int] | Series[float] ), - ) -> Series[int]: ... + ) -> Series[float]: ... + @overload + def __rfloordiv__( + self: Series[Timedelta], + other: ( + np_ndarray_bool + | np_ndarray_anyint + | np_ndarray_float + | np_ndarray_complex + | np_ndarray_dt + ), + ) -> Never: ... @overload def __rfloordiv__( self: Series[Timedelta], @@ -2399,6 +2509,7 @@ class Series(IndexOpsMixin[S1], NDFrame): timedelta | Sequence[timedelta] | np.timedelta64 + | np_ndarray_td | TimedeltaIndex | Series[Timedelta] ), @@ -2413,23 +2524,51 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Series: ... @overload def rfloordiv( - self: Series[bool] | Series[int] | Series[float], + self: Series[int], other: ( - float - | Sequence[float] - | np_ndarray_bool + Just[int] + | Sequence[Just[int]] + | np_ndarray_anyint + | Index[int] + | Series[int] + ), + level: Level | None = ..., + fill_value: float | None = None, + axis: AxisIndex = ..., + ) -> Series[int]: ... + @overload + def rfloordiv( + self: Series[int], + other: ( + Just[float] + | Sequence[Just[float]] + | np_ndarray_float + | Index[float] + | Series[float] + ), + level: Level | None = ..., + fill_value: float | None = None, + axis: AxisIndex = ..., + ) -> Series[float]: ... + @overload + def rfloordiv( + self: Series[float], + other: ( + Just[int] + | Just[float] + | Sequence[Just[int]] + | Sequence[Just[float]] | np_ndarray_anyint | np_ndarray_float - | Index[bool] | Index[int] | Index[float] - | Series[bool] + | Series[int] | Series[float] ), level: Level | None = ..., fill_value: float | None = None, axis: AxisIndex = ..., - ) -> Series[int]: ... + ) -> Series[float]: ... @overload def rfloordiv( self: Series[Timedelta], @@ -2437,6 +2576,7 @@ class Series(IndexOpsMixin[S1], NDFrame): timedelta | Sequence[timedelta] | np.timedelta64 + | np_ndarray_td | TimedeltaIndex | Series[Timedelta] ), diff --git a/tests/series/arithmetic/float/test_floordiv.py b/tests/series/arithmetic/float/test_floordiv.py new file mode 100644 index 000000000..428885ea9 --- /dev/null +++ b/tests/series/arithmetic/float/test_floordiv.py @@ -0,0 +1,178 @@ +from typing import Any + +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([1.2, 2.4, 3.6]) # left operand + + +def test_floordiv_py_scalar() -> None: + """Test pd.Series[float] // Python native scalars""" + b, i, f, c = True, 1, 1.0, 1j + + if TYPE_CHECKING_INVALID_USAGE: + _0 = left // b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left // i, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left // f, "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _1 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + _2 = b // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(i // left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(f // left, "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _3 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + left.floordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.floordiv(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.floordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left.floordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + left.rfloordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rfloordiv(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.rfloordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left.rfloordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + +def test_floordiv_py_sequence() -> None: + """Test pd.Series[float] // Python native sequences""" + b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] + + if TYPE_CHECKING_INVALID_USAGE: + _0 = left // b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left // i, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left // f, "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _1 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + _2 = b // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(i // left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(f // left, "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _3 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + left.floordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.floordiv(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.floordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left.floordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + left.rfloordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rfloordiv(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.rfloordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left.rfloordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + +def test_floordiv_numpy_array() -> None: + """Test pd.Series[float] // numpy arrays""" + b = np.array([True, False, True], np.bool_) + i = np.array([2, 3, 5], np.int64) + f = np.array([1.0, 2.0, 3.0], np.float64) + c = np.array([1.1j, 2.2j, 4.1j], np.complex128) + + if TYPE_CHECKING_INVALID_USAGE: + assert_type(left // b, Never) + check(assert_type(left // i, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left // f, "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + assert_type(left // c, Never) + + # `numpy` typing gives the corresponding `ndarray`s in the static type + # checking, where our `__rsub__` cannot override. At runtime, they lead to + # errors or pd.Series. + assert_type(b // left, "npt.NDArray[np.int8]") + check(i // left, pd.Series, np.floating) + check(f // left, pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + assert_type(c // left, Any) + + left.floordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.floordiv(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.floordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left.floordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + left.rfloordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rfloordiv(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.rfloordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left.rfloordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + +def test_floordiv_pd_index() -> None: + """Test pd.Series[float] // pandas Indexes""" + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) + + if TYPE_CHECKING_INVALID_USAGE: + _0 = left // b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left // i, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left // f, "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _1 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + _2 = b // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(i // left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(f // left, "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _3 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + left.floordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.floordiv(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.floordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left.floordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + left.rfloordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rfloordiv(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.rfloordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left.rfloordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + +def test_floordiv_pd_series() -> None: + """Test pd.Series[float] // pandas Series""" + b = pd.Series([True, False, True]) + i = pd.Series([2, 3, 5]) + f = pd.Series([1.0, 2.0, 3.0]) + c = pd.Series([1.1j, 2.2j, 4.1j]) + + if TYPE_CHECKING_INVALID_USAGE: + _0 = left // b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left // i, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left // f, "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _1 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + _2 = b // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(i // left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(f // left, "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _3 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + left.floordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.floordiv(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.floordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left.floordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + left.rfloordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rfloordiv(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.rfloordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left.rfloordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] diff --git a/tests/series/arithmetic/int/test_floordiv.py b/tests/series/arithmetic/int/test_floordiv.py new file mode 100644 index 000000000..9ab65269f --- /dev/null +++ b/tests/series/arithmetic/int/test_floordiv.py @@ -0,0 +1,178 @@ +from typing import Any + +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([1, 2, 3]) # left operand + + +def test_floordiv_py_scalar() -> None: + """Test pd.Series[int] // Python native scalars""" + b, i, f, c = True, 1, 1.0, 1j + + if TYPE_CHECKING_INVALID_USAGE: + _0 = left // b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left // i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left // f, "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _1 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + _2 = b // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(i // left, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(f // left, "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _3 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + left.floordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.floordiv(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.floordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left.floordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + left.rfloordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rfloordiv(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.rfloordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left.rfloordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + +def test_floordiv_py_sequence() -> None: + """Test pd.Series[int] // Python native sequences""" + b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] + + if TYPE_CHECKING_INVALID_USAGE: + _0 = left // b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left // i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left // f, "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _1 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + _2 = b // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(i // left, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(f // left, "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _3 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + left.floordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.floordiv(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.floordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left.floordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + left.rfloordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rfloordiv(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.rfloordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left.rfloordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + +def test_floordiv_numpy_array() -> None: + """Test pd.Series[int] // numpy arrays""" + b = np.array([True, False, True], np.bool_) + i = np.array([2, 3, 5], np.int64) + f = np.array([1.0, 2.0, 3.0], np.float64) + c = np.array([1.1j, 2.2j, 4.1j], np.complex128) + + if TYPE_CHECKING_INVALID_USAGE: + assert_type(left // b, Never) + check(assert_type(left // i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left // f, "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + assert_type(left // c, Never) + + # `numpy` typing gives the corresponding `ndarray`s in the static type + # checking, where our `__rsub__` cannot override. At runtime, they lead to + # errors or pd.Series. + assert_type(b // left, "npt.NDArray[np.int8]") + check(i // left, pd.Series, np.integer) + check(f // left, pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + assert_type(c // left, Any) + + left.floordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.floordiv(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.floordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left.floordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + left.rfloordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rfloordiv(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.rfloordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left.rfloordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + +def test_floordiv_pd_index() -> None: + """Test pd.Series[int] // pandas Indexes""" + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) + + if TYPE_CHECKING_INVALID_USAGE: + _0 = left // b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left // i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left // f, "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _1 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + _2 = b // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(i // left, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(f // left, "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _3 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + left.floordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.floordiv(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.floordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left.floordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + left.rfloordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rfloordiv(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.rfloordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left.rfloordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + +def test_floordiv_pd_series() -> None: + """Test pd.Series[int] // pandas Series""" + b = pd.Series([True, False, True]) + i = pd.Series([2, 3, 5]) + f = pd.Series([1.0, 2.0, 3.0]) + c = pd.Series([1.1j, 2.2j, 4.1j]) + + if TYPE_CHECKING_INVALID_USAGE: + _0 = left // b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left // i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left // f, "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _1 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + _2 = b // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(i // left, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(f // left, "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _3 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + left.floordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.floordiv(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.floordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left.floordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + left.rfloordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rfloordiv(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.rfloordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left.rfloordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] diff --git a/tests/series/arithmetic/timedelta/test_floordiv.py b/tests/series/arithmetic/timedelta/test_floordiv.py new file mode 100644 index 000000000..1cd7b1dee --- /dev/null +++ b/tests/series/arithmetic/timedelta/test_floordiv.py @@ -0,0 +1,294 @@ +from datetime import ( + datetime, + timedelta, +) +from typing import Any + +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.Timedelta(1, "s")]) # left operand + + +def test_floordiv_py_scalar() -> None: + """Test pd.Series[pd.Timedelta] // Python native scalars""" + b, i, f, c = True, 1, 1.0, 1j + s, d = datetime(2025, 9, 24), timedelta(seconds=1) + + if TYPE_CHECKING_INVALID_USAGE: + _0 = left // b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left // i, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left // f, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + _1 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _2 = left // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left // d, "pd.Series[int]"), pd.Series, np.integer) + + if TYPE_CHECKING_INVALID_USAGE: + _3 = b // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _4 = i // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _5 = f // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _6 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _7 = s // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d // left, "pd.Series[int]"), pd.Series, np.integer) + + if TYPE_CHECKING_INVALID_USAGE: + left.floordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left.floordiv(i), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) + check( + assert_type(left.floordiv(f), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) + if TYPE_CHECKING_INVALID_USAGE: + left.floordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.floordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.floordiv(d), "pd.Series[int]"), pd.Series, np.integer) + + if TYPE_CHECKING_INVALID_USAGE: + left.rfloordiv(b) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rfloordiv(i) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rfloordiv(f) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rfloordiv(c) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rfloordiv(s) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rfloordiv(d), "pd.Series[int]"), pd.Series, np.integer) + + +def test_floordiv_py_sequence() -> None: + """Test pd.Series[pd.Timedelta] // Python native sequences""" + b, i, f, c = [True], [2], [1.5], [1.7j] + s, d = [datetime(2025, 9, 24)], [timedelta(seconds=1)] + + if TYPE_CHECKING_INVALID_USAGE: + _0 = left // b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left // i, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left // f, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + _1 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _2 = left // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left // d, "pd.Series[int]"), pd.Series, int) + + if TYPE_CHECKING_INVALID_USAGE: + _3 = b // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _4 = i // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _5 = f // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _6 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _7 = s // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d // left, "pd.Series[int]"), pd.Series, np.integer) + + if TYPE_CHECKING_INVALID_USAGE: + left.floordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left.floordiv(i), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) + check( + assert_type(left.floordiv(f), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) + if TYPE_CHECKING_INVALID_USAGE: + left.floordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.floordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.floordiv(d), "pd.Series[int]"), pd.Series, np.integer) + + if TYPE_CHECKING_INVALID_USAGE: + left.rfloordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rfloordiv(i) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rfloordiv(f) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rfloordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rfloordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rfloordiv(d), "pd.Series[int]"), pd.Series, np.integer) + + +def test_floordiv_numpy_array() -> None: + """Test pd.Series[pd.Timedelta] // numpy arrays""" + b = np.array([True], np.bool_) + i = np.array([2], np.int64) + f = np.array([1.5], np.float64) + c = np.array([1.7j], np.complex128) + s = np.array([datetime(2025, 9, 24)], np.datetime64) + d = np.array([timedelta(seconds=1)], np.timedelta64) + + if TYPE_CHECKING_INVALID_USAGE: + assert_type(left // b, Never) + check(assert_type(left // i, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left // f, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + assert_type(left // c, Never) + assert_type(left // s, Never) + check(assert_type(left // d, "pd.Series[int]"), pd.Series, np.integer) + + # `numpy` typing gives the corresponding `ndarray`s in the static type + # checking, where our `__rsub__` cannot override. At runtime, they lead to + # errors or pd.Series. + if TYPE_CHECKING_INVALID_USAGE: + assert_type(b // left, "npt.NDArray[np.int8]") + assert_type(i // left, "npt.NDArray[np.int64]") + assert_type(f // left, "npt.NDArray[np.float64]") + assert_type(c // left, Any) + assert_type(s // left, Any) + check(assert_type(d // left, "npt.NDArray[np.int64]"), pd.Series, np.integer) + + if TYPE_CHECKING_INVALID_USAGE: + left.floordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left.floordiv(i), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) + check( + assert_type(left.floordiv(f), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) + if TYPE_CHECKING_INVALID_USAGE: + left.floordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.floordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.floordiv(d), "pd.Series[int]"), pd.Series, np.integer) + + if TYPE_CHECKING_INVALID_USAGE: + left.rfloordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rfloordiv(i) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rfloordiv(f) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rfloordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rfloordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rfloordiv(d), "pd.Series[int]"), pd.Series, np.integer) + + +def test_floordiv_pd_scalar() -> None: + """Test pd.Series[pd.Timedelta] // pandas scalars""" + s, d = pd.Timestamp(2025, 9, 24), 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[int]"), pd.Series, np.integer) + + if TYPE_CHECKING_INVALID_USAGE: + _1 = s // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d // left, "pd.Series[int]"), pd.Series, np.integer) + + if TYPE_CHECKING_INVALID_USAGE: + left.floordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.floordiv(d), "pd.Series[int]"), pd.Series, np.integer) + + if TYPE_CHECKING_INVALID_USAGE: + left.rfloordiv(s) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rfloordiv(d), "pd.Series[int]"), pd.Series, np.integer) + + +def test_floordiv_pd_index() -> None: + """Test pd.Series[pd.Timedelta] // pandas Indexes""" + b = pd.Index([True]) + i = pd.Index([2]) + f = pd.Index([1.5]) + c = pd.Index([1.7j]) + s, d = pd.Index([datetime(2025, 9, 24)]), pd.Index([timedelta(seconds=1)]) + + if TYPE_CHECKING_INVALID_USAGE: + _0 = left // b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left // i, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left // f, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + _1 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _2 = left // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left // d, "pd.Series[int]"), pd.Series, np.integer) + + if TYPE_CHECKING_INVALID_USAGE: + _3 = b // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _4 = i // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _5 = f // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _6 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _7 = s // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d // left, "pd.Series[int]"), pd.Series, np.integer) + + if TYPE_CHECKING_INVALID_USAGE: + left.floordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left.floordiv(i), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) + check( + assert_type(left.floordiv(f), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) + if TYPE_CHECKING_INVALID_USAGE: + left.floordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.floordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.floordiv(d), "pd.Series[int]"), pd.Series, np.integer) + + if TYPE_CHECKING_INVALID_USAGE: + left.rfloordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rfloordiv(i) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rfloordiv(f) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rfloordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rfloordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rfloordiv(d), "pd.Series[int]"), pd.Series, np.integer) + + +def test_floordiv_pd_series() -> None: + """Test pd.Series[pd.Timedelta] // pandas Series""" + b = pd.Series([True]) + i = pd.Series([2]) + f = pd.Series([1.5]) + c = pd.Series([1.7j]) + s, d = pd.Series([datetime(2025, 9, 24)]), pd.Series([timedelta(seconds=1)]) + + if TYPE_CHECKING_INVALID_USAGE: + _0 = left // b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left // i, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(left // f, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + _1 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _2 = left // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left // d, "pd.Series[int]"), pd.Series, np.integer) + + if TYPE_CHECKING_INVALID_USAGE: + _3 = b // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _4 = i // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _5 = f // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _6 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _7 = s // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d // left, "pd.Series[int]"), pd.Series, np.integer) + + if TYPE_CHECKING_INVALID_USAGE: + left.floordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left.floordiv(i), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) + check( + assert_type(left.floordiv(f), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) + if TYPE_CHECKING_INVALID_USAGE: + left.floordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.floordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.floordiv(d), "pd.Series[int]"), pd.Series, np.integer) + + if TYPE_CHECKING_INVALID_USAGE: + left.rfloordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rfloordiv(i) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rfloordiv(f) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rfloordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.rfloordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rfloordiv(d), "pd.Series[int]"), pd.Series, np.integer) From 9e840fceda364c6173e48975b87429ee135258ca Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Wed, 24 Sep 2025 22:11:36 +0200 Subject: [PATCH 08/13] feat(test): remove redundant --- tests/series/test_series.py | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/tests/series/test_series.py b/tests/series/test_series.py index b69cf6793..9a5087b8a 100644 --- a/tests/series/test_series.py +++ b/tests/series/test_series.py @@ -3187,33 +3187,6 @@ def double(x): check(assert_type(s.mask(s > 3, pd.NA), "pd.Series[int]"), pd.Series, np.float64) -def test_timedelta_div() -> None: - series = pd.Series([pd.Timedelta(days=1)]) - delta = datetime.timedelta(1) - - check(assert_type(series / delta, "pd.Series[float]"), pd.Series, float) - check(assert_type(series / [delta], "pd.Series[float]"), pd.Series, float) - check(assert_type(series / 1, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) - check(assert_type(series / [1], "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) - check(assert_type(series // delta, "pd.Series[int]"), pd.Series, np.longlong) - check(assert_type(series // [delta], "pd.Series[int]"), pd.Series, int) - check(assert_type(series // 1, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) - check( - assert_type(series // [1], "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta - ) - - check(assert_type(delta / series, "pd.Series[float]"), pd.Series, float) - check(assert_type([delta] / series, "pd.Series[float]"), pd.Series, float) - check(assert_type(delta // series, "pd.Series[int]"), pd.Series, np.longlong) - check(assert_type([delta] // series, "pd.Series[int]"), pd.Series, np.signedinteger) - - if TYPE_CHECKING_INVALID_USAGE: - 1 / series # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - [1] / series # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - 1 // series # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - [1] // series # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - - def test_rank() -> None: check( assert_type(pd.Series([1, 2]).rank(), "pd.Series[float]"), pd.Series, np.float64 From 27e81a047caf94cfc11150e1ee2a55834c3019cd Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Wed, 24 Sep 2025 22:36:38 +0200 Subject: [PATCH 09/13] fix: pandas-dev/pandas#62316 --- tests/series/arithmetic/timedelta/test_mul.py | 79 ++++++++++++++----- 1 file changed, 60 insertions(+), 19 deletions(-) diff --git a/tests/series/arithmetic/timedelta/test_mul.py b/tests/series/arithmetic/timedelta/test_mul.py index 4cf585cd4..8f83ca19e 100644 --- a/tests/series/arithmetic/timedelta/test_mul.py +++ b/tests/series/arithmetic/timedelta/test_mul.py @@ -19,25 +19,36 @@ def test_mul_py_scalar() -> None: """Test pd.Series[pd.Timedelta] * Python native scalars""" b, i, f, c = True, 1, 1.0, 1j - check(assert_type(left * b, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + # pandas-dev/pandas#62316 + if PD_LTE_23: + check(assert_type(left * b, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(left * i, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(left * f, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) if TYPE_CHECKING_INVALID_USAGE: _0 = left * c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - check(assert_type(b * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if PD_LTE_23: + check(assert_type(b * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(i * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(f * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) if TYPE_CHECKING_INVALID_USAGE: _1 = c * left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - check(assert_type(left.mul(b), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if PD_LTE_23: + check( + assert_type(left.mul(b), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta + ) check(assert_type(left.mul(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(left.mul(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) if TYPE_CHECKING_INVALID_USAGE: left.mul(c) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] - check(assert_type(left.rmul(b), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if PD_LTE_23: + check( + assert_type(left.rmul(b), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) check(assert_type(left.rmul(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(left.rmul(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) if TYPE_CHECKING_INVALID_USAGE: @@ -48,25 +59,36 @@ def test_mul_py_sequence() -> None: """Test pd.Series[pd.Timedelta] * Python native sequences""" b, i, f, c = [True], [2], [1.5], [1.7j] - check(assert_type(left * b, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + # pandas-dev/pandas#62316 + if PD_LTE_23: + check(assert_type(left * b, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(left * i, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(left * f, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) if TYPE_CHECKING_INVALID_USAGE: _0 = left * c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - check(assert_type(b * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if PD_LTE_23: + check(assert_type(b * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(i * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(f * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) if TYPE_CHECKING_INVALID_USAGE: _1 = c * left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - check(assert_type(left.mul(b), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if PD_LTE_23: + check( + assert_type(left.mul(b), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta + ) check(assert_type(left.mul(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(left.mul(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) if TYPE_CHECKING_INVALID_USAGE: left.mul(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] - check(assert_type(left.rmul(b), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if PD_LTE_23: + check( + assert_type(left.rmul(b), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) check(assert_type(left.rmul(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(left.rmul(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) if TYPE_CHECKING_INVALID_USAGE: @@ -80,7 +102,9 @@ def test_mul_numpy_array() -> None: f = np.array([1.5], np.float64) c = np.array([1.7j], np.complex128) - check(assert_type(left * b, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + # pandas-dev/pandas#62316 + if PD_LTE_23: + check(assert_type(left * b, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(left * i, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(left * f, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) if TYPE_CHECKING_INVALID_USAGE: @@ -89,20 +113,29 @@ def test_mul_numpy_array() -> None: # `numpy` typing gives the corresponding `ndarray`s in the static type # checking, where our `__rmul__` cannot override. At runtime, they return # `Series` with the correct element type. - check(assert_type(b * left, "npt.NDArray[np.bool_]"), pd.Series, pd.Timedelta) + if PD_LTE_23: + check(assert_type(b * left, "npt.NDArray[np.bool_]"), pd.Series, pd.Timedelta) check(assert_type(i * left, "npt.NDArray[np.int64]"), pd.Series, pd.Timedelta) check(assert_type(f * left, "npt.NDArray[np.float64]"), pd.Series, pd.Timedelta) if TYPE_CHECKING_INVALID_USAGE: # We made it Never, but numpy takes over assert_type(c * left, "npt.NDArray[np.complex128]") - check(assert_type(left.mul(b), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if PD_LTE_23: + check( + assert_type(left.mul(b), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta + ) check(assert_type(left.mul(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(left.mul(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) if TYPE_CHECKING_INVALID_USAGE: left.mul(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] - check(assert_type(left.rmul(b), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if PD_LTE_23: + check( + assert_type(left.rmul(b), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) check(assert_type(left.rmul(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(left.rmul(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) if TYPE_CHECKING_INVALID_USAGE: @@ -116,25 +149,36 @@ def test_mul_pd_index() -> None: f = pd.Index([1.5]) c = pd.Index([1.7j]) - check(assert_type(left * b, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + # pandas-dev/pandas#62316 + if PD_LTE_23: + check(assert_type(left * b, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(left * i, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(left * f, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) if TYPE_CHECKING_INVALID_USAGE: _0 = left * c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - check(assert_type(b * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if PD_LTE_23: + check(assert_type(b * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(i * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(f * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) if TYPE_CHECKING_INVALID_USAGE: _1 = c * left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - check(assert_type(left.mul(b), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if PD_LTE_23: + check( + assert_type(left.mul(b), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta + ) check(assert_type(left.mul(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(left.mul(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) if TYPE_CHECKING_INVALID_USAGE: left.mul(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] - check(assert_type(left.rmul(b), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + if PD_LTE_23: + check( + assert_type(left.rmul(b), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) check(assert_type(left.rmul(i), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(left.rmul(f), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) if TYPE_CHECKING_INVALID_USAGE: @@ -156,7 +200,6 @@ def test_mul_pd_series() -> None: if TYPE_CHECKING_INVALID_USAGE: _0 = left * c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - # pandas-dev/pandas#62316 if PD_LTE_23: check(assert_type(b * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) check(assert_type(i * left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) @@ -164,7 +207,6 @@ def test_mul_pd_series() -> None: if TYPE_CHECKING_INVALID_USAGE: _1 = c * left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - # pandas-dev/pandas#62316 if PD_LTE_23: check( assert_type(left.mul(b), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta @@ -174,7 +216,6 @@ def test_mul_pd_series() -> None: if TYPE_CHECKING_INVALID_USAGE: left.mul(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] - # pandas-dev/pandas#62316 if PD_LTE_23: check( assert_type(left.rmul(b), "pd.Series[pd.Timedelta]"), From 05fad40cce41e740eddfc7467ac4bcabae6f0bd0 Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Thu, 25 Sep 2025 20:05:06 +0200 Subject: [PATCH 10/13] fix: comments --- .pre-commit-config.yaml | 4 +- pandas-stubs/core/frame.pyi | 2 +- pandas-stubs/core/groupby/indexing.pyi | 2 +- pandas-stubs/core/series.pyi | 25 ++++++-- .../series/arithmetic/float/test_floordiv.py | 2 +- tests/series/arithmetic/int/test_floordiv.py | 2 +- .../arithmetic/timedelta/test_floordiv.py | 2 +- .../arithmetic/timedelta/test_truediv.py | 2 +- tests/series/test_agg.py | 60 +++++++++++++++++++ tests/series/test_cumul.py | 8 +++ tests/series/test_series.py | 1 - tests/test_timefuncs.py | 9 ++- ttest.py | 11 ++++ 13 files changed, 112 insertions(+), 18 deletions(-) create mode 100644 tests/series/test_agg.py create mode 100644 ttest.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c04587ea9..6578e1709 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,7 +3,7 @@ ci: autofix_prs: false repos: - repo: https://github.com/python/black - rev: 25.1.0 + rev: 25.9.0 hooks: - id: black - repo: https://github.com/PyCQA/isort @@ -11,7 +11,7 @@ repos: hooks: - id: isort - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.10 + rev: v0.13.1 hooks: - id: ruff-check args: [ diff --git a/pandas-stubs/core/frame.pyi b/pandas-stubs/core/frame.pyi index 5c370d6eb..ce61a30f1 100644 --- a/pandas-stubs/core/frame.pyi +++ b/pandas-stubs/core/frame.pyi @@ -763,7 +763,7 @@ class DataFrame(NDFrame, OpsMixin, _GetItemHack): @overload def to_xml( self, - path_or_buffer: Literal[None] = ..., + path_or_buffer: None = ..., index: bool = ..., root_name: str | None = ..., row_name: str | None = ..., diff --git a/pandas-stubs/core/groupby/indexing.pyi b/pandas-stubs/core/groupby/indexing.pyi index c013d4c74..150a7a86b 100644 --- a/pandas-stubs/core/groupby/indexing.pyi +++ b/pandas-stubs/core/groupby/indexing.pyi @@ -27,6 +27,6 @@ class GroupByNthSelector(Generic[_GroupByT]): def __call__( self, n: PositionalIndexer | tuple, - dropna: Literal["any", "all", None] = ..., + dropna: Literal["any", "all"] | None = ..., ) -> DataFrame | Series: ... def __getitem__(self, n: PositionalIndexer | tuple) -> DataFrame | Series: ... diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index e90214552..362038ffc 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -215,10 +215,14 @@ class _SupportsMul(Protocol[_T_co]): def __mul__(self, value: Self, /) -> _T_co: ... @type_check_only -class _SupportsAddRMul(Protocol[_T_co]): +class _SupportsAdd_MulFloat(Protocol[_T_co]): def __add__(self, value: Self, /) -> _T_co: ... def __mul__(self, value: float, /) -> _T_co: ... +@type_check_only +class SupportsTruedivInt(Protocol[_T_co]): + def __truediv__(self, value: int, /) -> _T_co: ... + class _iLocIndexerSeries(_iLocIndexer, Generic[S1]): # get item @overload @@ -4474,7 +4478,7 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Timestamp: ... @overload def mean( - self: SupportsGetItem[Scalar, _SupportsAddRMul[S1]], + self: SupportsGetItem[Scalar, _SupportsAdd_MulFloat[S1]], axis: AxisIndex | None = 0, skipna: _bool = True, level: None = ..., @@ -4489,25 +4493,34 @@ class Series(IndexOpsMixin[S1], NDFrame): level: None = ..., numeric_only: _bool = False, **kwargs: Any, + ) -> Any: ... + @overload + def median( + self: Series[complex], + axis: AxisIndex | None = 0, + skipna: _bool = True, + level: None = ..., + numeric_only: _bool = False, + **kwargs: Any, ) -> float: ... @overload def median( - self: Series[Timestamp], + self: SupportsGetItem[Scalar, SupportsTruedivInt[S2]], axis: AxisIndex | None = 0, skipna: _bool = True, level: None = ..., numeric_only: _bool = False, **kwargs: Any, - ) -> Timestamp: ... + ) -> S2: ... @overload def median( - self, + self: Series[Timestamp], axis: AxisIndex | None = 0, skipna: _bool = True, level: None = ..., numeric_only: _bool = False, **kwargs: Any, - ) -> S1: ... + ) -> Timestamp: ... def min( self, axis: AxisIndex | None = 0, diff --git a/tests/series/arithmetic/float/test_floordiv.py b/tests/series/arithmetic/float/test_floordiv.py index 428885ea9..2eedc4ef3 100644 --- a/tests/series/arithmetic/float/test_floordiv.py +++ b/tests/series/arithmetic/float/test_floordiv.py @@ -91,7 +91,7 @@ def test_floordiv_numpy_array() -> None: assert_type(left // c, Never) # `numpy` typing gives the corresponding `ndarray`s in the static type - # checking, where our `__rsub__` cannot override. At runtime, they lead to + # checking, where our `__rfloordiv__` cannot override. At runtime, they lead to # errors or pd.Series. assert_type(b // left, "npt.NDArray[np.int8]") check(i // left, pd.Series, np.floating) diff --git a/tests/series/arithmetic/int/test_floordiv.py b/tests/series/arithmetic/int/test_floordiv.py index 9ab65269f..0504d1074 100644 --- a/tests/series/arithmetic/int/test_floordiv.py +++ b/tests/series/arithmetic/int/test_floordiv.py @@ -91,7 +91,7 @@ def test_floordiv_numpy_array() -> None: assert_type(left // c, Never) # `numpy` typing gives the corresponding `ndarray`s in the static type - # checking, where our `__rsub__` cannot override. At runtime, they lead to + # checking, where our `__rfloordiv__` cannot override. At runtime, they lead to # errors or pd.Series. assert_type(b // left, "npt.NDArray[np.int8]") check(i // left, pd.Series, np.integer) diff --git a/tests/series/arithmetic/timedelta/test_floordiv.py b/tests/series/arithmetic/timedelta/test_floordiv.py index 1cd7b1dee..bb267d583 100644 --- a/tests/series/arithmetic/timedelta/test_floordiv.py +++ b/tests/series/arithmetic/timedelta/test_floordiv.py @@ -135,7 +135,7 @@ def test_floordiv_numpy_array() -> None: check(assert_type(left // d, "pd.Series[int]"), pd.Series, np.integer) # `numpy` typing gives the corresponding `ndarray`s in the static type - # checking, where our `__rsub__` cannot override. At runtime, they lead to + # checking, where our `__rfloordiv__` cannot override. At runtime, they lead to # errors or pd.Series. if TYPE_CHECKING_INVALID_USAGE: assert_type(b // left, "npt.NDArray[np.int8]") diff --git a/tests/series/arithmetic/timedelta/test_truediv.py b/tests/series/arithmetic/timedelta/test_truediv.py index a19662e53..1c8a59864 100644 --- a/tests/series/arithmetic/timedelta/test_truediv.py +++ b/tests/series/arithmetic/timedelta/test_truediv.py @@ -161,7 +161,7 @@ def test_truediv_numpy_array() -> None: check(assert_type(left / d, "pd.Series[float]"), pd.Series, np.floating) # `numpy` typing gives the corresponding `ndarray`s in the static type - # checking, where our `__rsub__` cannot override. At runtime, they lead to + # checking, where our `__rtruediv__` cannot override. At runtime, they lead to # errors or pd.Series. if TYPE_CHECKING_INVALID_USAGE: assert_type(b / left, "npt.NDArray[np.float64]") diff --git a/tests/series/test_agg.py b/tests/series/test_agg.py new file mode 100644 index 000000000..e40cacf3e --- /dev/null +++ b/tests/series/test_agg.py @@ -0,0 +1,60 @@ +from typing import Any + +import numpy as np +import pandas as pd +from typing_extensions import assert_type + +from tests import ( + TYPE_CHECKING_INVALID_USAGE, + check, + pytest_warns_bounded, +) + + +def test_agg_any_float() -> None: + series = pd.DataFrame({"A": [1.0, float("nan"), 2.0]})["A"] + check(assert_type(series.median(), Any), np.float64) + + +def test_agg_bool() -> None: + series = pd.Series([True, False, True]) + check(assert_type(series.median(), float), np.float64) + + +def test_agg_int() -> None: + series = pd.Series([3, 1, 2]) + check(assert_type(series.median(), float), np.float64) + + +def test_agg_float() -> None: + series = pd.Series([3.0, float("nan"), 2.0]) + check(assert_type(series.median(), float), np.float64) + + +def test_agg_complex() -> None: + series = pd.Series([3j, 3 + 4j, 2j]) + with pytest_warns_bounded( + np.exceptions.ComplexWarning, + r"Casting complex values to real discards the imaginary part", + ): + check(assert_type(series.median(), float), np.float64) + + +def test_agg_str() -> None: + series = pd.Series(["1", "a", "🐼"]) + if TYPE_CHECKING_INVALID_USAGE: + series.median() # type: ignore[misc] # pyright: ignore[reportAttributeAccessIssue] + + +def test_agg_ts() -> None: + series = pd.Series(pd.to_datetime(["2025-09-18", "2025-09-18", "2025-09-18"])) + check(assert_type(series, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + + check(assert_type(series.median(), pd.Timestamp), pd.Timestamp) + + +def test_agg_td() -> None: + series = pd.Series(pd.to_timedelta(["1 days", "2 days", "3 days"])) + check(assert_type(series, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(series.median(), pd.Timedelta), pd.Timedelta) diff --git a/tests/series/test_cumul.py b/tests/series/test_cumul.py index 5c1980a46..fd98cf243 100644 --- a/tests/series/test_cumul.py +++ b/tests/series/test_cumul.py @@ -49,3 +49,11 @@ def test_cumul_ts() -> None: if TYPE_CHECKING_INVALID_USAGE: series.cumprod() # type: ignore[misc] # pyright: ignore[reportAttributeAccessIssue] + + +def test_cumul_td() -> None: + series = pd.Series(pd.to_timedelta(["1 days", "2 days", "3 days"])) + check(assert_type(series, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + if TYPE_CHECKING_INVALID_USAGE: + series.cumprod() # type: ignore[misc] # pyright: ignore[reportAttributeAccessIssue] diff --git a/tests/series/test_series.py b/tests/series/test_series.py index 9a5087b8a..7ec856c76 100644 --- a/tests/series/test_series.py +++ b/tests/series/test_series.py @@ -507,7 +507,6 @@ def test_types_mean() -> None: def test_types_median() -> None: s = pd.Series([1, 2, 3, np.nan]) - check(assert_type(s.median(), float), float) check( assert_type(s.groupby(level=0).median(), "pd.Series[float]"), pd.Series, diff --git a/tests/test_timefuncs.py b/tests/test_timefuncs.py index c007bfafd..18012f210 100644 --- a/tests/test_timefuncs.py +++ b/tests/test_timefuncs.py @@ -1041,6 +1041,11 @@ def test_series_types_to_numpy() -> None: np_1darray, dtype=np.int64, ) + check( + assert_type(td_s.to_numpy(dtype=np.timedelta64), np_1darray[np.timedelta64]), + np_1darray, + dtype=np.timedelta64, + ) check( assert_type(ts_s.to_numpy(dtype=np.int64), np_1darray[np.int64]), np_1darray, @@ -1718,10 +1723,9 @@ def test_timedeltaseries_add_timestampseries() -> None: check(assert_type(plus, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) -def test_mean_median_std() -> None: +def test_mean_std() -> None: s = pd.Series([pd.Timedelta("1 ns"), pd.Timedelta("2 ns"), pd.Timedelta("3 ns")]) check(assert_type(s.mean(), pd.Timedelta), pd.Timedelta) - check(assert_type(s.median(), pd.Timedelta), pd.Timedelta) check(assert_type(s.std(), pd.Timedelta), pd.Timedelta) s2 = pd.Series( @@ -1732,7 +1736,6 @@ def test_mean_median_std() -> None: ] ) check(assert_type(s2.mean(), pd.Timestamp), pd.Timestamp) - check(assert_type(s2.median(), pd.Timestamp), pd.Timestamp) check(assert_type(s2.std(), pd.Timedelta), pd.Timedelta) diff --git a/ttest.py b/ttest.py new file mode 100644 index 000000000..c19001886 --- /dev/null +++ b/ttest.py @@ -0,0 +1,11 @@ +from typing import reveal_type + +import pandas as pd + +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"])) +reveal_type(s2) +td = s1 - s2 +reveal_type(td) +ssum = s1 + s2 From bad9882b3918c05d7ca1c6b0a2b408b62ff4985f Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Thu, 25 Sep 2025 20:30:56 +0200 Subject: [PATCH 11/13] fix(test): ignore mypy for now --- tests/test_timefuncs.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_timefuncs.py b/tests/test_timefuncs.py index 18012f210..cf987df5d 100644 --- a/tests/test_timefuncs.py +++ b/tests/test_timefuncs.py @@ -1042,7 +1042,8 @@ def test_series_types_to_numpy() -> None: dtype=np.int64, ) check( - assert_type(td_s.to_numpy(dtype=np.timedelta64), np_1darray[np.timedelta64]), + # mypy gives error: Expression is of type "ndarray[tuple[int], dtype[timedelta64[Any]]]", not "ndarray[tuple[int], dtype[timedelta64[timedelta | int | None]]]" [assert-type] + assert_type(td_s.to_numpy(dtype=np.timedelta64), np_1darray[np.timedelta64]), # type: ignore[assert-type] np_1darray, dtype=np.timedelta64, ) From ddc41d16d9838b939e3ff31d7e943afe73f8e50a Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Fri, 26 Sep 2025 10:58:56 +0200 Subject: [PATCH 12/13] fix: comments --- pandas-stubs/_typing.pyi | 8 ++++++++ pandas-stubs/core/series.pyi | 36 +++++++++++++++++++++++++----------- tests/series/test_agg.py | 25 +++++++++++++++++++++++++ tests/series/test_series.py | 2 -- tests/test_timefuncs.py | 16 ---------------- ttest.py | 11 ----------- 6 files changed, 58 insertions(+), 40 deletions(-) delete mode 100644 ttest.py diff --git a/pandas-stubs/_typing.pyi b/pandas-stubs/_typing.pyi index 95e184356..d75d7a3ef 100644 --- a/pandas-stubs/_typing.pyi +++ b/pandas-stubs/_typing.pyi @@ -825,6 +825,14 @@ np_ndarray_td: TypeAlias = npt.NDArray[np.timedelta64] # Define shape and generic type variables with defaults similar to numpy GenericT = TypeVar("GenericT", bound=np.generic, default=Any) +TD64ItemT = TypeVar( + "TD64ItemT", + bound=datetime.timedelta | int | None, + default=datetime.timedelta | int | None, +) +DT64ItemT = TypeVar( + "DT64ItemT", bound=datetime.date | int | None, default=datetime.date | int | None +) GenericT_co = TypeVar("GenericT_co", bound=np.generic, default=Any, covariant=True) ShapeT = TypeVar("ShapeT", bound=tuple[int, ...], default=tuple[Any, ...]) # Numpy ndarray with more ergonomic typevar diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index 362038ffc..5a843b678 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -214,11 +214,6 @@ class _SupportsAdd(Protocol[_T_co]): class _SupportsMul(Protocol[_T_co]): def __mul__(self, value: Self, /) -> _T_co: ... -@type_check_only -class _SupportsAdd_MulFloat(Protocol[_T_co]): - def __add__(self, value: Self, /) -> _T_co: ... - def __mul__(self, value: float, /) -> _T_co: ... - @type_check_only class SupportsTruedivInt(Protocol[_T_co]): def __truediv__(self, value: int, /) -> _T_co: ... @@ -4466,7 +4461,7 @@ class Series(IndexOpsMixin[S1], NDFrame): level: None = ..., numeric_only: _bool = False, **kwargs: Any, - ) -> float: ... + ) -> Any: ... @overload def mean( self: Series[Timestamp], @@ -4478,13 +4473,13 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Timestamp: ... @overload def mean( - self: SupportsGetItem[Scalar, _SupportsAdd_MulFloat[S1]], + self: SupportsGetItem[Scalar, SupportsTruedivInt[S2]], axis: AxisIndex | None = 0, skipna: _bool = True, level: None = ..., numeric_only: _bool = False, **kwargs: Any, - ) -> S1: ... + ) -> S2: ... @overload def median( self: Series[Never], @@ -4632,7 +4627,26 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Scalar: ... @overload def std( - self: Series[Timestamp] | Series[Timedelta], + self: Series[Never], + axis: AxisIndex | None = 0, + skipna: _bool | None = True, + ddof: int = 1, + numeric_only: _bool = False, + **kwargs: Any, + ) -> Any: ... + @overload + def std( + self: Series[complex], + axis: AxisIndex | None = 0, + skipna: _bool | None = True, + level: None = ..., + ddof: int = ..., + numeric_only: _bool = False, + **kwargs: Any, + ) -> np.float64: ... + @overload + def std( + self: Series[Timestamp], axis: AxisIndex | None = 0, skipna: _bool | None = True, level: None = ..., @@ -4642,13 +4656,13 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Timedelta: ... @overload def std( - self, + self: SupportsGetItem[Scalar, SupportsTruedivInt[S2]], axis: AxisIndex | None = 0, skipna: _bool | None = True, ddof: int = 1, numeric_only: _bool = False, **kwargs: Any, - ) -> float: ... + ) -> S2: ... def sum( self: SupportsGetItem[Scalar, _SupportsAdd[_T]], axis: AxisIndex | None = 0, diff --git a/tests/series/test_agg.py b/tests/series/test_agg.py index e40cacf3e..bfc1e2017 100644 --- a/tests/series/test_agg.py +++ b/tests/series/test_agg.py @@ -13,48 +13,73 @@ def test_agg_any_float() -> None: series = pd.DataFrame({"A": [1.0, float("nan"), 2.0]})["A"] + check(assert_type(series.mean(), Any), np.float64) check(assert_type(series.median(), Any), np.float64) + check(assert_type(series.std(), Any), np.float64) def test_agg_bool() -> None: series = pd.Series([True, False, True]) + check(assert_type(series.mean(), float), np.float64) check(assert_type(series.median(), float), np.float64) + check(assert_type(series.std(), float), np.float64) def test_agg_int() -> None: series = pd.Series([3, 1, 2]) + check(assert_type(series.mean(), float), np.float64) check(assert_type(series.median(), float), np.float64) + check(assert_type(series.std(), float), np.float64) def test_agg_float() -> None: series = pd.Series([3.0, float("nan"), 2.0]) + check(assert_type(series.mean(), float), np.float64) check(assert_type(series.median(), float), np.float64) + check(assert_type(series.std(), float), np.float64) def test_agg_complex() -> None: series = pd.Series([3j, 3 + 4j, 2j]) + check(assert_type(series, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(series.mean(), complex), np.complex128) with pytest_warns_bounded( np.exceptions.ComplexWarning, r"Casting complex values to real discards the imaginary part", ): check(assert_type(series.median(), float), np.float64) + with ( + pytest_warns_bounded( + np.exceptions.ComplexWarning, + r"Casting complex values to real discards the imaginary part", + ), + pytest_warns_bounded(RuntimeWarning, r"invalid value encountered in sqrt"), + ): + check(assert_type(series.std(), np.float64), np.float64) def test_agg_str() -> None: series = pd.Series(["1", "a", "🐼"]) if TYPE_CHECKING_INVALID_USAGE: + series.mean() # type: ignore[misc] # pyright: ignore[reportAttributeAccessIssue] series.median() # type: ignore[misc] # pyright: ignore[reportAttributeAccessIssue] + series.std() # type: ignore[misc] # pyright: ignore[reportAttributeAccessIssue] def test_agg_ts() -> None: series = pd.Series(pd.to_datetime(["2025-09-18", "2025-09-18", "2025-09-18"])) check(assert_type(series, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) + check(assert_type(series.mean(), pd.Timestamp), pd.Timestamp) check(assert_type(series.median(), pd.Timestamp), pd.Timestamp) + check(assert_type(series.std(), pd.Timedelta), pd.Timedelta) def test_agg_td() -> None: series = pd.Series(pd.to_timedelta(["1 days", "2 days", "3 days"])) check(assert_type(series, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(series.mean(), pd.Timedelta), pd.Timedelta) check(assert_type(series.median(), pd.Timedelta), pd.Timedelta) + check(assert_type(series.std(), pd.Timedelta), pd.Timedelta) diff --git a/tests/series/test_series.py b/tests/series/test_series.py index 7ec856c76..8160e0baa 100644 --- a/tests/series/test_series.py +++ b/tests/series/test_series.py @@ -495,7 +495,6 @@ def test_types_rank() -> None: def test_types_mean() -> None: s = pd.Series([1, 2, 3, np.nan]) - check(assert_type(s.mean(), float), float) check( assert_type(s.groupby(level=0).mean(), "pd.Series[float]"), pd.Series, @@ -740,7 +739,6 @@ def test_types_var() -> None: def test_types_std() -> None: s = pd.Series([-10, 2, 3, 10]) - s.std() s.std(axis=0, ddof=1) s.std(skipna=True, numeric_only=False) diff --git a/tests/test_timefuncs.py b/tests/test_timefuncs.py index cf987df5d..c86d83521 100644 --- a/tests/test_timefuncs.py +++ b/tests/test_timefuncs.py @@ -1724,22 +1724,6 @@ def test_timedeltaseries_add_timestampseries() -> None: check(assert_type(plus, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp) -def test_mean_std() -> None: - s = pd.Series([pd.Timedelta("1 ns"), pd.Timedelta("2 ns"), pd.Timedelta("3 ns")]) - check(assert_type(s.mean(), pd.Timedelta), pd.Timedelta) - check(assert_type(s.std(), pd.Timedelta), pd.Timedelta) - - s2 = pd.Series( - [ - pd.Timestamp("2021-01-01"), - pd.Timestamp("2021-01-02"), - pd.Timestamp("2021-01-03"), - ] - ) - check(assert_type(s2.mean(), pd.Timestamp), pd.Timestamp) - check(assert_type(s2.std(), pd.Timedelta), pd.Timedelta) - - def test_timestamp_strptime_fails(): if TYPE_CHECKING_INVALID_USAGE: assert_never( diff --git a/ttest.py b/ttest.py deleted file mode 100644 index c19001886..000000000 --- a/ttest.py +++ /dev/null @@ -1,11 +0,0 @@ -from typing import reveal_type - -import pandas as pd - -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"])) -reveal_type(s2) -td = s1 - s2 -reveal_type(td) -ssum = s1 + s2 From f094cd75575d9f7e7b59438d0820c7ed91811443 Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Fri, 26 Sep 2025 19:57:20 +0200 Subject: [PATCH 13/13] fix: comments --- .pre-commit-config.yaml | 4 ++-- pandas-stubs/_typing.pyi | 8 -------- pandas-stubs/core/indexes/base.pyi | 1 - pandas-stubs/core/series.pyi | 10 +++++----- tests/indexes/arithmetic/bool/test_add.py | 1 - tests/series/test_agg.py | 8 +++----- tests/test_timefuncs.py | 8 ++++++-- 7 files changed, 16 insertions(+), 24 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6578e1709..a94f5c741 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,7 @@ minimum_pre_commit_version: 2.15.0 ci: autofix_prs: false repos: -- repo: https://github.com/python/black +- repo: https://github.com/psf/black rev: 25.9.0 hooks: - id: black @@ -11,7 +11,7 @@ repos: hooks: - id: isort - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.13.1 + rev: v0.13.2 hooks: - id: ruff-check args: [ diff --git a/pandas-stubs/_typing.pyi b/pandas-stubs/_typing.pyi index d75d7a3ef..95e184356 100644 --- a/pandas-stubs/_typing.pyi +++ b/pandas-stubs/_typing.pyi @@ -825,14 +825,6 @@ np_ndarray_td: TypeAlias = npt.NDArray[np.timedelta64] # Define shape and generic type variables with defaults similar to numpy GenericT = TypeVar("GenericT", bound=np.generic, default=Any) -TD64ItemT = TypeVar( - "TD64ItemT", - bound=datetime.timedelta | int | None, - default=datetime.timedelta | int | None, -) -DT64ItemT = TypeVar( - "DT64ItemT", bound=datetime.date | int | None, default=datetime.date | int | None -) GenericT_co = TypeVar("GenericT_co", bound=np.generic, default=Any, covariant=True) ShapeT = TypeVar("ShapeT", bound=tuple[int, ...], default=tuple[Any, ...]) # Numpy ndarray with more ergonomic typevar diff --git a/pandas-stubs/core/indexes/base.pyi b/pandas-stubs/core/indexes/base.pyi index 926785756..034b04cc5 100644 --- a/pandas-stubs/core/indexes/base.pyi +++ b/pandas-stubs/core/indexes/base.pyi @@ -477,7 +477,6 @@ class Index(IndexOpsMixin[S1]): def __ge__(self, other: Self | S1) -> np_1darray[np.bool]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] def __lt__(self, other: Self | S1) -> np_1darray[np.bool]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] def __gt__(self, other: Self | S1) -> np_1darray[np.bool]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] - # overwrite inherited methods from OpsMixin @overload def __add__(self: Index[Never], other: _str) -> Never: ... @overload diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index 5a843b678..96509c4c6 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -4461,7 +4461,7 @@ class Series(IndexOpsMixin[S1], NDFrame): level: None = ..., numeric_only: _bool = False, **kwargs: Any, - ) -> Any: ... + ) -> float: ... @overload def mean( self: Series[Timestamp], @@ -4488,7 +4488,7 @@ class Series(IndexOpsMixin[S1], NDFrame): level: None = ..., numeric_only: _bool = False, **kwargs: Any, - ) -> Any: ... + ) -> float: ... @overload def median( self: Series[complex], @@ -4633,7 +4633,7 @@ class Series(IndexOpsMixin[S1], NDFrame): ddof: int = 1, numeric_only: _bool = False, **kwargs: Any, - ) -> Any: ... + ) -> float: ... @overload def std( self: Series[complex], @@ -4675,7 +4675,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload # type: ignore[override] def to_numpy( # pyrefly: ignore[bad-override] self: Series[Timestamp], - dtype: None = None, + dtype: None | type[np.datetime64] = None, copy: bool = False, na_value: Scalar = ..., **kwargs, @@ -4691,7 +4691,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def to_numpy( # pyrefly: ignore[bad-override] self: Series[Timedelta], - dtype: None = None, + dtype: None | type[np.timedelta64] = None, copy: bool = False, na_value: Scalar = ..., **kwargs, diff --git a/tests/indexes/arithmetic/bool/test_add.py b/tests/indexes/arithmetic/bool/test_add.py index 3255a6e7c..b80a25b1d 100644 --- a/tests/indexes/arithmetic/bool/test_add.py +++ b/tests/indexes/arithmetic/bool/test_add.py @@ -13,7 +13,6 @@ def test_add_py_scalar() -> None: """Test pd.Index[bool] + Python native scalars""" b, i, f, c = True, 1, 1.0, 1j - left.__add__(b) check(assert_type(left + b, "pd.Index[bool]"), pd.Index, np.bool_) check(assert_type(left + i, "pd.Index[int]"), pd.Index, np.integer) check(assert_type(left + f, "pd.Index[float]"), pd.Index, np.floating) diff --git a/tests/series/test_agg.py b/tests/series/test_agg.py index bfc1e2017..bd1d2ec21 100644 --- a/tests/series/test_agg.py +++ b/tests/series/test_agg.py @@ -1,5 +1,3 @@ -from typing import Any - import numpy as np import pandas as pd from typing_extensions import assert_type @@ -13,9 +11,9 @@ def test_agg_any_float() -> None: series = pd.DataFrame({"A": [1.0, float("nan"), 2.0]})["A"] - check(assert_type(series.mean(), Any), np.float64) - check(assert_type(series.median(), Any), np.float64) - check(assert_type(series.std(), Any), np.float64) + check(assert_type(series.mean(), float), np.float64) + check(assert_type(series.median(), float), np.float64) + check(assert_type(series.std(), float), np.float64) def test_agg_bool() -> None: diff --git a/tests/test_timefuncs.py b/tests/test_timefuncs.py index c86d83521..354be303b 100644 --- a/tests/test_timefuncs.py +++ b/tests/test_timefuncs.py @@ -1042,8 +1042,7 @@ def test_series_types_to_numpy() -> None: dtype=np.int64, ) check( - # mypy gives error: Expression is of type "ndarray[tuple[int], dtype[timedelta64[Any]]]", not "ndarray[tuple[int], dtype[timedelta64[timedelta | int | None]]]" [assert-type] - assert_type(td_s.to_numpy(dtype=np.timedelta64), np_1darray[np.timedelta64]), # type: ignore[assert-type] + assert_type(td_s.to_numpy(dtype=np.timedelta64), np_1darray[np.timedelta64]), np_1darray, dtype=np.timedelta64, ) @@ -1052,6 +1051,11 @@ def test_series_types_to_numpy() -> None: np_1darray, dtype=np.int64, ) + check( + assert_type(ts_s.to_numpy(dtype=np.datetime64), np_1darray[np.datetime64]), + np_1darray, + dtype=np.datetime64, + ) check( assert_type(p_s.to_numpy(dtype=np.int64), np_1darray[np.int64]), np_1darray,