From a0741239e5bfb60c9804830e767485d12e54073e Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Sun, 19 Oct 2025 22:49:04 +0200 Subject: [PATCH 1/9] floordiv --- pandas-stubs/core/base.pyi | 79 +++++- pandas-stubs/core/indexes/base.pyi | 127 +++++++-- pandas-stubs/core/indexes/datetimes.pyi | 27 +- pandas-stubs/core/indexes/timedeltas.pyi | 59 ++-- pandas-stubs/core/series.pyi | 259 +++++++++--------- .../indexes/arithmetic/float/test_truediv.py | 49 +++- tests/indexes/arithmetic/int/test_floordiv.py | 127 +++++++++ tests/indexes/arithmetic/int/test_truediv.py | 49 +++- .../timedeltaindex/test_floordiv.py | 141 ++++++++++ .../series/arithmetic/float/test_floordiv.py | 167 ++++++++--- tests/series/arithmetic/float/test_truediv.py | 132 ++++++++- tests/series/arithmetic/int/test_floordiv.py | 173 ++++++++---- tests/series/arithmetic/int/test_truediv.py | 28 ++ .../arithmetic/timedelta/test_floordiv.py | 88 +++--- tests/test_natype.py | 17 +- 15 files changed, 1180 insertions(+), 342 deletions(-) create mode 100644 tests/indexes/arithmetic/int/test_floordiv.py create mode 100644 tests/indexes/arithmetic/timedeltaindex/test_floordiv.py diff --git a/pandas-stubs/core/base.pyi b/pandas-stubs/core/base.pyi index ea3865add..55af19d4f 100644 --- a/pandas-stubs/core/base.pyi +++ b/pandas-stubs/core/base.pyi @@ -29,6 +29,7 @@ from pandas._libs.tslibs.timedeltas import Timedelta from pandas._typing import ( S1, S2, + S3, AxisIndex, DropKeep, DTypeLike, @@ -280,7 +281,7 @@ class ElementOpsMixin(Generic[S2]): ) -> ElementOpsMixin[complex]: ... @overload def _proto_truediv( - self: ElementOpsMixin[Timedelta], other: timedelta | Timedelta | np.timedelta64 + self: ElementOpsMixin[Timedelta], other: timedelta | np.timedelta64 | Timedelta ) -> ElementOpsMixin[float]: ... @overload def _proto_rtruediv( @@ -296,8 +297,56 @@ class ElementOpsMixin(Generic[S2]): ) -> ElementOpsMixin[complex]: ... @overload def _proto_rtruediv( - self: ElementOpsMixin[Timedelta], other: timedelta | Timedelta | np.timedelta64 + self: ElementOpsMixin[Timedelta], other: timedelta | np.timedelta64 | Timedelta ) -> ElementOpsMixin[float]: ... + @overload + def _proto_floordiv( + self: ElementOpsMixin[int], other: int | np.integer + ) -> ElementOpsMixin[int]: ... + @overload + def _proto_floordiv( + self: ElementOpsMixin[float], other: float | np.floating + ) -> ElementOpsMixin[float]: ... + @overload + def _proto_floordiv( + self: ElementOpsMixin[Timedelta], other: timedelta | np.timedelta64 | Timedelta + ) -> ElementOpsMixin[int]: ... + @overload + def _proto_rfloordiv( + self: ElementOpsMixin[int], other: int | np.integer + ) -> ElementOpsMixin[int]: ... + @overload + def _proto_rfloordiv( + self: ElementOpsMixin[float], other: float | np.floating + ) -> ElementOpsMixin[float]: ... + @overload + def _proto_rfloordiv( + self: ElementOpsMixin[Timedelta], other: timedelta | np.timedelta64 | Timedelta + ) -> ElementOpsMixin[int]: ... + @overload + def _proto_mod( + self: ElementOpsMixin[int], other: int | np.integer + ) -> ElementOpsMixin[int]: ... + @overload + def _proto_mod( + self: ElementOpsMixin[float], other: float | np.floating + ) -> ElementOpsMixin[float]: ... + @overload + def _proto_mod( + self: ElementOpsMixin[Timedelta], other: timedelta | np.timedelta64 | Timedelta + ) -> ElementOpsMixin[Timedelta]: ... + @overload + def _proto_rmod( + self: ElementOpsMixin[int], other: int | np.integer + ) -> ElementOpsMixin[int]: ... + @overload + def _proto_rmod( + self: ElementOpsMixin[float], other: float | np.floating + ) -> ElementOpsMixin[float]: ... + @overload + def _proto_rmod( + self: ElementOpsMixin[Timedelta], other: timedelta | np.timedelta64 | Timedelta + ) -> ElementOpsMixin[Timedelta]: ... @type_check_only class Supports_ProtoAdd(Protocol[_T_contra, S2]): @@ -322,3 +371,29 @@ class Supports_ProtoTrueDiv(Protocol[_T_contra, S2]): @type_check_only class Supports_ProtoRTrueDiv(Protocol[_T_contra, S2]): def _proto_rtruediv(self, other: _T_contra, /) -> ElementOpsMixin[S2]: ... + +@type_check_only +class Supports_ProtoFloorDiv(Protocol[_T_contra, S2]): + def _proto_floordiv(self, other: _T_contra, /) -> ElementOpsMixin[S2]: ... + +@type_check_only +class Supports_ProtoRFloorDiv(Protocol[_T_contra, S2]): + def _proto_rfloordiv(self, other: _T_contra, /) -> ElementOpsMixin[S2]: ... + +@type_check_only +class Supports_ProtoMod(Protocol[_T_contra, S2]): + def _proto_mod(self, other: _T_contra, /) -> ElementOpsMixin[S2]: ... + +@type_check_only +class Supports_ProtoRMod(Protocol[_T_contra, S2]): + def _proto_rmod(self, other: _T_contra, /) -> ElementOpsMixin[S2]: ... + +@type_check_only +class Supports_ProtoDivMod(Protocol[_T_contra, S2, S3]): + def _proto_floordiv(self, other: _T_contra, /) -> ElementOpsMixin[S2]: ... + def _proto_mod(self, other: _T_contra, /) -> ElementOpsMixin[S3]: ... + +@type_check_only +class Supports_ProtoRDivMod(Protocol[_T_contra, S2, S3]): + def _proto_rfloordiv(self, other: _T_contra, /) -> ElementOpsMixin[S2]: ... + def _proto_rmod(self, other: _T_contra, /) -> ElementOpsMixin[S3]: ... diff --git a/pandas-stubs/core/indexes/base.pyi b/pandas-stubs/core/indexes/base.pyi index 21aa39db3..0c9f4a445 100644 --- a/pandas-stubs/core/indexes/base.pyi +++ b/pandas-stubs/core/indexes/base.pyi @@ -29,37 +29,38 @@ from _typeshed import ( _T_contra, ) import numpy as np -from pandas import ( - DataFrame, - DatetimeIndex, - Interval, - IntervalIndex, - MultiIndex, - Period, - PeriodDtype, - PeriodIndex, - Series, - TimedeltaIndex, -) from pandas.core.arrays.boolean import BooleanArray from pandas.core.base import ( ElementOpsMixin, IndexOpsMixin, Supports_ProtoAdd, + Supports_ProtoFloorDiv, Supports_ProtoMul, Supports_ProtoRAdd, + Supports_ProtoRFloorDiv, Supports_ProtoRMul, Supports_ProtoRTrueDiv, Supports_ProtoTrueDiv, ) +from pandas.core.frame import DataFrame from pandas.core.indexes.category import CategoricalIndex +from pandas.core.indexes.datetimes import DatetimeIndex +from pandas.core.indexes.interval import IntervalIndex +from pandas.core.indexes.multi import MultiIndex +from pandas.core.indexes.period import PeriodIndex +from pandas.core.indexes.timedeltas import TimedeltaIndex +from pandas.core.series import Series from pandas.core.strings.accessor import StringMethods from typing_extensions import ( Never, Self, ) -from pandas._libs.interval import _OrderableT +from pandas._libs.interval import ( + Interval, + _OrderableT, +) +from pandas._libs.tslibs.period import Period from pandas._libs.tslibs.timedeltas import Timedelta from pandas._typing import ( C2, @@ -97,6 +98,7 @@ from pandas._typing import ( TimedeltaDtypeArg, TimestampDtypeArg, np_1darray, + np_ndarray, np_ndarray_anyint, np_ndarray_bool, np_ndarray_complex, @@ -107,6 +109,8 @@ from pandas._typing import ( type_t, ) +from pandas.core.dtypes.dtypes import PeriodDtype + class InvalidIndexError(Exception): ... class Index(IndexOpsMixin[S1], ElementOpsMixin[S1]): @@ -942,14 +946,17 @@ class Index(IndexOpsMixin[S1], ElementOpsMixin[S1]): @overload def __truediv__(self: Index[bool], other: np_ndarray_bool) -> Never: ... @overload + def __truediv__(self, other: np_ndarray_dt) -> Never: ... + @overload + def __truediv__(self: Index[T_COMPLEX], other: np_ndarray_td) -> Never: ... + @overload def __truediv__( self: Supports_ProtoTrueDiv[_T_contra, S2], other: _T_contra | Sequence[_T_contra], ) -> Index[S2]: ... @overload def __truediv__( - self: Index[int], - other: np_ndarray_bool | Index[bool], + self: Index[int], other: np_ndarray_bool | Index[bool] ) -> Index[float]: ... @overload def __truediv__( @@ -993,10 +1000,12 @@ class Index(IndexOpsMixin[S1], ElementOpsMixin[S1]): self: Index[Never], other: complex | ArrayLike | SequenceNotStr[S1] | Index ) -> Index: ... @overload - def __rtruediv__(self, other: Index[Never]) -> Index: ... + def __rtruediv__(self, other: Index[Never]) -> Index: ... # type: ignore[overload-overlap] @overload def __rtruediv__(self: Index[bool], other: np_ndarray_bool) -> Never: ... @overload + def __rtruediv__(self, other: np_ndarray_dt) -> Never: ... + @overload def __rtruediv__( self: Supports_ProtoRTrueDiv[_T_contra, S2], other: _T_contra | Sequence[_T_contra], @@ -1041,13 +1050,91 @@ class Index(IndexOpsMixin[S1], ElementOpsMixin[S1]): ), ) -> Index[complex]: ... @overload + def __rtruediv__( + self: Index[int] | Index[float], + other: timedelta | np.timedelta64 | np_ndarray_td | TimedeltaIndex, + ) -> TimedeltaIndex: ... + @overload def __rtruediv__(self, other: Path) -> Index: ... + @overload + def __floordiv__(self, other: Index[Never]) -> Index: ... + @overload def __floordiv__( - self, other: float | Sequence[float] | Index[int] | Index[float] - ) -> Self: ... + self: Index[int] | Index[float], + other: np_ndarray_complex | np_ndarray_dt | np_ndarray_td, + ) -> Never: ... + @overload + def __floordiv__( + self: Index[bool] | Index[complex], other: np_ndarray + ) -> Never: ... + @overload + def __floordiv__( + self: Supports_ProtoFloorDiv[_T_contra, S2], + other: _T_contra | Sequence[_T_contra], + ) -> Index[S2]: ... + @overload + def __floordiv__( + self: Index[int], other: np_ndarray_bool | Index[bool] + ) -> Index[int]: ... + @overload + def __floordiv__( + self: Index[float], other: np_ndarray_bool | Index[bool] + ) -> Index[float]: ... + @overload + def __floordiv__( + self: Index[bool] | Index[int], other: np_ndarray_anyint | Index[int] + ) -> Index[int]: ... + @overload + def __floordiv__( + self: Index[float], other: np_ndarray_anyint | Index[int] + ) -> Index[float]: ... + @overload + def __floordiv__( + self: Index[int] | Index[float], + other: float | Sequence[float] | np_ndarray_float | Index[float], + ) -> Index[float]: ... + @overload + def __rfloordiv__(self, other: Index[Never]) -> Index: ... # type: ignore[overload-overlap] + @overload def __rfloordiv__( - self, other: float | Sequence[float] | Index[int] | Index[float] - ) -> Self: ... + self: Index[int] | Index[float], + other: np_ndarray_complex | np_ndarray_dt | np_ndarray_td, + ) -> Never: ... + @overload + def __rfloordiv__( + self: Index[bool] | Index[complex], other: np_ndarray + ) -> Never: ... + @overload + def __rfloordiv__( + self: Supports_ProtoRFloorDiv[_T_contra, S2], + other: _T_contra | Sequence[_T_contra], + ) -> Index[S2]: ... + @overload + def __rfloordiv__( + self: Index[int], other: np_ndarray_bool | Index[bool] + ) -> Index[int]: ... + @overload + def __rfloordiv__( + self: Index[float], other: np_ndarray_bool | Index[bool] + ) -> Index[float]: ... + @overload + def __rfloordiv__( + self: Index[bool] | Index[int], other: np_ndarray_anyint | Index[int] + ) -> Index[int]: ... + @overload + def __rfloordiv__( + self: Index[float], other: np_ndarray_anyint | Index[int] + ) -> Index[float]: ... + @overload + def __rfloordiv__( + self: Index[int] | Index[float], + other: float | Sequence[float] | np_ndarray_float | Index[float], + ) -> Index[float]: ... + @overload + def __rfloordiv__( + self: Index[int] | Index[float], + other: timedelta | np_ndarray_td | TimedeltaIndex, + ) -> TimedeltaIndex: ... def infer_objects(self, copy: bool = True) -> Self: ... @type_check_only diff --git a/pandas-stubs/core/indexes/datetimes.pyi b/pandas-stubs/core/indexes/datetimes.pyi index 58166f29f..0ecf7a9a0 100644 --- a/pandas-stubs/core/indexes/datetimes.pyi +++ b/pandas-stubs/core/indexes/datetimes.pyi @@ -14,17 +14,18 @@ from typing import ( ) import numpy as np -from pandas import ( - DataFrame, - Index, - TimedeltaIndex, - Timestamp, -) +from pandas.core.frame import DataFrame from pandas.core.indexes.accessors import DatetimeIndexProperties +from pandas.core.indexes.base import Index from pandas.core.indexes.datetimelike import DatetimeTimedeltaMixin +from pandas.core.indexes.timedeltas import TimedeltaIndex from pandas.core.series import Series -from typing_extensions import Self +from typing_extensions import ( + Never, + Self, +) +from pandas._libs.tslibs.timestamps import Timestamp from pandas._typing import ( AxesData, DateAndDatetimeLike, @@ -34,6 +35,7 @@ from pandas._typing import ( TimeUnit, TimeZones, np_1darray, + np_ndarray, np_ndarray_dt, np_ndarray_td, ) @@ -63,18 +65,23 @@ class DatetimeIndex( def __add__( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] self, other: timedelta | BaseOffset ) -> Self: ... - def __radd__( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + def __radd__( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] self, other: timedelta | BaseOffset ) -> Self: ... @overload # type: ignore[override] - # pyrefly: ignore # bad-override - def __sub__( + def __sub__( # pyrefly: ignore[bad-override] self, other: datetime | np.datetime64 | np_ndarray_dt | Self ) -> TimedeltaIndex: ... @overload def __sub__( # pyright: ignore[reportIncompatibleMethodOverride] self, other: timedelta | np.timedelta64 | np_ndarray_td | BaseOffset ) -> Self: ... + def __truediv__( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] # pyrefly: ignore[bad-override] + self, other: np_ndarray + ) -> Never: ... + def __rtruediv__( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] # pyrefly: ignore[bad-override] + self, other: np_ndarray + ) -> Never: ... @final def to_series( self, index: Index | None = None, name: Hashable | None = None diff --git a/pandas-stubs/core/indexes/timedeltas.pyi b/pandas-stubs/core/indexes/timedeltas.pyi index dd1a8b189..1eec0d158 100644 --- a/pandas-stubs/core/indexes/timedeltas.pyi +++ b/pandas-stubs/core/indexes/timedeltas.pyi @@ -2,7 +2,10 @@ from collections.abc import ( Hashable, Sequence, ) -import datetime as dt +from datetime import ( + datetime, + timedelta, +) from typing import ( Literal, TypeAlias, @@ -36,7 +39,6 @@ from pandas._typing import ( np_ndarray_dt, np_ndarray_float, np_ndarray_td, - num, ) _NUM_FACTOR: TypeAlias = Just[int] | Just[float] | np.integer | np.floating @@ -48,7 +50,7 @@ _NUM_FACTOR_SEQ: TypeAlias = ( | Index[int] | Index[float] ) -_DT_FACTOR: TypeAlias = dt.timedelta | np.timedelta64 | Timedelta +_DT_FACTOR: TypeAlias = timedelta | np.timedelta64 | Timedelta _DT_FACTOR_SEQ: TypeAlias = _DT_FACTOR | Sequence[_DT_FACTOR] | np_ndarray_td class TimedeltaIndex( @@ -56,9 +58,7 @@ class TimedeltaIndex( ): def __new__( cls, - data: ( - Sequence[dt.timedelta | Timedelta | np.timedelta64 | float] | AxesData - ) = ..., + data: Sequence[timedelta | Timedelta | np.timedelta64 | float] | AxesData = ..., freq: Frequency = ..., closed: object = ..., dtype: Literal[" PeriodIndex: ... @overload - def __add__(self, other: dt.datetime | DatetimeIndex) -> DatetimeIndex: ... + def __add__(self, other: datetime | DatetimeIndex) -> DatetimeIndex: ... @overload def __add__( # pyright: ignore[reportIncompatibleMethodOverride] - self, other: dt.timedelta | Self + self, other: timedelta | Self ) -> Self: ... @overload # type: ignore[override] # pyrefly: ignore # bad-override def __radd__(self, other: Period) -> PeriodIndex: ... @overload - def __radd__(self, other: dt.datetime | DatetimeIndex) -> DatetimeIndex: ... + def __radd__(self, other: datetime | DatetimeIndex) -> DatetimeIndex: ... @overload def __radd__( # pyright: ignore[reportIncompatibleMethodOverride] - self, other: dt.timedelta | Self + self, other: timedelta | Self ) -> Self: ... def __sub__( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] - self, other: dt.timedelta | np.timedelta64 | np_ndarray_td | BaseOffset | Self + self, other: timedelta | np.timedelta64 | np_ndarray_td | BaseOffset | Self ) -> Self: ... @overload # type: ignore[override] # pyrefly: ignore # bad-override def __rsub__( - self, other: dt.timedelta | np.timedelta64 | np_ndarray_td | BaseOffset | Self + self, other: timedelta | np.timedelta64 | np_ndarray_td | BaseOffset | Self ) -> Self: ... @overload def __rsub__( # pyright: ignore[reportIncompatibleMethodOverride] - self, other: dt.datetime | np.datetime64 | np_ndarray_dt | DatetimeIndex + self, other: datetime | np.datetime64 | np_ndarray_dt | DatetimeIndex ) -> DatetimeIndex: ... @overload # type: ignore[override] def __mul__(self, other: np_ndarray_bool | np_ndarray_complex) -> Never: ... @@ -124,13 +124,30 @@ class TimedeltaIndex( self, other: _DT_FACTOR_SEQ | Self ) -> Index[float]: ... @overload # type: ignore[override] - # pyrefly: ignore # bad-override - def __floordiv__(self, other: num | Sequence[float]) -> Self: ... + def __floordiv__( # pyrefly: ignore [bad-override] + self, other: np_ndarray_bool | np_ndarray_complex | np_ndarray_dt + ) -> Never: ... + @overload + def __floordiv__(self, other: _NUM_FACTOR_SEQ) -> Self: ... @overload def __floordiv__( # pyright: ignore[reportIncompatibleMethodOverride] - self, other: dt.timedelta | Sequence[dt.timedelta] + self, other: _DT_FACTOR_SEQ | Self + ) -> Index[int]: ... + @overload # type: ignore[override] + def __rfloordiv__( # pyrefly: ignore[bad-override] + self, + other: ( + np_ndarray_bool + | np_ndarray_anyint + | np_ndarray_float + | np_ndarray_complex + | np_ndarray_dt + ), + ) -> Never: ... + @overload + def __rfloordiv__( # pyright: ignore[reportIncompatibleMethodOverride] + self, other: _DT_FACTOR_SEQ | Self ) -> Index[int]: ... - def __rfloordiv__(self, other: dt.timedelta | Sequence[dt.timedelta]) -> Index[int]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] @property def inferred_type(self) -> str: ... @final @@ -138,7 +155,7 @@ class TimedeltaIndex( self, index: Index | None = None, name: Hashable | None = None ) -> Series[Timedelta]: ... def shift( - self, periods: int = 1, freq: Frequency | dt.timedelta | None = None + self, periods: int = 1, freq: Frequency | timedelta | None = None ) -> Self: ... @overload @@ -146,7 +163,7 @@ def timedelta_range( start: TimedeltaConvertibleTypes, end: TimedeltaConvertibleTypes, *, - freq: Frequency | Timedelta | dt.timedelta | None = None, + freq: Frequency | Timedelta | timedelta | None = None, name: Hashable | None = None, closed: Literal["left", "right"] | None = None, unit: None | str = ..., @@ -156,7 +173,7 @@ def timedelta_range( *, end: TimedeltaConvertibleTypes, periods: int, - freq: Frequency | Timedelta | dt.timedelta | None = None, + freq: Frequency | Timedelta | timedelta | None = None, name: Hashable | None = None, closed: Literal["left", "right"] | None = None, unit: None | str = ..., @@ -166,7 +183,7 @@ def timedelta_range( start: TimedeltaConvertibleTypes, *, periods: int, - freq: Frequency | Timedelta | dt.timedelta | None = None, + freq: Frequency | Timedelta | timedelta | None = None, name: Hashable | None = None, closed: Literal["left", "right"] | None = None, unit: None | str = ..., diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index c05af4813..29b345631 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -69,8 +69,10 @@ from pandas.core.base import ( IndexOpsMixin, NumListLike, Supports_ProtoAdd, + Supports_ProtoFloorDiv, Supports_ProtoMul, Supports_ProtoRAdd, + Supports_ProtoRFloorDiv, Supports_ProtoRMul, Supports_ProtoRTrueDiv, Supports_ProtoTrueDiv, @@ -2153,7 +2155,7 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): @overload def __floordiv__( self: Series[int] | Series[float], - other: np_ndarray_bool | np_ndarray_complex | np_ndarray_dt | np_ndarray_td, + other: np_ndarray_complex | np_ndarray_dt | np_ndarray_td, ) -> Never: ... @overload def __floordiv__( @@ -2161,40 +2163,31 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): ) -> Never: ... @overload def __floordiv__( - self: Series[int], - other: ( - Just[int] - | Sequence[Just[int]] - | np_ndarray_anyint - | Index[int] - | Series[int] - ), + self: Supports_ProtoFloorDiv[_T_contra, S2], + other: _T_contra | Sequence[_T_contra], + ) -> Series[S2]: ... + @overload + def __floordiv__( + self: Series[int], other: np_ndarray_bool | Index[bool] | Series[bool] ) -> Series[int]: ... @overload def __floordiv__( - self: Series[int], - other: ( - Just[float] - | Sequence[Just[float]] - | np_ndarray_float - | Index[float] - | Series[float] - ), + self: Series[float], other: np_ndarray_bool | Index[bool] | Series[bool] ) -> Series[float]: ... @overload def __floordiv__( - self: Series[float], + self: Series[bool] | Series[int], + other: np_ndarray_anyint | Index[int] | Series[int], + ) -> Series[int]: ... + @overload + def __floordiv__( + self: Series[float], other: np_ndarray_anyint | Index[int] | Series[int] + ) -> Series[float]: ... + @overload + def __floordiv__( + self: 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] + float | Sequence[float] | np_ndarray_float | Index[float] | Series[float] ), ) -> Series[float]: ... @overload @@ -2208,8 +2201,7 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): other: ( Just[int] | Just[float] - | Sequence[Just[int]] - | Sequence[Just[float]] + | Sequence[Just[int] | Just[float]] | np_ndarray_anyint | np_ndarray_float | Index[int] @@ -2221,14 +2213,7 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): @overload def __floordiv__( self: Series[Timedelta], - other: ( - timedelta - | Sequence[timedelta] - | np.timedelta64 - | np_ndarray_td - | TimedeltaIndex - | Series[Timedelta] - ), + other: np_ndarray_td | TimedeltaIndex | Series[Timedelta], ) -> Series[int]: ... @overload def floordiv( @@ -2239,47 +2224,50 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): axis: AxisIndex | None = 0, ) -> Series: ... @overload + def floordiv( + self: Supports_ProtoFloorDiv[_T_contra, S2], + other: _T_contra | Sequence[_T_contra], + level: Level | None = ..., + fill_value: float | None = None, + axis: AxisIndex | None = 0, + ) -> Series[S2]: ... + @overload def floordiv( self: Series[int], - other: ( - Just[int] - | Sequence[Just[int]] - | np_ndarray_anyint - | Index[int] - | Series[int] - ), + other: np_ndarray_bool | Index[bool] | Series[bool], 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] - ), + self: Series[float], + other: np_ndarray_bool | Index[bool] | Series[bool], level: Level | None = ..., fill_value: float | None = None, axis: AxisIndex | None = 0, ) -> Series[float]: ... @overload + def floordiv( + self: Series[bool] | Series[int], + other: 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[float], + other: np_ndarray_anyint | Index[int] | Series[int], + level: Level | None = ..., + fill_value: float | None = None, + axis: AxisIndex | None = 0, + ) -> Series[float]: ... + @overload + def floordiv( + self: 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] + float | Sequence[float] | np_ndarray_float | Index[float] | Series[float] ), level: Level | None = ..., fill_value: float | None = None, @@ -2291,8 +2279,7 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): other: ( Just[int] | Just[float] - | Sequence[Just[int]] - | Sequence[Just[float]] + | Sequence[Just[int] | Just[float]] | np_ndarray_anyint | np_ndarray_float | Index[int] @@ -2307,14 +2294,7 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): @overload def floordiv( self: Series[Timedelta], - other: ( - timedelta - | Sequence[timedelta] - | np.timedelta64 - | np_ndarray_td - | TimedeltaIndex - | Series[Timedelta] - ), + other: np_ndarray_td | TimedeltaIndex | Series[Timedelta], level: Level | None = ..., fill_value: float | None = None, axis: AxisIndex | None = 0, @@ -2324,7 +2304,7 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): @overload def __rfloordiv__( self: Series[int] | Series[float], - other: np_ndarray_bool | np_ndarray_complex | np_ndarray_dt | np_ndarray_td, + other: np_ndarray_complex | np_ndarray_dt | np_ndarray_td, ) -> Never: ... @overload def __rfloordiv__( @@ -2332,40 +2312,31 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): ) -> Never: ... @overload def __rfloordiv__( - self: Series[int], - other: ( - Just[int] - | Sequence[Just[int]] - | np_ndarray_anyint - | Index[int] - | Series[int] - ), + self: Supports_ProtoRFloorDiv[_T_contra, S2], + other: _T_contra | Sequence[_T_contra], + ) -> Series[S2]: ... + @overload + def __rfloordiv__( + self: Series[int], other: np_ndarray_bool | Index[bool] | Series[bool] ) -> Series[int]: ... @overload def __rfloordiv__( - self: Series[int], - other: ( - Just[float] - | Sequence[Just[float]] - | np_ndarray_float - | Index[float] - | Series[float] - ), + self: Series[float], other: np_ndarray_bool | Index[bool] | Series[bool] ) -> Series[float]: ... @overload def __rfloordiv__( - self: Series[float], + self: Series[bool] | Series[int], + other: np_ndarray_anyint | Index[int] | Series[int], + ) -> Series[int]: ... + @overload + def __rfloordiv__( + self: Series[float], other: np_ndarray_anyint | Index[int] | Series[int] + ) -> Series[float]: ... + @overload + def __rfloordiv__( + self: 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] + float | Sequence[float] | np_ndarray_float | Index[float] | Series[float] ), ) -> Series[float]: ... @overload @@ -2380,16 +2351,14 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): ), ) -> Never: ... @overload + def __rfloordiv__( + self: Series[int] | Series[float], + other: timedelta | np_ndarray_td | TimedeltaIndex | Series[Timedelta], + ) -> Series[Timedelta]: ... + @overload def __rfloordiv__( self: Series[Timedelta], - other: ( - timedelta - | Sequence[timedelta] - | np.timedelta64 - | np_ndarray_td - | TimedeltaIndex - | Series[Timedelta] - ), + other: np_ndarray_td | TimedeltaIndex | Series[Timedelta], ) -> Series[int]: ... @overload def rfloordiv( @@ -2400,47 +2369,50 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): axis: AxisIndex | None = 0, ) -> Series: ... @overload + def rfloordiv( + self: Supports_ProtoRFloorDiv[_T_contra, S2], + other: _T_contra | Sequence[_T_contra], + level: Level | None = ..., + fill_value: float | None = None, + axis: AxisIndex = ..., + ) -> Series[S2]: ... + @overload def rfloordiv( self: Series[int], - other: ( - Just[int] - | Sequence[Just[int]] - | np_ndarray_anyint - | Index[int] - | Series[int] - ), + other: np_ndarray_bool | Index[bool] | Series[bool], 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] - ), + self: Series[float], + other: np_ndarray_bool | Index[bool] | Series[bool], level: Level | None = ..., fill_value: float | None = None, axis: AxisIndex = ..., ) -> Series[float]: ... @overload + def rfloordiv( + self: Series[bool] | Series[int], + other: np_ndarray_anyint | Index[int] | Series[int], + level: Level | None = ..., + fill_value: float | None = None, + axis: AxisIndex = ..., + ) -> Series[int]: ... + @overload def rfloordiv( self: Series[float], + other: np_ndarray_anyint | Index[int] | Series[int], + level: Level | None = ..., + fill_value: float | None = None, + axis: AxisIndex = ..., + ) -> Series[float]: ... + @overload + def rfloordiv( + self: 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] + float | Sequence[float] | np_ndarray_float | Index[float] | Series[float] ), level: Level | None = ..., fill_value: float | None = None, @@ -2448,11 +2420,10 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): ) -> Series[float]: ... @overload def rfloordiv( - self: Series[Timedelta], + self: Series[int] | Series[float], other: ( timedelta | Sequence[timedelta] - | np.timedelta64 | np_ndarray_td | TimedeltaIndex | Series[Timedelta] @@ -2460,6 +2431,14 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): level: Level | None = ..., fill_value: float | None = None, axis: AxisIndex = ..., + ) -> Series[Timedelta]: ... + @overload + def rfloordiv( + self: Series[Timedelta], + other: np_ndarray_td | TimedeltaIndex | Series[Timedelta], + level: Level | None = ..., + fill_value: float | None = None, + axis: AxisIndex = ..., ) -> Series[int]: ... def __ge__( # type: ignore[override] self, other: S1 | ListLike | Series[S1] | datetime | timedelta | date @@ -3582,6 +3561,10 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): @overload def __truediv__(self: Series[bool], other: np_ndarray_bool) -> Never: ... @overload + def __truediv__(self, other: np_ndarray_dt) -> Never: ... + @overload + def __truediv__(self: Series[T_COMPLEX], other: np_ndarray_td) -> Never: ... + @overload def __truediv__( self: Series[Timedelta], other: np_ndarray_bool | np_ndarray_complex | np_ndarray_dt, @@ -3838,9 +3821,11 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): @overload def __rtruediv__(self: Series[bool], other: np_ndarray_bool) -> Never: ... @overload + def __rtruediv__(self, other: np_ndarray_dt) -> Never: ... + @overload def __rtruediv__( self: Series[Timedelta], - other: np_ndarray_bool | np_ndarray_complex | np_ndarray_dt, + other: np_ndarray_bool | np_ndarray_complex, ) -> Never: ... @overload def __rtruediv__( diff --git a/tests/indexes/arithmetic/float/test_truediv.py b/tests/indexes/arithmetic/float/test_truediv.py index 6e1cd074a..f26fe1070 100644 --- a/tests/indexes/arithmetic/float/test_truediv.py +++ b/tests/indexes/arithmetic/float/test_truediv.py @@ -1,8 +1,17 @@ +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 import pytest -from typing_extensions import assert_type +from typing_extensions import ( + Never, + assert_type, +) from tests import ( TYPE_CHECKING_INVALID_USAGE, @@ -20,31 +29,46 @@ def left() -> "pd.Index[float]": def test_truediv_py_scalar(left: "pd.Index[float]") -> None: """Test pd.Index[float] / Python native scalars""" b, i, f, c = True, 1, 1.0, 1j + s, d = datetime(2025, 10, 30), timedelta(seconds=1) check(assert_type(left / b, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(left / i, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(left / f, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(left / c, "pd.Index[complex]"), pd.Index, np.complexfloating) + if TYPE_CHECKING_INVALID_USAGE: + _04 = left / s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left / d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] check(assert_type(b / left, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(i / left, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(f / left, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(c / left, "pd.Index[complex]"), pd.Index, np.complexfloating) + if TYPE_CHECKING_INVALID_USAGE: + _14 = s / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d / left, pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) def test_truediv_py_sequence(left: "pd.Index[float]") -> None: """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] + s = [datetime(2025, 10, d) for d in (27, 28, 29)] + d = [timedelta(seconds=s) for s in (1, 2, 3)] check(assert_type(left / b, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(left / i, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(left / f, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(left / c, "pd.Index[complex]"), pd.Index, np.complexfloating) + if TYPE_CHECKING_INVALID_USAGE: + _04 = left / s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left / d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] check(assert_type(b / left, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(i / left, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(f / left, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(c / left, "pd.Index[complex]"), pd.Index, np.complexfloating) + if TYPE_CHECKING_INVALID_USAGE: + _14 = s / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _15 = d / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] def test_truediv_numpy_array(left: "pd.Index[float]") -> None: @@ -53,11 +77,16 @@ def test_truediv_numpy_array(left: "pd.Index[float]") -> None: 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) + s = np.array([np.datetime64(f"2025-10-{d:02d}") for d in (1, 2, 3)], np.datetime64) + d = np.array([np.timedelta64(s + 1, "s") for s in range(3)], np.timedelta64) check(assert_type(left / b, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(left / i, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(left / f, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(left / c, "pd.Index[complex]"), pd.Index, np.complexfloating) + if TYPE_CHECKING_INVALID_USAGE: + assert_type(left / s, Never) + assert_type(left / d, Never) # `numpy` typing gives the corresponding `ndarray`s in the static type # checking, where our `__rtruediv__` cannot override. At runtime, they return @@ -70,6 +99,13 @@ def test_truediv_numpy_array(left: "pd.Index[float]") -> None: pd.Index, np.complexfloating, ) + if TYPE_CHECKING_INVALID_USAGE: + assert_type(s / left, Any) + check( + assert_type(d / left, "npt.NDArray[np.float64]"), + pd.TimedeltaIndex, + pd.Timedelta, + ) def test_truediv_pd_scalar(left: "pd.Index[float]") -> None: @@ -80,9 +116,8 @@ def test_truediv_pd_scalar(left: "pd.Index[float]") -> None: _00 = left / s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] _01 = left / d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - if TYPE_CHECKING_INVALID_USAGE: _10 = s / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - _11 = d / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d / left, pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) def test_truediv_pd_index(left: "pd.Index[float]") -> None: @@ -91,13 +126,21 @@ def test_truediv_pd_index(left: "pd.Index[float]") -> None: i = pd.Index([2, 3, 5]) f = pd.Index([1.0, 2.0, 3.0]) c = pd.Index([1.1j, 2.2j, 4.1j]) + s = pd.Index([datetime(2025, 10, d) for d in (1, 2, 3)]) + d = pd.Index([timedelta(seconds=s + 1) for s in range(3)]) check(assert_type(left / b, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(left / i, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(left / f, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(left / c, "pd.Index[complex]"), pd.Index, np.complexfloating) + if TYPE_CHECKING_INVALID_USAGE: + _04 = left / s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left / d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] check(assert_type(b / left, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(i / left, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(f / left, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(c / left, "pd.Index[complex]"), pd.Index, np.complexfloating) + if TYPE_CHECKING_INVALID_USAGE: + _14 = s / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d / left, pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) diff --git a/tests/indexes/arithmetic/int/test_floordiv.py b/tests/indexes/arithmetic/int/test_floordiv.py new file mode 100644 index 000000000..fe3d2766b --- /dev/null +++ b/tests/indexes/arithmetic/int/test_floordiv.py @@ -0,0 +1,127 @@ +from datetime import ( + datetime, + timedelta, +) +from typing import Any + +import numpy as np +import pandas as pd +import pytest +from typing_extensions import ( + Never, + assert_type, +) + +from tests import ( + TYPE_CHECKING_INVALID_USAGE, + check, +) + + +@pytest.fixture +def left() -> "pd.Index[int]": + """Left operand""" + lo = pd.Index([1, 2, 3]) + return check(assert_type(lo, "pd.Index[int]"), pd.Index, np.integer) + + +def test_floordiv_py_scalar(left: "pd.Index[int]") -> None: + """Test pd.Index[int] // Python native scalars""" + b, i, f, c = True, 1, 1.0, 1j + s, d = datetime(2025, 9, 27), timedelta(seconds=1) + + check(assert_type(left // b, "pd.Index[int]"), pd.Index, np.integer) + check(assert_type(left // i, "pd.Index[int]"), pd.Index, np.integer) + check(assert_type(left // f, "pd.Index[float]"), pd.Index, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _03 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _04 = left // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left // d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + check(assert_type(b // left, "pd.Index[int]"), pd.Index, np.integer) + check(assert_type(i // left, "pd.Index[int]"), pd.Index, np.integer) + check(assert_type(f // left, "pd.Index[float]"), pd.Index, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _13 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _14 = s // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d // left, pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) + + +def test_floordiv_py_sequence(left: "pd.Index[int]") -> None: + """Test pd.Index[int] // Python native sequences""" + b, i, f, c = [True, True, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] + s = [datetime(2025, 10, 27 + d) for d in range(3)] + d = [timedelta(seconds=s) for s in range(3)] + + check(assert_type(left // b, "pd.Index[int]"), pd.Index, np.integer) + check(assert_type(left // i, "pd.Index[int]"), pd.Index, np.integer) + check(assert_type(left // f, "pd.Index[float]"), pd.Index, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _03 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _04 = left // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left // d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + check(assert_type(b // left, "pd.Index[int]"), pd.Index, np.integer) + check(assert_type(i // left, "pd.Index[int]"), pd.Index, np.integer) + check(assert_type(f // left, "pd.Index[float]"), pd.Index, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _13 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _14 = s // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _15 = d // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + +def test_floordiv_numpy_array(left: "pd.Index[int]") -> None: + """Test pd.Index[int] // numpy arrays""" + b = np.array([True, True, 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) + s = np.array( + [np.datetime64(f"2025-10-{d:02d}") for d in (23, 24, 25)], np.datetime64 + ) + d = np.array([np.timedelta64(s + 1, "s") for s in range(3)], np.timedelta64) + + check(assert_type(left // b, "pd.Index[int]"), pd.Index, np.integer) + check(assert_type(left // i, "pd.Index[int]"), pd.Index, np.integer) + check(assert_type(left // f, "pd.Index[float]"), pd.Index, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + assert_type(left // c, Never) + assert_type(left // s, Never) + assert_type(left // d, Never) + + # `numpy` typing gives the corresponding `ndarray`s in the static type + # checking, where our `__rfloordiv__` cannot override. At runtime, they lead to + # errors or pd.Index. + check(b // left, pd.Index, np.integer) + check(i // left, pd.Index, np.integer) + check(f // left, pd.Index, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + assert_type(c // left, Any) + assert_type(s // left, Any) + assert_type(d // left, "np.typing.NDArray[np.int64]") + + +def test_floordiv_pd_index(left: "pd.Index[int]") -> None: + """Test pd.Index[int] // pandas Indexes""" + b = pd.Index([True, True, 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]) + s = pd.Index([datetime(2025, 10, d) for d in (27, 28, 29)]) + d = pd.Index([timedelta(seconds=s + 1) for s in range(3)]) + + check(assert_type(left // b, "pd.Index[int]"), pd.Index, np.integer) + check(assert_type(left // i, "pd.Index[int]"), pd.Index, np.integer) + check(assert_type(left // f, "pd.Index[float]"), pd.Index, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _03 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _04 = left // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left // d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + check(assert_type(b // left, "pd.Index[int]"), pd.Index, np.integer) + check(assert_type(i // left, "pd.Index[int]"), pd.Index, np.integer) + check(assert_type(f // left, "pd.Index[float]"), pd.Index, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _13 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _14 = s // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d // left, pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) diff --git a/tests/indexes/arithmetic/int/test_truediv.py b/tests/indexes/arithmetic/int/test_truediv.py index 3b9c2d8a1..6df55ce33 100644 --- a/tests/indexes/arithmetic/int/test_truediv.py +++ b/tests/indexes/arithmetic/int/test_truediv.py @@ -1,8 +1,17 @@ +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 import pytest -from typing_extensions import assert_type +from typing_extensions import ( + Never, + assert_type, +) from tests import ( TYPE_CHECKING_INVALID_USAGE, @@ -20,31 +29,46 @@ def left() -> "pd.Index[int]": def test_truediv_py_scalar(left: "pd.Index[int]") -> None: """Test pd.Index[int] / Python native scalars""" b, i, f, c = True, 1, 1.0, 1j + s, d = datetime(2025, 10, 30), timedelta(seconds=1) check(assert_type(left / b, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(left / i, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(left / f, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(left / c, "pd.Index[complex]"), pd.Index, np.complexfloating) + if TYPE_CHECKING_INVALID_USAGE: + _04 = left / s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left / d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] check(assert_type(b / left, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(i / left, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(f / left, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(c / left, "pd.Index[complex]"), pd.Index, np.complexfloating) + if TYPE_CHECKING_INVALID_USAGE: + _14 = s / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d / left, pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) def test_truediv_py_sequence(left: "pd.Index[int]") -> None: """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] + s = [datetime(2025, 10, d) for d in (27, 28, 29)] + d = [timedelta(seconds=s) for s in (1, 2, 3)] check(assert_type(left / b, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(left / i, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(left / f, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(left / c, "pd.Index[complex]"), pd.Index, np.complexfloating) + if TYPE_CHECKING_INVALID_USAGE: + _04 = left / s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left / d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] check(assert_type(b / left, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(i / left, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(f / left, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(c / left, "pd.Index[complex]"), pd.Index, np.complexfloating) + if TYPE_CHECKING_INVALID_USAGE: + _14 = s / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _15 = d / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] def test_truediv_numpy_array(left: "pd.Index[int]") -> None: @@ -53,11 +77,16 @@ def test_truediv_numpy_array(left: "pd.Index[int]") -> None: 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) + s = np.array([np.datetime64(f"2025-10-{d:02d}") for d in (1, 2, 3)], np.datetime64) + d = np.array([np.timedelta64(s + 1, "s") for s in range(3)], np.timedelta64) check(assert_type(left / b, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(left / i, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(left / f, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(left / c, "pd.Index[complex]"), pd.Index, np.complexfloating) + if TYPE_CHECKING_INVALID_USAGE: + assert_type(left / s, Never) + assert_type(left / d, Never) # `numpy` typing gives the corresponding `ndarray`s in the static type # checking, where our `__rtruediv__` cannot override. At runtime, they return @@ -70,6 +99,13 @@ def test_truediv_numpy_array(left: "pd.Index[int]") -> None: pd.Index, np.complexfloating, ) + if TYPE_CHECKING_INVALID_USAGE: + assert_type(s / left, Any) + check( + assert_type(d / left, "npt.NDArray[np.float64]"), + pd.TimedeltaIndex, + pd.Timedelta, + ) def test_truediv_pd_scalar(left: "pd.Index[int]") -> None: @@ -80,9 +116,8 @@ def test_truediv_pd_scalar(left: "pd.Index[int]") -> None: _00 = left / s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] _01 = left / d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - if TYPE_CHECKING_INVALID_USAGE: _10 = s / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - _11 = d / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d / left, pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) def test_truediv_pd_index(left: "pd.Index[int]") -> None: @@ -91,13 +126,21 @@ def test_truediv_pd_index(left: "pd.Index[int]") -> None: i = pd.Index([2, 3, 5]) f = pd.Index([1.0, 2.0, 3.0]) c = pd.Index([1.1j, 2.2j, 4.1j]) + s = pd.Index([datetime(2025, 10, d) for d in (1, 2, 3)]) + d = pd.Index([timedelta(seconds=s + 1) for s in range(3)]) check(assert_type(left / b, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(left / i, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(left / f, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(left / c, "pd.Index[complex]"), pd.Index, np.complexfloating) + if TYPE_CHECKING_INVALID_USAGE: + _04 = left / s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left / d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] check(assert_type(b / left, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(i / left, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(f / left, "pd.Index[float]"), pd.Index, np.floating) check(assert_type(c / left, "pd.Index[complex]"), pd.Index, np.complexfloating) + if TYPE_CHECKING_INVALID_USAGE: + _14 = s / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d / left, pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) diff --git a/tests/indexes/arithmetic/timedeltaindex/test_floordiv.py b/tests/indexes/arithmetic/timedeltaindex/test_floordiv.py new file mode 100644 index 000000000..ab2e7cb8e --- /dev/null +++ b/tests/indexes/arithmetic/timedeltaindex/test_floordiv.py @@ -0,0 +1,141 @@ +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 +import pytest +from typing_extensions import ( + Never, + assert_type, +) + +from tests import ( + TYPE_CHECKING_INVALID_USAGE, + check, +) + + +@pytest.fixture +def left() -> pd.TimedeltaIndex: + """Left operand""" + lo = pd.Index([pd.Timedelta(1, "s")]) + return check(assert_type(lo, pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) + + +def test_floordiv_py_scalar(left: pd.TimedeltaIndex) -> None: + """Test pd.TimedeltaIndex // 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: + _00 = left // b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left // i, pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) + check(assert_type(left // f, pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + _03 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _04 = left // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left // d, "pd.Index[int]"), pd.Index, np.integer) + + if TYPE_CHECKING_INVALID_USAGE: + _10 = b // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _11 = i // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _12 = f // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _13 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _14 = s // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d // left, "pd.Index[int]"), pd.Index, np.integer) + + +def test_floordiv_py_sequence(left: pd.TimedeltaIndex) -> None: + """Test pd.TimedeltaIndex // 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: + _00 = left // b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left // i, pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) + check(assert_type(left // f, pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + _03 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _04 = left // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left // d, "pd.Index[int]"), pd.Index, int) + + if TYPE_CHECKING_INVALID_USAGE: + _10 = b // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _11 = i // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _12 = f // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _13 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _14 = s // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d // left, "pd.Index[int]"), pd.Index, np.integer) + + +def test_floordiv_numpy_array(left: pd.TimedeltaIndex) -> None: + """Test pd.TimedeltaIndex // 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.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) + check(assert_type(left // f, pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + assert_type(left // c, Never) + assert_type(left // s, Never) + check(assert_type(left // d, "pd.Index[int]"), pd.Index, np.integer) + + # `numpy` typing gives the corresponding `ndarray`s in the static type + # 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]") + 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.Index, np.integer) + + +def test_floordiv_pd_scalar(left: pd.TimedeltaIndex) -> None: + """Test pd.TimedeltaIndex // pandas scalars""" + s, d = pd.Timestamp(2025, 9, 24), pd.Timedelta(seconds=1) + + if TYPE_CHECKING_INVALID_USAGE: + _00 = left // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left // d, "pd.Index[int]"), pd.Index, np.integer) + + if TYPE_CHECKING_INVALID_USAGE: + _10 = s // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d // left, "pd.Index[int]"), pd.Index, np.integer) + + +def test_floordiv_pd_index(left: pd.TimedeltaIndex) -> None: + """Test pd.TimedeltaIndex // 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: + _00 = left // b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left // i, pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) + check(assert_type(left // f, pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) + if TYPE_CHECKING_INVALID_USAGE: + _03 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _04 = left // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left // d, "pd.Index[int]"), pd.Index, np.integer) + + if TYPE_CHECKING_INVALID_USAGE: + _10 = b // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _11 = i // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _12 = f // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _13 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _14 = s // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d // left, "pd.Index[int]"), pd.Index, np.integer) diff --git a/tests/series/arithmetic/float/test_floordiv.py b/tests/series/arithmetic/float/test_floordiv.py index 2eedc4ef3..72a803da2 100644 --- a/tests/series/arithmetic/float/test_floordiv.py +++ b/tests/series/arithmetic/float/test_floordiv.py @@ -1,8 +1,12 @@ +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 +import pytest from typing_extensions import ( Never, assert_type, @@ -13,166 +17,239 @@ check, ) -left = pd.Series([1.2, 2.4, 3.6]) # left operand + +@pytest.fixture +def left() -> "pd.Series[float]": + """Left operand""" + lo = pd.Series([1.2, 2.4, 3.6]) + return check(assert_type(lo, "pd.Series[float]"), pd.Series, np.floating) -def test_floordiv_py_scalar() -> None: +def test_floordiv_py_scalar(left: "pd.Series[float]") -> None: """Test pd.Series[float] // Python native scalars""" b, i, f, c = True, 1, 1.0, 1j + s, d = datetime(2025, 9, 27), timedelta(seconds=1) - if TYPE_CHECKING_INVALID_USAGE: - _0 = left // b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + 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) if TYPE_CHECKING_INVALID_USAGE: - _1 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _03 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _04 = left // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left // d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - _2 = b // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + 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) if TYPE_CHECKING_INVALID_USAGE: - _3 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _13 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _14 = s // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d // left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) - left.floordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.floordiv(b), "pd.Series[float]"), pd.Series, np.floating) 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.floordiv(c) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + left.floordiv(s) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + left.floordiv(d) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] - left.rfloordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rfloordiv(b), "pd.Series[float]"), pd.Series, np.floating) 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] + 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[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) -def test_floordiv_py_sequence() -> None: +def test_floordiv_py_sequence(left: "pd.Series[float]") -> 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] + s = [datetime(2025, 10, 27 + d) for d in range(3)] + d = [timedelta(seconds=s) for s in range(3)] - if TYPE_CHECKING_INVALID_USAGE: - _0 = left // b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + 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) if TYPE_CHECKING_INVALID_USAGE: - _1 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _03 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _04 = left // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left // d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - _2 = b // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + 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) if TYPE_CHECKING_INVALID_USAGE: - _3 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _13 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _14 = s // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _15 = d // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - left.floordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.floordiv(b), "pd.Series[float]"), pd.Series, np.floating) 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.floordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.floordiv(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] - left.rfloordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rfloordiv(b), "pd.Series[float]"), pd.Series, np.floating) 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] + left.rfloordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left.rfloordiv(d), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) -def test_floordiv_numpy_array() -> None: +def test_floordiv_numpy_array(left: "pd.Series[float]") -> 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) + s = np.array( + [np.datetime64(f"2025-10-{d:02d}") for d in (23, 24, 25)], np.datetime64 + ) + d = np.array([np.timedelta64(s + 1, "s") for s in range(3)], np.timedelta64) - if TYPE_CHECKING_INVALID_USAGE: - assert_type(left // b, Never) + 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) if TYPE_CHECKING_INVALID_USAGE: assert_type(left // c, Never) + assert_type(left // s, Never) + assert_type(left // d, Never) - # `numpy` typing gives the corresponding `ndarray`s in the static type - # checking, where our `__rfloordiv__` cannot override. At runtime, they lead to - # errors or pd.Series. - assert_type(b // left, "npt.NDArray[np.int8]") + # `numpy` typing gives the corresponding `ndarray`s in the static type + # checking, where our `__rfloordiv__` cannot override. At runtime, they lead to + # errors or pd.Series. + check(b // left, pd.Series, np.floating) check(i // left, pd.Series, np.floating) check(f // left, pd.Series, np.floating) if TYPE_CHECKING_INVALID_USAGE: assert_type(c // left, Any) + assert_type(s // left, Any) + check( + assert_type(d // left, "np.typing.NDArray[np.int64]"), pd.Series, pd.Timedelta + ) - left.floordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.floordiv(b), "pd.Series[float]"), pd.Series, np.floating) 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.floordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.floordiv(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] - left.rfloordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rfloordiv(b), "pd.Series[float]"), pd.Series, np.floating) 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] + left.rfloordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left.rfloordiv(d), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) -def test_floordiv_pd_index() -> None: +def test_floordiv_pd_index(left: "pd.Series[float]") -> 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]) + s = pd.Index([datetime(2025, 10, d) for d in (27, 28, 29)]) + d = pd.Index([timedelta(seconds=s + 1) for s in range(3)]) - if TYPE_CHECKING_INVALID_USAGE: - _0 = left // b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + 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) if TYPE_CHECKING_INVALID_USAGE: - _1 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _03 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _04 = left // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left // d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - _2 = b // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + 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) if TYPE_CHECKING_INVALID_USAGE: - _3 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _13 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _14 = s // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d // left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) - left.floordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.floordiv(b), "pd.Series[float]"), pd.Series, np.floating) 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.floordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.floordiv(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] - left.rfloordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rfloordiv(b), "pd.Series[float]"), pd.Series, np.floating) 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] + left.rfloordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left.rfloordiv(d), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) -def test_floordiv_pd_series() -> None: +def test_floordiv_pd_series(left: "pd.Series[float]") -> 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]) + s = pd.Series([datetime(2025, 10, d) for d in (27, 28, 29)]) + d = pd.Series([timedelta(seconds=s + 1) for s in range(3)]) - if TYPE_CHECKING_INVALID_USAGE: - _0 = left // b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + 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) if TYPE_CHECKING_INVALID_USAGE: - _1 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _03 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _04 = left // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left // d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - _2 = b // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + 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) if TYPE_CHECKING_INVALID_USAGE: - _3 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _13 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _14 = s // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d // left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) - left.floordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.floordiv(b), "pd.Series[float]"), pd.Series, np.floating) 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.floordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.floordiv(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] - left.rfloordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rfloordiv(b), "pd.Series[float]"), pd.Series, np.floating) 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] + left.rfloordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left.rfloordiv(d), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) diff --git a/tests/series/arithmetic/float/test_truediv.py b/tests/series/arithmetic/float/test_truediv.py index 83c3da2f5..18d38e661 100644 --- a/tests/series/arithmetic/float/test_truediv.py +++ b/tests/series/arithmetic/float/test_truediv.py @@ -1,8 +1,17 @@ +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 import pytest -from typing_extensions import assert_type +from typing_extensions import ( + Never, + assert_type, +) from tests import ( TYPE_CHECKING_INVALID_USAGE, @@ -20,16 +29,23 @@ def left() -> "pd.Series[float]": def test_truediv_py_scalar(left: "pd.Series[float]") -> None: """Test pd.Series[float] / Python native scalars""" b, i, f, c = True, 1, 1.0, 1j + s, d = datetime(2025, 9, 27), timedelta(seconds=1) 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) + if TYPE_CHECKING_INVALID_USAGE: + _04 = left / s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left / d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] 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) + if TYPE_CHECKING_INVALID_USAGE: + _14 = s / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d / left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) 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) @@ -39,11 +55,17 @@ def test_truediv_py_scalar(left: "pd.Series[float]") -> None: pd.Series, np.complexfloating, ) + if TYPE_CHECKING_INVALID_USAGE: + left.truediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.truediv(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] 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) + if TYPE_CHECKING_INVALID_USAGE: + left.div(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.div(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] 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) @@ -53,6 +75,13 @@ def test_truediv_py_scalar(left: "pd.Series[float]") -> None: pd.Series, np.complexfloating, ) + if TYPE_CHECKING_INVALID_USAGE: + left.rtruediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left.rtruediv(d), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) 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) @@ -60,21 +89,32 @@ def test_truediv_py_scalar(left: "pd.Series[float]") -> None: check( assert_type(left.rdiv(c), "pd.Series[complex]"), pd.Series, np.complexfloating ) + if TYPE_CHECKING_INVALID_USAGE: + left.rdiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rdiv(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) def test_truediv_py_sequence(left: "pd.Series[float]") -> 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] + s = [datetime(2025, 10, 27 + d) for d in range(3)] + d = [timedelta(seconds=s) for s in range(3)] 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) + if TYPE_CHECKING_INVALID_USAGE: + _04 = left / s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left / d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] 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) + if TYPE_CHECKING_INVALID_USAGE: + _14 = s / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d / left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) 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) @@ -84,11 +124,17 @@ def test_truediv_py_sequence(left: "pd.Series[float]") -> None: pd.Series, np.complexfloating, ) + if TYPE_CHECKING_INVALID_USAGE: + left.truediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.truediv(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] 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) + if TYPE_CHECKING_INVALID_USAGE: + left.div(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.div(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] 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) @@ -98,6 +144,13 @@ def test_truediv_py_sequence(left: "pd.Series[float]") -> None: pd.Series, np.complexfloating, ) + if TYPE_CHECKING_INVALID_USAGE: + left.rtruediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left.rtruediv(d), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) 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) @@ -105,6 +158,9 @@ def test_truediv_py_sequence(left: "pd.Series[float]") -> None: check( assert_type(left.rdiv(c), "pd.Series[complex]"), pd.Series, np.complexfloating ) + if TYPE_CHECKING_INVALID_USAGE: + left.rdiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rdiv(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) def test_truediv_numpy_array(left: "pd.Series[float]") -> None: @@ -113,11 +169,18 @@ def test_truediv_numpy_array(left: "pd.Series[float]") -> None: 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) + s = np.array( + [np.datetime64(f"2025-10-{d:02d}") for d in (28, 29, 30)], np.datetime64 + ) + d = np.array([np.timedelta64(s + 1, "s") for s in range(3)], np.timedelta64) 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) + if TYPE_CHECKING_INVALID_USAGE: + assert_type(left / s, Never) + assert_type(left / d, Never) # `numpy` typing gives the corresponding `ndarray`s in the static type # checking, where our `__rtruediv__` cannot override. At runtime, they return @@ -130,6 +193,9 @@ def test_truediv_numpy_array(left: "pd.Series[float]") -> None: pd.Series, np.complexfloating, ) + if TYPE_CHECKING_INVALID_USAGE: + assert_type(s / left, Any) + check(assert_type(d / left, "npt.NDArray[np.float64]"), pd.Series, pd.Timedelta) 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) @@ -139,11 +205,17 @@ def test_truediv_numpy_array(left: "pd.Series[float]") -> None: pd.Series, np.complexfloating, ) + if TYPE_CHECKING_INVALID_USAGE: + left.truediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.truediv(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] 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) + if TYPE_CHECKING_INVALID_USAGE: + left.div(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.div(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] 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) @@ -153,6 +225,13 @@ def test_truediv_numpy_array(left: "pd.Series[float]") -> None: pd.Series, np.complexfloating, ) + if TYPE_CHECKING_INVALID_USAGE: + left.rtruediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left.rtruediv(d), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) 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) @@ -160,6 +239,9 @@ def test_truediv_numpy_array(left: "pd.Series[float]") -> None: check( assert_type(left.rdiv(c), "pd.Series[complex]"), pd.Series, np.complexfloating ) + if TYPE_CHECKING_INVALID_USAGE: + left.rdiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rdiv(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) def test_truediv_pd_scalar(left: "pd.Series[float]") -> None: @@ -201,16 +283,24 @@ def test_truediv_pd_index(left: "pd.Series[float]") -> None: i = pd.Index([2, 3, 5]) f = pd.Index([1.0, 2.0, 3.0]) c = pd.Index([1.1j, 2.2j, 4.1j]) + s = pd.Index([datetime(2025, 10, d) for d in (28, 29, 30)]) + d = pd.Index([timedelta(seconds=s + 1) for s in range(3)]) 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) + if TYPE_CHECKING_INVALID_USAGE: + _04 = left / s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left / d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] 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) + if TYPE_CHECKING_INVALID_USAGE: + _14 = s / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d / left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) 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) @@ -220,11 +310,17 @@ def test_truediv_pd_index(left: "pd.Series[float]") -> None: pd.Series, np.complexfloating, ) + if TYPE_CHECKING_INVALID_USAGE: + left.truediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.truediv(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] 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) + if TYPE_CHECKING_INVALID_USAGE: + left.div(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.div(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] 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) @@ -234,6 +330,13 @@ def test_truediv_pd_index(left: "pd.Series[float]") -> None: pd.Series, np.complexfloating, ) + if TYPE_CHECKING_INVALID_USAGE: + left.rtruediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left.rtruediv(d), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) 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) @@ -241,6 +344,9 @@ def test_truediv_pd_index(left: "pd.Series[float]") -> None: check( assert_type(left.rdiv(c), "pd.Series[complex]"), pd.Series, np.complexfloating ) + if TYPE_CHECKING_INVALID_USAGE: + left.rdiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rdiv(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) def test_truediv_pd_series(left: "pd.Series[float]") -> None: @@ -249,16 +355,24 @@ def test_truediv_pd_series(left: "pd.Series[float]") -> None: i = pd.Series([2, 3, 5]) f = pd.Series([1.0, 2.0, 3.0]) c = pd.Series([1.1j, 2.2j, 4.1j]) + s = pd.Series([datetime(2025, 10, d) for d in (28, 29, 30)]) + d = pd.Series([timedelta(seconds=s + 1) for s in range(3)]) 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) + if TYPE_CHECKING_INVALID_USAGE: + _04 = left / s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left / d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] 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) + if TYPE_CHECKING_INVALID_USAGE: + _14 = s / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d / left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) 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) @@ -268,11 +382,17 @@ def test_truediv_pd_series(left: "pd.Series[float]") -> None: pd.Series, np.complexfloating, ) + if TYPE_CHECKING_INVALID_USAGE: + left.truediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.truediv(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] 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) + if TYPE_CHECKING_INVALID_USAGE: + left.div(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.div(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] 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) @@ -282,6 +402,13 @@ def test_truediv_pd_series(left: "pd.Series[float]") -> None: pd.Series, np.complexfloating, ) + if TYPE_CHECKING_INVALID_USAGE: + left.rtruediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left.rtruediv(d), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) 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) @@ -289,3 +416,6 @@ def test_truediv_pd_series(left: "pd.Series[float]") -> None: check( assert_type(left.rdiv(c), "pd.Series[complex]"), pd.Series, np.complexfloating ) + if TYPE_CHECKING_INVALID_USAGE: + left.rdiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rdiv(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) diff --git a/tests/series/arithmetic/int/test_floordiv.py b/tests/series/arithmetic/int/test_floordiv.py index 0504d1074..a5e810b44 100644 --- a/tests/series/arithmetic/int/test_floordiv.py +++ b/tests/series/arithmetic/int/test_floordiv.py @@ -1,8 +1,12 @@ +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 +import pytest from typing_extensions import ( Never, assert_type, @@ -13,166 +17,237 @@ check, ) -left = pd.Series([1, 2, 3]) # left operand + +@pytest.fixture +def left() -> "pd.Series[int]": + """Left operand""" + lo = pd.Series([1, 2, 3]) + return check(assert_type(lo, "pd.Series[int]"), pd.Series, np.integer) -def test_floordiv_py_scalar() -> None: +def test_floordiv_py_scalar(left: "pd.Series[int]") -> None: """Test pd.Series[int] // Python native scalars""" b, i, f, c = True, 1, 1.0, 1j + s, d = datetime(2025, 9, 27), timedelta(seconds=1) - if TYPE_CHECKING_INVALID_USAGE: - _0 = left // b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + 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) if TYPE_CHECKING_INVALID_USAGE: - _1 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _03 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _04 = left // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left // d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - _2 = b // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + 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) if TYPE_CHECKING_INVALID_USAGE: - _3 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _13 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _14 = s // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d // left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) - left.floordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.floordiv(b), "pd.Series[int]"), pd.Series, np.integer) 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.floordiv(c) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + left.floordiv(s) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + left.floordiv(d) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] - left.rfloordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rfloordiv(b), "pd.Series[int]"), pd.Series, np.integer) 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] + 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[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) -def test_floordiv_py_sequence() -> None: +def test_floordiv_py_sequence(left: "pd.Series[int]") -> 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] + b, i, f, c = [True, True, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] + s = [datetime(2025, 10, 27 + d) for d in range(3)] + d = [timedelta(seconds=s) for s in range(3)] - if TYPE_CHECKING_INVALID_USAGE: - _0 = left // b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + 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) if TYPE_CHECKING_INVALID_USAGE: - _1 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _03 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _04 = left // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left // d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - _2 = b // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + 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) if TYPE_CHECKING_INVALID_USAGE: - _3 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _13 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _14 = s // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _15 = d // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - left.floordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.floordiv(b), "pd.Series[int]"), pd.Series, np.integer) 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.floordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.floordiv(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] - left.rfloordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rfloordiv(b), "pd.Series[int]"), pd.Series, np.integer) 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] + left.rfloordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left.rfloordiv(d), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) -def test_floordiv_numpy_array() -> None: +def test_floordiv_numpy_array(left: "pd.Series[int]") -> None: """Test pd.Series[int] // numpy arrays""" - b = np.array([True, False, True], np.bool_) + b = np.array([True, True, 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) + s = np.array( + [np.datetime64(f"2025-10-{d:02d}") for d in (23, 24, 25)], np.datetime64 + ) + d = np.array([np.timedelta64(s + 1, "s") for s in range(3)], np.timedelta64) - if TYPE_CHECKING_INVALID_USAGE: - assert_type(left // b, Never) + 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) if TYPE_CHECKING_INVALID_USAGE: assert_type(left // c, Never) + assert_type(left // s, Never) + assert_type(left // d, Never) - # `numpy` typing gives the corresponding `ndarray`s in the static type - # checking, where our `__rfloordiv__` cannot override. At runtime, they lead to - # errors or pd.Series. - assert_type(b // left, "npt.NDArray[np.int8]") + # `numpy` typing gives the corresponding `ndarray`s in the static type + # checking, where our `__rfloordiv__` cannot override. At runtime, they lead to + # errors or pd.Series. + check(b // left, pd.Series, np.integer) check(i // left, pd.Series, np.integer) check(f // left, pd.Series, np.floating) if TYPE_CHECKING_INVALID_USAGE: assert_type(c // left, Any) + assert_type(s // left, Any) + assert_type(d // left, "np.typing.NDArray[np.int64]") - left.floordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.floordiv(b), "pd.Series[int]"), pd.Series, np.integer) 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.floordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.floordiv(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] - left.rfloordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rfloordiv(b), "pd.Series[int]"), pd.Series, np.integer) 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] + left.rfloordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left.rfloordiv(d), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) -def test_floordiv_pd_index() -> None: +def test_floordiv_pd_index(left: "pd.Series[int]") -> None: """Test pd.Series[int] // pandas Indexes""" - b = pd.Index([True, False, True]) + b = pd.Index([True, True, 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]) + s = pd.Index([datetime(2025, 10, d) for d in (27, 28, 29)]) + d = pd.Index([timedelta(seconds=s + 1) for s in range(3)]) - if TYPE_CHECKING_INVALID_USAGE: - _0 = left // b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + 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) if TYPE_CHECKING_INVALID_USAGE: - _1 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _03 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _04 = left // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left // d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - _2 = b // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + 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) if TYPE_CHECKING_INVALID_USAGE: - _3 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _13 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _14 = s // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d // left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) - left.floordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.floordiv(b), "pd.Series[int]"), pd.Series, np.integer) 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.floordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.floordiv(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] - left.rfloordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rfloordiv(b), "pd.Series[int]"), pd.Series, np.integer) 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] + left.rfloordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left.rfloordiv(d), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) -def test_floordiv_pd_series() -> None: +def test_floordiv_pd_series(left: "pd.Series[int]") -> None: """Test pd.Series[int] // pandas Series""" - b = pd.Series([True, False, True]) + b = pd.Series([True, True, 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]) + s = pd.Series([datetime(2025, 10, d) for d in (27, 28, 29)]) + d = pd.Series([timedelta(seconds=s + 1) for s in range(3)]) - if TYPE_CHECKING_INVALID_USAGE: - _0 = left // b # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + 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) if TYPE_CHECKING_INVALID_USAGE: - _1 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _03 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _04 = left // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left // d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - _2 = b // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + 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) if TYPE_CHECKING_INVALID_USAGE: - _3 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _13 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _14 = s // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d // left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) - left.floordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.floordiv(b), "pd.Series[int]"), pd.Series, np.integer) 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.floordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.floordiv(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] - left.rfloordiv(b) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rfloordiv(b), "pd.Series[int]"), pd.Series, np.integer) 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] + left.rfloordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left.rfloordiv(d), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) diff --git a/tests/series/arithmetic/int/test_truediv.py b/tests/series/arithmetic/int/test_truediv.py index 757173a3a..52c3f66a0 100644 --- a/tests/series/arithmetic/int/test_truediv.py +++ b/tests/series/arithmetic/int/test_truediv.py @@ -1,3 +1,8 @@ +from datetime import ( + datetime, + timedelta, +) + import numpy as np from numpy import typing as npt # noqa: F401 import pandas as pd @@ -20,16 +25,23 @@ def left() -> "pd.Series[int]": def test_truediv_py_scalar(left: "pd.Series[int]") -> None: """Test pd.Series[int] / Python native scalars""" b, i, f, c = True, 1, 1.0, 1j + s, d = datetime(2025, 9, 27), timedelta(seconds=1) 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) + if TYPE_CHECKING_INVALID_USAGE: + _04 = left / s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left / d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] 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) + if TYPE_CHECKING_INVALID_USAGE: + _14 = s / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d / left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) 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) @@ -39,11 +51,17 @@ def test_truediv_py_scalar(left: "pd.Series[int]") -> None: pd.Series, np.complexfloating, ) + if TYPE_CHECKING_INVALID_USAGE: + left.truediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.truediv(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] 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) + if TYPE_CHECKING_INVALID_USAGE: + left.div(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.div(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] 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) @@ -53,6 +71,13 @@ def test_truediv_py_scalar(left: "pd.Series[int]") -> None: pd.Series, np.complexfloating, ) + if TYPE_CHECKING_INVALID_USAGE: + left.rtruediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left.rtruediv(d), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) 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) @@ -60,6 +85,9 @@ def test_truediv_py_scalar(left: "pd.Series[int]") -> None: check( assert_type(left.rdiv(c), "pd.Series[complex]"), pd.Series, np.complexfloating ) + if TYPE_CHECKING_INVALID_USAGE: + left.rdiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rdiv(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) def test_truediv_py_sequence(left: "pd.Series[int]") -> None: diff --git a/tests/series/arithmetic/timedelta/test_floordiv.py b/tests/series/arithmetic/timedelta/test_floordiv.py index bb267d583..eb9a9935d 100644 --- a/tests/series/arithmetic/timedelta/test_floordiv.py +++ b/tests/series/arithmetic/timedelta/test_floordiv.py @@ -7,6 +7,7 @@ import numpy as np from numpy import typing as npt # noqa: F401 import pandas as pd +import pytest from typing_extensions import ( Never, assert_type, @@ -17,29 +18,34 @@ check, ) -left = pd.Series([pd.Timedelta(1, "s")]) # left operand +@pytest.fixture +def left() -> "pd.Series[pd.Timedelta]": + """Left operand""" + lo = pd.Series([pd.Timedelta(1, "s")]) + return check(assert_type(lo, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) -def test_floordiv_py_scalar() -> None: + +def test_floordiv_py_scalar(left: "pd.Series[pd.Timedelta]") -> 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] + _00 = 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] + _03 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _04 = 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] + _10 = b // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _11 = i // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _12 = f // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _13 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _14 = 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: @@ -68,26 +74,26 @@ def test_floordiv_py_scalar() -> None: check(assert_type(left.rfloordiv(d), "pd.Series[int]"), pd.Series, np.integer) -def test_floordiv_py_sequence() -> None: +def test_floordiv_py_sequence(left: "pd.Series[pd.Timedelta]") -> 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] + _00 = 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] + _03 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _04 = 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] + _10 = b // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _11 = i // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _12 = f // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _13 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _14 = 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: @@ -116,7 +122,7 @@ def test_floordiv_py_sequence() -> None: check(assert_type(left.rfloordiv(d), "pd.Series[int]"), pd.Series, np.integer) -def test_floordiv_numpy_array() -> None: +def test_floordiv_numpy_array(left: "pd.Series[pd.Timedelta]") -> None: """Test pd.Series[pd.Timedelta] // numpy arrays""" b = np.array([True], np.bool_) i = np.array([2], np.int64) @@ -171,16 +177,16 @@ def test_floordiv_numpy_array() -> None: check(assert_type(left.rfloordiv(d), "pd.Series[int]"), pd.Series, np.integer) -def test_floordiv_pd_scalar() -> None: +def test_floordiv_pd_scalar(left: "pd.Series[pd.Timedelta]") -> 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] + _00 = 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] + _10 = 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: @@ -192,7 +198,7 @@ def test_floordiv_pd_scalar() -> None: check(assert_type(left.rfloordiv(d), "pd.Series[int]"), pd.Series, np.integer) -def test_floordiv_pd_index() -> None: +def test_floordiv_pd_index(left: "pd.Series[pd.Timedelta]") -> None: """Test pd.Series[pd.Timedelta] // pandas Indexes""" b = pd.Index([True]) i = pd.Index([2]) @@ -201,20 +207,20 @@ def test_floordiv_pd_index() -> None: 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] + _00 = 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] + _03 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _04 = 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] + _10 = b // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _11 = i // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _12 = f // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _13 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _14 = 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: @@ -243,7 +249,7 @@ def test_floordiv_pd_index() -> None: check(assert_type(left.rfloordiv(d), "pd.Series[int]"), pd.Series, np.integer) -def test_floordiv_pd_series() -> None: +def test_floordiv_pd_series(left: "pd.Series[pd.Timedelta]") -> None: """Test pd.Series[pd.Timedelta] // pandas Series""" b = pd.Series([True]) i = pd.Series([2]) @@ -252,20 +258,20 @@ def test_floordiv_pd_series() -> None: 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] + _00 = 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] + _03 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _04 = 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] + _10 = b // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _11 = i // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _12 = f // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _13 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _14 = 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: diff --git a/tests/test_natype.py b/tests/test_natype.py index 7a524bc37..c55d07a47 100644 --- a/tests/test_natype.py +++ b/tests/test_natype.py @@ -83,11 +83,8 @@ def test_arithmetic() -> None: # __divmod__ # bug upstream: https://github.com/pandas-dev/pandas/issues/62196 # check( - # assert_type( - # divmod(na, s_int), - # tuple[pd.Series, pd.Series], - # ), - # tuple, + assert_type(divmod(na, s_int), tuple[pd.Series, pd.Series]) + # , tuple # ) # check( # assert_type( @@ -110,13 +107,13 @@ def test_arithmetic() -> None: # __rdivmod__ # bug upstream: https://github.com/pandas-dev/pandas/issues/62196 # check( - # assert_type(divmod(s_int, na), tuple[pd.Series, pd.Series]), - # tuple, + assert_type(divmod(s_int, na), "tuple[pd.Series[int], pd.Series[int]]") + # , tuple, # ) - # https://github.com/pandas-dev/pandas-stubs/issues/1347 + # bug upstream: https://github.com/pandas-dev/pandas/issues/62196 # check( - # assert_type(divmod(idx_int, na), tuple[pd.Index, pd.Index]), - # tuple, + assert_type(divmod(idx_int, na), "tuple[pd.Index[int], pd.Index[int]]") + # , tuple, # ) check(assert_type(divmod(1, na), tuple[NAType, NAType]), tuple) From 7a32e45f6d094928319f9895d63b8c890f3d671b Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Tue, 28 Oct 2025 11:22:29 +0100 Subject: [PATCH 2/9] remove irrelevant changes --- pandas-stubs/core/base.pyi | 43 -------------------------------------- tests/test_natype.py | 16 ++++++++++---- 2 files changed, 12 insertions(+), 47 deletions(-) diff --git a/pandas-stubs/core/base.pyi b/pandas-stubs/core/base.pyi index 55af19d4f..e9447a76f 100644 --- a/pandas-stubs/core/base.pyi +++ b/pandas-stubs/core/base.pyi @@ -29,7 +29,6 @@ from pandas._libs.tslibs.timedeltas import Timedelta from pandas._typing import ( S1, S2, - S3, AxisIndex, DropKeep, DTypeLike, @@ -323,30 +322,6 @@ class ElementOpsMixin(Generic[S2]): def _proto_rfloordiv( self: ElementOpsMixin[Timedelta], other: timedelta | np.timedelta64 | Timedelta ) -> ElementOpsMixin[int]: ... - @overload - def _proto_mod( - self: ElementOpsMixin[int], other: int | np.integer - ) -> ElementOpsMixin[int]: ... - @overload - def _proto_mod( - self: ElementOpsMixin[float], other: float | np.floating - ) -> ElementOpsMixin[float]: ... - @overload - def _proto_mod( - self: ElementOpsMixin[Timedelta], other: timedelta | np.timedelta64 | Timedelta - ) -> ElementOpsMixin[Timedelta]: ... - @overload - def _proto_rmod( - self: ElementOpsMixin[int], other: int | np.integer - ) -> ElementOpsMixin[int]: ... - @overload - def _proto_rmod( - self: ElementOpsMixin[float], other: float | np.floating - ) -> ElementOpsMixin[float]: ... - @overload - def _proto_rmod( - self: ElementOpsMixin[Timedelta], other: timedelta | np.timedelta64 | Timedelta - ) -> ElementOpsMixin[Timedelta]: ... @type_check_only class Supports_ProtoAdd(Protocol[_T_contra, S2]): @@ -379,21 +354,3 @@ class Supports_ProtoFloorDiv(Protocol[_T_contra, S2]): @type_check_only class Supports_ProtoRFloorDiv(Protocol[_T_contra, S2]): def _proto_rfloordiv(self, other: _T_contra, /) -> ElementOpsMixin[S2]: ... - -@type_check_only -class Supports_ProtoMod(Protocol[_T_contra, S2]): - def _proto_mod(self, other: _T_contra, /) -> ElementOpsMixin[S2]: ... - -@type_check_only -class Supports_ProtoRMod(Protocol[_T_contra, S2]): - def _proto_rmod(self, other: _T_contra, /) -> ElementOpsMixin[S2]: ... - -@type_check_only -class Supports_ProtoDivMod(Protocol[_T_contra, S2, S3]): - def _proto_floordiv(self, other: _T_contra, /) -> ElementOpsMixin[S2]: ... - def _proto_mod(self, other: _T_contra, /) -> ElementOpsMixin[S3]: ... - -@type_check_only -class Supports_ProtoRDivMod(Protocol[_T_contra, S2, S3]): - def _proto_rfloordiv(self, other: _T_contra, /) -> ElementOpsMixin[S2]: ... - def _proto_rmod(self, other: _T_contra, /) -> ElementOpsMixin[S3]: ... diff --git a/tests/test_natype.py b/tests/test_natype.py index c55d07a47..f1016374f 100644 --- a/tests/test_natype.py +++ b/tests/test_natype.py @@ -83,8 +83,11 @@ def test_arithmetic() -> None: # __divmod__ # bug upstream: https://github.com/pandas-dev/pandas/issues/62196 # check( - assert_type(divmod(na, s_int), tuple[pd.Series, pd.Series]) - # , tuple + # assert_type( + # divmod(na, s_int), + # tuple[pd.Series, pd.Series], + # ), + # tuple, # ) # check( # assert_type( @@ -107,8 +110,13 @@ def test_arithmetic() -> None: # __rdivmod__ # bug upstream: https://github.com/pandas-dev/pandas/issues/62196 # check( - assert_type(divmod(s_int, na), "tuple[pd.Series[int], pd.Series[int]]") - # , tuple, + # assert_type(divmod(s_int, na), tuple[pd.Series, pd.Series]), + # tuple, + # ) + # https://github.com/pandas-dev/pandas-stubs/issues/1347 + # check( + # assert_type(divmod(idx_int, na), tuple[pd.Index, pd.Index]), + # tuple, # , tuple, # ) # bug upstream: https://github.com/pandas-dev/pandas/issues/62196 # check( From cb1506ad9fa2faefdaf99d46a5769da2d3463db6 Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Tue, 28 Oct 2025 11:59:50 +0100 Subject: [PATCH 3/9] floordiv --- pandas-stubs/core/indexes/base.pyi | 34 ++- pandas-stubs/core/series.pyi | 26 ++ .../indexes/arithmetic/float/test_floordiv.py | 131 +++++++++ tests/indexes/arithmetic/test_floordiv.py | 127 +++++++++ tests/series/arithmetic/test_floordiv.py | 253 ++++++++++++++++++ 5 files changed, 569 insertions(+), 2 deletions(-) create mode 100644 tests/indexes/arithmetic/float/test_floordiv.py create mode 100644 tests/indexes/arithmetic/test_floordiv.py create mode 100644 tests/series/arithmetic/test_floordiv.py diff --git a/pandas-stubs/core/indexes/base.pyi b/pandas-stubs/core/indexes/base.pyi index 0c9f4a445..534ac4825 100644 --- a/pandas-stubs/core/indexes/base.pyi +++ b/pandas-stubs/core/indexes/base.pyi @@ -1057,7 +1057,23 @@ class Index(IndexOpsMixin[S1], ElementOpsMixin[S1]): @overload def __rtruediv__(self, other: Path) -> Index: ... @overload - def __floordiv__(self, other: Index[Never]) -> Index: ... + def __floordiv__( + self: Index[Never], + other: ( + float + | Sequence[float] + | np_ndarray_bool + | np_ndarray_anyint + | np_ndarray_float + | Index[bool] + | Index[int] + | Index[float] + ), + ) -> Index: ... + @overload + def __floordiv__( + self: Index[bool] | Index[int] | Index[float], other: Index[Never] + ) -> Index: ... @overload def __floordiv__( self: Index[int] | Index[float], @@ -1094,7 +1110,21 @@ class Index(IndexOpsMixin[S1], ElementOpsMixin[S1]): other: float | Sequence[float] | np_ndarray_float | Index[float], ) -> Index[float]: ... @overload - def __rfloordiv__(self, other: Index[Never]) -> Index: ... # type: ignore[overload-overlap] + def __rfloordiv__( + self: Index[Never], + other: ( + float + | Sequence[float] + | np_ndarray_bool + | np_ndarray_anyint + | np_ndarray_float + | Index[bool] + | Index[int] + | Index[float] + ), + ) -> Index: ... + @overload + def __rfloordiv__(self: Index[bool] | Index[int] | Index[float], other: Index[Never]) -> Index: ... # type: ignore[overload-overlap] @overload def __rfloordiv__( self: Index[int] | Index[float], diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index 29b345631..40b4c20cd 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -2151,6 +2151,19 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): def __and__(self, other: int | np_ndarray_anyint | Series[int]) -> Series[int]: ... def __eq__(self, other: object) -> Series[_bool]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] @overload + def __floordiv__( + self: Series[Never], + other: ( + float + | Sequence[float] + | np_ndarray_bool + | np_ndarray_anyint + | np_ndarray_float + | Index + | Series + ), + ) -> Series: ... + @overload def __floordiv__(self, other: Index[Never] | Series[Never]) -> Series: ... @overload def __floordiv__( @@ -2300,6 +2313,19 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): axis: AxisIndex | None = 0, ) -> Series[int]: ... @overload + def __rfloordiv__( + self: Series[Never], + other: ( + float + | Sequence[float] + | np_ndarray_bool + | np_ndarray_anyint + | np_ndarray_float + | Index + | Series + ), + ) -> Series: ... + @overload def __rfloordiv__(self, other: Index[Never] | Series[Never]) -> Series: ... @overload def __rfloordiv__( diff --git a/tests/indexes/arithmetic/float/test_floordiv.py b/tests/indexes/arithmetic/float/test_floordiv.py new file mode 100644 index 000000000..45faab573 --- /dev/null +++ b/tests/indexes/arithmetic/float/test_floordiv.py @@ -0,0 +1,131 @@ +from datetime import ( + datetime, + timedelta, +) +from typing import Any + +import numpy as np +import pandas as pd +import pytest +from typing_extensions import ( + Never, + assert_type, +) + +from tests import ( + TYPE_CHECKING_INVALID_USAGE, + check, +) + + +@pytest.fixture +def left() -> "pd.Index[float]": + """Left operand""" + lo = pd.Index([1.2, 2.4, 3.6]) + return check(assert_type(lo, "pd.Index[float]"), pd.Index, np.floating) + + +def test_floordiv_py_scalar(left: "pd.Index[float]") -> None: + """Test pd.Index[float] // Python native scalars""" + b, i, f, c = True, 1, 1.0, 1j + s, d = datetime(2025, 9, 27), timedelta(seconds=1) + + check(assert_type(left // b, "pd.Index[float]"), pd.Index, np.floating) + check(assert_type(left // i, "pd.Index[float]"), pd.Index, np.floating) + check(assert_type(left // f, "pd.Index[float]"), pd.Index, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _03 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _04 = left // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left // d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + check(assert_type(b // left, "pd.Index[float]"), pd.Index, np.floating) + check(assert_type(i // left, "pd.Index[float]"), pd.Index, np.floating) + check(assert_type(f // left, "pd.Index[float]"), pd.Index, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _13 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _14 = s // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d // left, pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) + + +def test_floordiv_py_sequence(left: "pd.Index[float]") -> None: + """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] + s = [datetime(2025, 10, 27 + d) for d in range(3)] + d = [timedelta(seconds=s) for s in range(3)] + + check(assert_type(left // b, "pd.Index[float]"), pd.Index, np.floating) + check(assert_type(left // i, "pd.Index[float]"), pd.Index, np.floating) + check(assert_type(left // f, "pd.Index[float]"), pd.Index, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _03 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _04 = left // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left // d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + check(assert_type(b // left, "pd.Index[float]"), pd.Index, np.floating) + check(assert_type(i // left, "pd.Index[float]"), pd.Index, np.floating) + check(assert_type(f // left, "pd.Index[float]"), pd.Index, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _13 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _14 = s // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _15 = d // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + +def test_floordiv_numpy_array(left: "pd.Index[float]") -> None: + """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) + c = np.array([1.1j, 2.2j, 4.1j], np.complex128) + s = np.array( + [np.datetime64(f"2025-10-{d:02d}") for d in (23, 24, 25)], np.datetime64 + ) + d = np.array([np.timedelta64(s + 1, "s") for s in range(3)], np.timedelta64) + + check(assert_type(left // b, "pd.Index[float]"), pd.Index, np.floating) + check(assert_type(left // i, "pd.Index[float]"), pd.Index, np.floating) + check(assert_type(left // f, "pd.Index[float]"), pd.Index, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + assert_type(left // c, Never) + assert_type(left // s, Never) + assert_type(left // d, Never) + + # `numpy` typing gives the corresponding `ndarray`s in the static type + # checking, where our `__rfloordiv__` cannot override. At runtime, they lead to + # errors or pd.Index. + check(b // left, pd.Index, np.floating) + check(i // left, pd.Index, np.floating) + check(f // left, pd.Index, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + assert_type(c // left, Any) + assert_type(s // left, Any) + check( + assert_type(d // left, "np.typing.NDArray[np.int64]"), + pd.TimedeltaIndex, + pd.Timedelta, + ) + + +def test_floordiv_pd_index(left: "pd.Index[float]") -> None: + """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]) + c = pd.Index([1.1j, 2.2j, 4.1j]) + s = pd.Index([datetime(2025, 10, d) for d in (27, 28, 29)]) + d = pd.Index([timedelta(seconds=s + 1) for s in range(3)]) + + check(assert_type(left // b, "pd.Index[float]"), pd.Index, np.floating) + check(assert_type(left // i, "pd.Index[float]"), pd.Index, np.floating) + check(assert_type(left // f, "pd.Index[float]"), pd.Index, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _03 = left // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _04 = left // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left // d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + check(assert_type(b // left, "pd.Index[float]"), pd.Index, np.floating) + check(assert_type(i // left, "pd.Index[float]"), pd.Index, np.floating) + check(assert_type(f // left, "pd.Index[float]"), pd.Index, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _13 = c // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _14 = s // left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d // left, pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) diff --git a/tests/indexes/arithmetic/test_floordiv.py b/tests/indexes/arithmetic/test_floordiv.py new file mode 100644 index 000000000..76a3bed1e --- /dev/null +++ b/tests/indexes/arithmetic/test_floordiv.py @@ -0,0 +1,127 @@ +from datetime import ( + datetime, + timedelta, +) +from typing import Any + +import numpy as np +import pandas as pd +import pytest +from typing_extensions import ( + Never, + assert_type, +) + +from tests import ( + TYPE_CHECKING_INVALID_USAGE, + check, +) + + +@pytest.fixture +def left_i() -> pd.Index: + """Left operand""" + lo = pd.MultiIndex.from_arrays([[1, 2, 3]]).levels[0] + return check(assert_type(lo, pd.Index), pd.Index, np.integer) + + +def test_floordiv_py_scalar(left_i: pd.Index) -> None: + """Test pd.Index[int] // Python native scalars""" + b, i, f, c = True, 1, 1.0, 1j + s, d = datetime(2025, 9, 27), timedelta(seconds=1) + + check(assert_type(left_i // b, pd.Index), pd.Index, np.integer) + check(assert_type(left_i // i, pd.Index), pd.Index, np.integer) + check(assert_type(left_i // f, pd.Index), pd.Index, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _03 = left_i // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _04 = left_i // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left_i // d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + check(assert_type(b // left_i, pd.Index), pd.Index, np.integer) + check(assert_type(i // left_i, pd.Index), pd.Index, np.integer) + check(assert_type(f // left_i, pd.Index), pd.Index, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _13 = c // left_i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _14 = s // left_i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d // left_i, pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) + + +def test_floordiv_py_sequence(left_i: pd.Index) -> None: + """Test pd.Index[int] // Python native sequences""" + b, i, f, c = [True, True, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] + s = [datetime(2025, 10, 27 + d) for d in range(3)] + d = [timedelta(seconds=s) for s in range(3)] + + check(assert_type(left_i // b, pd.Index), pd.Index, np.integer) + check(assert_type(left_i // i, pd.Index), pd.Index, np.integer) + check(assert_type(left_i // f, pd.Index), pd.Index, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _03 = left_i // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _04 = left_i // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left_i // d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + check(assert_type(b // left_i, pd.Index), pd.Index, np.integer) + check(assert_type(i // left_i, pd.Index), pd.Index, np.integer) + check(assert_type(f // left_i, pd.Index), pd.Index, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _13 = c // left_i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _14 = s // left_i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _15 = d // left_i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + +def test_floordiv_numpy_array(left_i: pd.Index) -> None: + """Test pd.Index[int] // numpy arrays""" + b = np.array([True, True, 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) + s = np.array( + [np.datetime64(f"2025-10-{d:02d}") for d in (23, 24, 25)], np.datetime64 + ) + d = np.array([np.timedelta64(s + 1, "s") for s in range(3)], np.timedelta64) + + check(assert_type(left_i // b, pd.Index), pd.Index, np.integer) + check(assert_type(left_i // i, pd.Index), pd.Index, np.integer) + check(assert_type(left_i // f, pd.Index), pd.Index, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + assert_type(left_i // c, Never) + assert_type(left_i // s, Never) + assert_type(left_i // d, Never) + + # `numpy` typing gives the corresponding `ndarray`s in the static type + # checking, where our `__rfloordiv__` cannot override. At runtime, they lead to + # errors or pd.Index. + check(b // left_i, pd.Index, np.integer) + check(i // left_i, pd.Index, np.integer) + check(f // left_i, pd.Index, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + assert_type(c // left_i, Any) + assert_type(s // left_i, Any) + assert_type(d // left_i, "np.typing.NDArray[np.int64]") + + +def test_floordiv_pd_index(left_i: pd.Index) -> None: + """Test pd.Index[int] // pandas Indexes""" + b = pd.Index([True, True, 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]) + s = pd.Index([datetime(2025, 10, d) for d in (27, 28, 29)]) + d = pd.Index([timedelta(seconds=s + 1) for s in range(3)]) + + check(assert_type(left_i // b, pd.Index), pd.Index, np.integer) + check(assert_type(left_i // i, pd.Index), pd.Index, np.integer) + check(assert_type(left_i // f, pd.Index), pd.Index, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _03 = left_i // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _04 = left_i // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left_i // d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + check(assert_type(b // left_i, pd.Index), pd.Index, np.integer) + check(assert_type(i // left_i, pd.Index), pd.Index, np.integer) + check(assert_type(f // left_i, pd.Index), pd.Index, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _13 = c // left_i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _14 = s // left_i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d // left_i, pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) diff --git a/tests/series/arithmetic/test_floordiv.py b/tests/series/arithmetic/test_floordiv.py new file mode 100644 index 000000000..12cc69322 --- /dev/null +++ b/tests/series/arithmetic/test_floordiv.py @@ -0,0 +1,253 @@ +from datetime import ( + datetime, + timedelta, +) +from typing import Any + +import numpy as np +import pandas as pd +import pytest +from typing_extensions import ( + Never, + assert_type, +) + +from tests import ( + TYPE_CHECKING_INVALID_USAGE, + check, +) + + +@pytest.fixture +def left_i() -> pd.Series: + """Left operand""" + lo = pd.DataFrame({"a": [1, 2, 3]})["a"] + return check(assert_type(lo, pd.Series), pd.Series, np.integer) + + +def test_floordiv_py_scalar(left_i: pd.Series) -> None: + """Test pd.Series[int] // Python native scalars""" + b, i, f, c = True, 1, 1.0, 1j + s, d = datetime(2025, 9, 27), timedelta(seconds=1) + + check(assert_type(left_i // b, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i // i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i // f, "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _03 = left_i // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _04 = left_i // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left_i // d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + check(assert_type(b // left_i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(i // left_i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(f // left_i, "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _13 = c // left_i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _14 = s // left_i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d // left_i, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(left_i.floordiv(b), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i.floordiv(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i.floordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left_i.floordiv(c) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + left_i.floordiv(s) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + left_i.floordiv(d) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + + check(assert_type(left_i.rfloordiv(b), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i.rfloordiv(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i.rfloordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left_i.rfloordiv(c) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + left_i.rfloordiv(s) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left_i.rfloordiv(d), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) + + +def test_floordiv_py_sequence(left_i: pd.Series) -> None: + """Test pd.Series[int] // Python native sequences""" + b, i, f, c = [True, True, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] + s = [datetime(2025, 10, 27 + d) for d in range(3)] + d = [timedelta(seconds=s) for s in range(3)] + + check(assert_type(left_i // b, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i // i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i // f, "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _03 = left_i // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _04 = left_i // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left_i // d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + check(assert_type(b // left_i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(i // left_i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(f // left_i, "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _13 = c // left_i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _14 = s // left_i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _15 = d // left_i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + check(assert_type(left_i.floordiv(b), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i.floordiv(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i.floordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left_i.floordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left_i.floordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left_i.floordiv(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + check(assert_type(left_i.rfloordiv(b), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i.rfloordiv(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i.rfloordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left_i.rfloordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left_i.rfloordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left_i.rfloordiv(d), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) + + +def test_floordiv_numpy_array(left_i: pd.Series) -> None: + """Test pd.Series[int] // numpy arrays""" + b = np.array([True, True, 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) + s = np.array( + [np.datetime64(f"2025-10-{d:02d}") for d in (23, 24, 25)], np.datetime64 + ) + d = np.array([np.timedelta64(s + 1, "s") for s in range(3)], np.timedelta64) + + check(assert_type(left_i // b, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i // i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i // f, "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + assert_type(left_i // c, Never) + assert_type(left_i // s, Never) + assert_type(left_i // d, Never) + + # `numpy` typing gives the corresponding `ndarray`s in the static type + # checking, where our `__rfloordiv__` cannot override. At runtime, they lead to + # errors or pd.Series. + check(b // left_i, pd.Series, np.integer) + check(i // left_i, pd.Series, np.integer) + check(f // left_i, pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + assert_type(c // left_i, Any) + assert_type(s // left_i, Any) + assert_type(d // left_i, "np.typing.NDArray[np.int64]") + + check(assert_type(left_i.floordiv(b), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i.floordiv(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i.floordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left_i.floordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left_i.floordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left_i.floordiv(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + check(assert_type(left_i.rfloordiv(b), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i.rfloordiv(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i.rfloordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left_i.rfloordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left_i.rfloordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left_i.rfloordiv(d), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) + + +def test_floordiv_pd_index(left_i: pd.Series) -> None: + """Test pd.Series[int] // pandas Indexes""" + b = pd.Index([True, True, 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]) + s = pd.Index([datetime(2025, 10, d) for d in (27, 28, 29)]) + d = pd.Index([timedelta(seconds=s + 1) for s in range(3)]) + + check(assert_type(left_i // b, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i // i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i // f, "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _03 = left_i // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _04 = left_i // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left_i // d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + check(assert_type(b // left_i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(i // left_i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(f // left_i, "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _13 = c // left_i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _14 = s // left_i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d // left_i, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(left_i.floordiv(b), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i.floordiv(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i.floordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left_i.floordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left_i.floordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left_i.floordiv(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + check(assert_type(left_i.rfloordiv(b), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i.rfloordiv(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i.rfloordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left_i.rfloordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left_i.rfloordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left_i.rfloordiv(d), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) + + +def test_floordiv_pd_series(left_i: pd.Series) -> None: + """Test pd.Series[int] // pandas Series""" + b = pd.Series([True, True, 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]) + s = pd.Series([datetime(2025, 10, d) for d in (27, 28, 29)]) + d = pd.Series([timedelta(seconds=s + 1) for s in range(3)]) + + check(assert_type(left_i // b, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i // i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i // f, "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _03 = left_i // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _04 = left_i // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left_i // d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + + check(assert_type(b // left_i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(i // left_i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(f // left_i, "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + _13 = c // left_i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _14 = s // left_i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d // left_i, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + + check(assert_type(left_i.floordiv(b), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i.floordiv(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i.floordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left_i.floordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left_i.floordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left_i.floordiv(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + + check(assert_type(left_i.rfloordiv(b), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i.rfloordiv(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left_i.rfloordiv(f), "pd.Series[float]"), pd.Series, np.floating) + if TYPE_CHECKING_INVALID_USAGE: + left_i.rfloordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left_i.rfloordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left_i.rfloordiv(d), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) From 0f86bc870560ab9012b4a3ae8fac7732ecde4681 Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Tue, 28 Oct 2025 12:03:58 +0100 Subject: [PATCH 4/9] remove irrelevant change --- tests/test_natype.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/test_natype.py b/tests/test_natype.py index f1016374f..f9bc17162 100644 --- a/tests/test_natype.py +++ b/tests/test_natype.py @@ -116,12 +116,6 @@ def test_arithmetic() -> None: # https://github.com/pandas-dev/pandas-stubs/issues/1347 # check( # assert_type(divmod(idx_int, na), tuple[pd.Index, pd.Index]), - # tuple, # , tuple, - # ) - # bug upstream: https://github.com/pandas-dev/pandas/issues/62196 - # check( - assert_type(divmod(idx_int, na), "tuple[pd.Index[int], pd.Index[int]]") - # , tuple, # ) check(assert_type(divmod(1, na), tuple[NAType, NAType]), tuple) From e1090cf07499fcfd64e05b2c724e0c7998069444 Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Tue, 28 Oct 2025 13:46:59 +0100 Subject: [PATCH 5/9] floordiv --- pandas-stubs/core/indexes/timedeltas.pyi | 2 +- pandas-stubs/core/series.pyi | 77 ++++++++-- tests/indexes/arithmetic/test_floordiv.py | 2 +- tests/indexes/test_indexes.py | 39 ----- tests/scalars/test_scalars.py | 29 ---- tests/series/arithmetic/float/test_truediv.py | 2 +- tests/series/arithmetic/int/test_truediv.py | 108 +++++++++++++- tests/series/arithmetic/test_floordiv.py | 134 +++++++++--------- .../arithmetic/timedelta/test_truediv.py | 20 ++- tests/series/test_series.py | 2 - tests/test_natype.py | 1 + 11 files changed, 256 insertions(+), 160 deletions(-) diff --git a/pandas-stubs/core/indexes/timedeltas.pyi b/pandas-stubs/core/indexes/timedeltas.pyi index 1eec0d158..2f632cd8a 100644 --- a/pandas-stubs/core/indexes/timedeltas.pyi +++ b/pandas-stubs/core/indexes/timedeltas.pyi @@ -133,7 +133,7 @@ class TimedeltaIndex( def __floordiv__( # pyright: ignore[reportIncompatibleMethodOverride] self, other: _DT_FACTOR_SEQ | Self ) -> Index[int]: ... - @overload # type: ignore[override] + @overload def __rfloordiv__( # pyrefly: ignore[bad-override] self, other: ( diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index 40b4c20cd..9d99f09cb 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -2143,15 +2143,14 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): ) -> Series[_str]: ... # ignore needed for mypy as we want different results based on the arguments @overload # type: ignore[override] - # pyrefly: ignore # bad-override - def __and__( # pyright: ignore[reportOverlappingOverload] + def __and__( # pyright: ignore[reportOverlappingOverload] # pyrefly: ignore[bad-override] self, other: bool | list[int] | MaskType ) -> Series[bool]: ... @overload def __and__(self, other: int | np_ndarray_anyint | Series[int]) -> Series[int]: ... def __eq__(self, other: object) -> Series[_bool]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] @overload - def __floordiv__( + def __floordiv__( # type: ignore[overload-overlap] self: Series[Never], other: ( float @@ -2159,12 +2158,19 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Index - | Series + | Index[bool] + | Index[int] + | Index[float] + | Series[bool] + | Series[int] + | Series[float] ), ) -> Series: ... @overload - def __floordiv__(self, other: Index[Never] | Series[Never]) -> Series: ... + def __floordiv__( + self: Series[bool] | Series[int] | Series[float] | Series[Timedelta], + other: Index[Never] | Series[Never], + ) -> Series: ... @overload def __floordiv__( self: Series[int] | Series[float], @@ -2230,7 +2236,27 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): ) -> Series[int]: ... @overload def floordiv( - self, + self: Series[Never], + other: ( + float + | Sequence[float] + | np_ndarray_bool + | 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: ... + @overload + def floordiv( + self: Series[bool] | Series[int] | Series[float] | Series[Timedelta], other: Index[Never] | Series[Never], level: Level | None = ..., fill_value: float | None = None, @@ -2313,7 +2339,7 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): axis: AxisIndex | None = 0, ) -> Series[int]: ... @overload - def __rfloordiv__( + def __rfloordiv__( # type: ignore[overload-overlap] self: Series[Never], other: ( float @@ -2321,12 +2347,19 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Index - | Series + | Index[bool] + | Index[int] + | Index[float] + | Series[bool] + | Series[int] + | Series[float] ), ) -> Series: ... @overload - def __rfloordiv__(self, other: Index[Never] | Series[Never]) -> Series: ... + def __rfloordiv__( + self: Series[bool] | Series[int] | Series[float] | Series[Timedelta], + other: Index[Never] | Series[Never], + ) -> Series: ... @overload def __rfloordiv__( self: Series[int] | Series[float], @@ -2388,7 +2421,27 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): ) -> Series[int]: ... @overload def rfloordiv( - self, + self: Series[Never], + other: ( + float + | Sequence[float] + | np_ndarray_bool + | 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: ... + @overload + def rfloordiv( + self: Series[bool] | Series[int] | Series[float] | Series[Timedelta], other: Index[Never] | Series[Never], level: Level | None = ..., fill_value: float | None = None, diff --git a/tests/indexes/arithmetic/test_floordiv.py b/tests/indexes/arithmetic/test_floordiv.py index 76a3bed1e..82f3dbc8a 100644 --- a/tests/indexes/arithmetic/test_floordiv.py +++ b/tests/indexes/arithmetic/test_floordiv.py @@ -98,7 +98,7 @@ def test_floordiv_numpy_array(left_i: pd.Index) -> None: if TYPE_CHECKING_INVALID_USAGE: assert_type(c // left_i, Any) assert_type(s // left_i, Any) - assert_type(d // left_i, "np.typing.NDArray[np.int64]") + assert_type(d // left_i, Any) # pyright: ignore[reportAssertTypeFailure] def test_floordiv_pd_index(left_i: pd.Index) -> None: diff --git a/tests/indexes/test_indexes.py b/tests/indexes/test_indexes.py index 6c25d5e13..486bb82ad 100644 --- a/tests/indexes/test_indexes.py +++ b/tests/indexes/test_indexes.py @@ -265,17 +265,6 @@ def test_types_to_numpy() -> None: ) -def test_index_arithmetic() -> None: - # GH 287 - idx = pd.Index([1, 2.2, 3], dtype=float) - check(assert_type(idx * 3, "pd.Index[float]"), pd.Index, np.float64) - check(assert_type(idx / 3, "pd.Index[float]"), pd.Index, np.float64) - check(assert_type(idx // 3, "pd.Index[float]"), pd.Index, np.float64) - check(assert_type(3 * idx, "pd.Index[float]"), pd.Index, np.float64) - check(assert_type(3 / idx, "pd.Index[float]"), pd.Index, np.float64) - check(assert_type(3 // idx, "pd.Index[float]"), pd.Index, np.float64) - - def test_range_index_union() -> None: check( assert_type( @@ -846,9 +835,6 @@ def test_index_operators() -> None: i1 = pd.Index([1, 2, 3]) i2 = pd.Index([4, 5, 6]) - check(assert_type(i1 // i2, "pd.Index[int]"), pd.Index) - check(assert_type(i1 // 10, "pd.Index[int]"), pd.Index) - check(assert_type(10 // i1, "pd.Index[int]"), pd.Index) check(assert_type(i1**i2, "pd.Index[int]"), pd.Index) check(assert_type(i1**2, "pd.Index[int]"), pd.Index) check(assert_type(2**i1, "pd.Index[int]"), pd.Index) @@ -1197,31 +1183,6 @@ def test_new() -> None: ) -def test_timedelta_div() -> None: - index = pd.Index([pd.Timedelta(days=1)], dtype="timedelta64[s]") - delta = dt.timedelta(1) - - check(assert_type(index / delta, "pd.Index[float]"), pd.Index, float) - check(assert_type(index / [delta], "pd.Index[float]"), pd.Index, float) - check(assert_type(index / 1, pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) - check(assert_type(index / [1], pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) - check(assert_type(index // delta, "pd.Index[int]"), pd.Index, np.longlong) - check(assert_type(index // [delta], "pd.Index[int]"), pd.Index, int) - check(assert_type(index // 1, pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) - check(assert_type(index // [1], pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta) - - check(assert_type(delta / index, "pd.Index[float]"), pd.Index, float) - check(assert_type([delta] / index, "pd.Index[float]"), pd.Index, float) - check(assert_type(delta // index, "pd.Index[int]"), pd.Index, np.longlong) - check(assert_type([delta] // index, "pd.Index[int]"), pd.Index, np.signedinteger) - - if TYPE_CHECKING_INVALID_USAGE: - _0 = 1 / index # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - _1 = [1] / index # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - _2 = 1 // index # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - _3 = [1] // index # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - - def test_datetime_operators_builtin() -> None: time = pd.date_range("2022-01-01", "2022-01-31", freq="D") check(assert_type(time + dt.timedelta(0), pd.DatetimeIndex), pd.DatetimeIndex) diff --git a/tests/scalars/test_scalars.py b/tests/scalars/test_scalars.py index d4cafa390..61e3fd684 100644 --- a/tests/scalars/test_scalars.py +++ b/tests/scalars/test_scalars.py @@ -653,9 +653,6 @@ def test_timedelta_add_sub() -> None: def test_timedelta_mul_div() -> None: td = pd.Timedelta("1 day") - i_idx = pd.Index([1, 2, 3], dtype=int) - f_idx = pd.Index([1.2, 2.2, 3.4], dtype=float) - np_intp_arr: npt.NDArray[np.integer] = np.array([1, 2, 3]) np_float_arr: npt.NDArray[np.floating] = np.array([1.2, 2.2, 3.4]) @@ -663,11 +660,6 @@ def test_timedelta_mul_div() -> None: md_float = 3.5 md_ndarray_intp = np_intp_arr md_ndarray_float = np_float_arr - mp_series_int = pd.Series([1, 2, 3], dtype=int) - md_series_float = pd.Series([1.2, 2.2, 3.4], dtype=float) - md_int64_index = i_idx - md_float_index = f_idx - md_timedelta_series = pd.Series(pd.timedelta_range("1 day", periods=3)) check(assert_type(td * md_int, pd.Timedelta), pd.Timedelta) check(assert_type(td * md_float, pd.Timedelta), pd.Timedelta) @@ -709,23 +701,6 @@ def test_timedelta_mul_div() -> None: np.ndarray, np.timedelta64, ) - 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[int]"), - pd.Series, - np.longlong, - ) check(assert_type(pd.NaT // td, float), float) # Note: None of the reverse floordiv work @@ -736,10 +711,6 @@ def test_timedelta_mul_div() -> None: _01 = md_float // td # type: ignore[operator] # pyright: ignore[reportOperatorIssue] _02 = md_ndarray_intp // td # type: ignore[operator] # pyright: ignore[reportOperatorIssue] _03 = md_ndarray_float // td # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - _04 = mp_series_int // td # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - _05 = md_series_float // td # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - _06 = md_int64_index // td # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - _07 = md_float_index // td # type: ignore[operator] # pyright: ignore[reportOperatorIssue] check(assert_type(td / td, float), float) check(assert_type(td / pd.NaT, float), float) diff --git a/tests/series/arithmetic/float/test_truediv.py b/tests/series/arithmetic/float/test_truediv.py index 18d38e661..9b330fce8 100644 --- a/tests/series/arithmetic/float/test_truediv.py +++ b/tests/series/arithmetic/float/test_truediv.py @@ -114,7 +114,7 @@ def test_truediv_py_sequence(left: "pd.Series[float]") -> None: check(assert_type(c / left, "pd.Series[complex]"), pd.Series, np.complexfloating) if TYPE_CHECKING_INVALID_USAGE: _14 = s / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - check(assert_type(d / left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(d / left, "pd.Series[pd.Timedelta]"), pd.Series, timedelta) 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) diff --git a/tests/series/arithmetic/int/test_truediv.py b/tests/series/arithmetic/int/test_truediv.py index 52c3f66a0..1cda6bdb9 100644 --- a/tests/series/arithmetic/int/test_truediv.py +++ b/tests/series/arithmetic/int/test_truediv.py @@ -2,12 +2,16 @@ datetime, timedelta, ) +from typing import Any import numpy as np from numpy import typing as npt # noqa: F401 import pandas as pd import pytest -from typing_extensions import assert_type +from typing_extensions import ( + Never, + assert_type, +) from tests import ( TYPE_CHECKING_INVALID_USAGE, @@ -93,16 +97,24 @@ def test_truediv_py_scalar(left: "pd.Series[int]") -> None: def test_truediv_py_sequence(left: "pd.Series[int]") -> 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] + s = [datetime(2025, 10, 27 + d) for d in range(3)] + d = [timedelta(seconds=s) for s in range(3)] 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) + if TYPE_CHECKING_INVALID_USAGE: + _04 = left / s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left / d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] 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) + if TYPE_CHECKING_INVALID_USAGE: + _14 = s / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d / left, "pd.Series[pd.Timedelta]"), pd.Series, timedelta) 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) @@ -112,11 +124,17 @@ def test_truediv_py_sequence(left: "pd.Series[int]") -> None: pd.Series, np.complexfloating, ) + if TYPE_CHECKING_INVALID_USAGE: + left.truediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.truediv(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] 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) + if TYPE_CHECKING_INVALID_USAGE: + left.div(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.div(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] 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) @@ -126,6 +144,13 @@ def test_truediv_py_sequence(left: "pd.Series[int]") -> None: pd.Series, np.complexfloating, ) + if TYPE_CHECKING_INVALID_USAGE: + left.rtruediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left.rtruediv(d), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) 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) @@ -133,6 +158,9 @@ def test_truediv_py_sequence(left: "pd.Series[int]") -> None: check( assert_type(left.rdiv(c), "pd.Series[complex]"), pd.Series, np.complexfloating ) + if TYPE_CHECKING_INVALID_USAGE: + left.rdiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rdiv(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) def test_truediv_numpy_array(left: "pd.Series[int]") -> None: @@ -141,11 +169,18 @@ def test_truediv_numpy_array(left: "pd.Series[int]") -> None: 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) + s = np.array( + [np.datetime64(f"2025-10-{d:02d}") for d in (28, 29, 30)], np.datetime64 + ) + d = np.array([np.timedelta64(s + 1, "s") for s in range(3)], np.timedelta64) 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) + if TYPE_CHECKING_INVALID_USAGE: + assert_type(left / s, Never) + assert_type(left / d, Never) # `numpy` typing gives the corresponding `ndarray`s in the static type # checking, where our `__rtruediv__` cannot override. At runtime, they return @@ -158,6 +193,9 @@ def test_truediv_numpy_array(left: "pd.Series[int]") -> None: pd.Series, np.complexfloating, ) + if TYPE_CHECKING_INVALID_USAGE: + assert_type(s / left, Any) + check(assert_type(d / left, "npt.NDArray[np.float64]"), pd.Series, pd.Timedelta) 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) @@ -167,11 +205,17 @@ def test_truediv_numpy_array(left: "pd.Series[int]") -> None: pd.Series, np.complexfloating, ) + if TYPE_CHECKING_INVALID_USAGE: + left.truediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.truediv(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] 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) + if TYPE_CHECKING_INVALID_USAGE: + left.div(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.div(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] 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) @@ -181,6 +225,13 @@ def test_truediv_numpy_array(left: "pd.Series[int]") -> None: pd.Series, np.complexfloating, ) + if TYPE_CHECKING_INVALID_USAGE: + left.rtruediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left.rtruediv(d), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) 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) @@ -188,6 +239,13 @@ def test_truediv_numpy_array(left: "pd.Series[int]") -> None: check( assert_type(left.rdiv(c), "pd.Series[complex]"), pd.Series, np.complexfloating ) + if TYPE_CHECKING_INVALID_USAGE: + left.rdiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left.rdiv(d), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) def test_truediv_pd_scalar(left: "pd.Series[int]") -> None: @@ -229,16 +287,24 @@ def test_truediv_pd_index(left: "pd.Series[int]") -> None: i = pd.Index([2, 3, 5]) f = pd.Index([1.0, 2.0, 3.0]) c = pd.Index([1.1j, 2.2j, 4.1j]) + s = pd.Index([datetime(2025, 10, d) for d in (28, 29, 30)]) + d = pd.Index([timedelta(seconds=s + 1) for s in range(3)]) 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) + if TYPE_CHECKING_INVALID_USAGE: + _04 = left / s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left / d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] 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) + if TYPE_CHECKING_INVALID_USAGE: + _14 = s / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d / left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) 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) @@ -248,11 +314,17 @@ def test_truediv_pd_index(left: "pd.Series[int]") -> None: pd.Series, np.complexfloating, ) + if TYPE_CHECKING_INVALID_USAGE: + left.truediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.truediv(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] 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) + if TYPE_CHECKING_INVALID_USAGE: + left.div(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.div(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] 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) @@ -262,6 +334,13 @@ def test_truediv_pd_index(left: "pd.Series[int]") -> None: pd.Series, np.complexfloating, ) + if TYPE_CHECKING_INVALID_USAGE: + left.rtruediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left.rtruediv(d), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) 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) @@ -269,6 +348,9 @@ def test_truediv_pd_index(left: "pd.Series[int]") -> None: check( assert_type(left.rdiv(c), "pd.Series[complex]"), pd.Series, np.complexfloating ) + if TYPE_CHECKING_INVALID_USAGE: + left.rdiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rdiv(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) def test_truediv_pd_series(left: "pd.Series[int]") -> None: @@ -277,16 +359,24 @@ def test_truediv_pd_series(left: "pd.Series[int]") -> None: i = pd.Series([2, 3, 5]) f = pd.Series([1.0, 2.0, 3.0]) c = pd.Series([1.1j, 2.2j, 4.1j]) + s = pd.Series([datetime(2025, 10, d) for d in (28, 29, 30)]) + d = pd.Series([timedelta(seconds=s + 1) for s in range(3)]) 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) + if TYPE_CHECKING_INVALID_USAGE: + _04 = left / s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + _05 = left / d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] 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) + if TYPE_CHECKING_INVALID_USAGE: + _14 = s / left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(d / left, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) 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) @@ -296,11 +386,17 @@ def test_truediv_pd_series(left: "pd.Series[int]") -> None: pd.Series, np.complexfloating, ) + if TYPE_CHECKING_INVALID_USAGE: + left.truediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.truediv(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] 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) + if TYPE_CHECKING_INVALID_USAGE: + left.div(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left.div(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] 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) @@ -310,6 +406,13 @@ def test_truediv_pd_series(left: "pd.Series[int]") -> None: pd.Series, np.complexfloating, ) + if TYPE_CHECKING_INVALID_USAGE: + left.rtruediv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check( + assert_type(left.rtruediv(d), "pd.Series[pd.Timedelta]"), + pd.Series, + pd.Timedelta, + ) 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) @@ -317,3 +420,6 @@ def test_truediv_pd_series(left: "pd.Series[int]") -> None: check( assert_type(left.rdiv(c), "pd.Series[complex]"), pd.Series, np.complexfloating ) + if TYPE_CHECKING_INVALID_USAGE: + left.rdiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.rdiv(d), "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) diff --git a/tests/series/arithmetic/test_floordiv.py b/tests/series/arithmetic/test_floordiv.py index 12cc69322..6f563bc14 100644 --- a/tests/series/arithmetic/test_floordiv.py +++ b/tests/series/arithmetic/test_floordiv.py @@ -30,33 +30,33 @@ def test_floordiv_py_scalar(left_i: pd.Series) -> None: b, i, f, c = True, 1, 1.0, 1j s, d = datetime(2025, 9, 27), timedelta(seconds=1) - check(assert_type(left_i // b, "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i // i, "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i // f, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left_i // b, pd.Series), pd.Series, np.integer) + check(assert_type(left_i // i, pd.Series), pd.Series, np.integer) + check(assert_type(left_i // f, pd.Series), pd.Series, np.floating) if TYPE_CHECKING_INVALID_USAGE: _03 = left_i // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] _04 = left_i // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] _05 = left_i // d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - check(assert_type(b // left_i, "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(i // left_i, "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(f // left_i, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(b // left_i, pd.Series), pd.Series, np.integer) + check(assert_type(i // left_i, pd.Series), pd.Series, np.integer) + check(assert_type(f // left_i, pd.Series), pd.Series, np.floating) if TYPE_CHECKING_INVALID_USAGE: _13 = c // left_i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] _14 = s // left_i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] check(assert_type(d // left_i, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) - check(assert_type(left_i.floordiv(b), "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i.floordiv(i), "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i.floordiv(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left_i.floordiv(b), pd.Series), pd.Series, np.integer) + check(assert_type(left_i.floordiv(i), pd.Series), pd.Series, np.integer) + check(assert_type(left_i.floordiv(f), pd.Series), pd.Series, np.floating) if TYPE_CHECKING_INVALID_USAGE: - left_i.floordiv(c) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] - left_i.floordiv(s) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] - left_i.floordiv(d) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] + left_i.floordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left_i.floordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + left_i.floordiv(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] - check(assert_type(left_i.rfloordiv(b), "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i.rfloordiv(i), "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i.rfloordiv(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left_i.rfloordiv(b), pd.Series), pd.Series, np.integer) + check(assert_type(left_i.rfloordiv(i), pd.Series), pd.Series, np.integer) + check(assert_type(left_i.rfloordiv(f), pd.Series), pd.Series, np.floating) if TYPE_CHECKING_INVALID_USAGE: left_i.rfloordiv(c) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] left_i.rfloordiv(s) # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] @@ -73,33 +73,33 @@ def test_floordiv_py_sequence(left_i: pd.Series) -> None: s = [datetime(2025, 10, 27 + d) for d in range(3)] d = [timedelta(seconds=s) for s in range(3)] - check(assert_type(left_i // b, "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i // i, "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i // f, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left_i // b, pd.Series), pd.Series, np.integer) + check(assert_type(left_i // i, pd.Series), pd.Series, np.integer) + check(assert_type(left_i // f, pd.Series), pd.Series, np.floating) if TYPE_CHECKING_INVALID_USAGE: _03 = left_i // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] _04 = left_i // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] _05 = left_i // d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - check(assert_type(b // left_i, "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(i // left_i, "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(f // left_i, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(b // left_i, pd.Series), pd.Series, np.integer) + check(assert_type(i // left_i, pd.Series), pd.Series, np.integer) + check(assert_type(f // left_i, pd.Series), pd.Series, np.floating) if TYPE_CHECKING_INVALID_USAGE: _13 = c // left_i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] _14 = s // left_i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] _15 = d // left_i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - check(assert_type(left_i.floordiv(b), "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i.floordiv(i), "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i.floordiv(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left_i.floordiv(b), pd.Series), pd.Series, np.integer) + check(assert_type(left_i.floordiv(i), pd.Series), pd.Series, np.integer) + check(assert_type(left_i.floordiv(f), pd.Series), pd.Series, np.floating) if TYPE_CHECKING_INVALID_USAGE: left_i.floordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] left_i.floordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] left_i.floordiv(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] - check(assert_type(left_i.rfloordiv(b), "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i.rfloordiv(i), "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i.rfloordiv(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left_i.rfloordiv(b), pd.Series), pd.Series, np.integer) + check(assert_type(left_i.rfloordiv(i), pd.Series), pd.Series, np.integer) + check(assert_type(left_i.rfloordiv(f), pd.Series), pd.Series, np.floating) if TYPE_CHECKING_INVALID_USAGE: left_i.rfloordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] left_i.rfloordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] @@ -121,9 +121,9 @@ def test_floordiv_numpy_array(left_i: pd.Series) -> None: ) d = np.array([np.timedelta64(s + 1, "s") for s in range(3)], np.timedelta64) - check(assert_type(left_i // b, "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i // i, "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i // f, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left_i // b, pd.Series), pd.Series, np.integer) + check(assert_type(left_i // i, pd.Series), pd.Series, np.integer) + check(assert_type(left_i // f, pd.Series), pd.Series, np.floating) if TYPE_CHECKING_INVALID_USAGE: assert_type(left_i // c, Never) assert_type(left_i // s, Never) @@ -138,19 +138,19 @@ def test_floordiv_numpy_array(left_i: pd.Series) -> None: if TYPE_CHECKING_INVALID_USAGE: assert_type(c // left_i, Any) assert_type(s // left_i, Any) - assert_type(d // left_i, "np.typing.NDArray[np.int64]") + assert_type(d // left_i, Any) # pyright: ignore[reportAssertTypeFailure] - check(assert_type(left_i.floordiv(b), "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i.floordiv(i), "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i.floordiv(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left_i.floordiv(b), pd.Series), pd.Series, np.integer) + check(assert_type(left_i.floordiv(i), pd.Series), pd.Series, np.integer) + check(assert_type(left_i.floordiv(f), pd.Series), pd.Series, np.floating) if TYPE_CHECKING_INVALID_USAGE: left_i.floordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] left_i.floordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] - left_i.floordiv(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + # left_i.floordiv(d) # This invalid one cannot be detected by static type checking - check(assert_type(left_i.rfloordiv(b), "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i.rfloordiv(i), "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i.rfloordiv(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left_i.rfloordiv(b), pd.Series), pd.Series, np.integer) + check(assert_type(left_i.rfloordiv(i), pd.Series), pd.Series, np.integer) + check(assert_type(left_i.rfloordiv(f), pd.Series), pd.Series, np.floating) if TYPE_CHECKING_INVALID_USAGE: left_i.rfloordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] left_i.rfloordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] @@ -170,33 +170,33 @@ def test_floordiv_pd_index(left_i: pd.Series) -> None: s = pd.Index([datetime(2025, 10, d) for d in (27, 28, 29)]) d = pd.Index([timedelta(seconds=s + 1) for s in range(3)]) - check(assert_type(left_i // b, "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i // i, "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i // f, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left_i // b, pd.Series), pd.Series, np.integer) + check(assert_type(left_i // i, pd.Series), pd.Series, np.integer) + check(assert_type(left_i // f, pd.Series), pd.Series, np.floating) if TYPE_CHECKING_INVALID_USAGE: _03 = left_i // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] _04 = left_i // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - _05 = left_i // d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + # _05 = left_i // d # This invalid one cannot be detected by static type checking - check(assert_type(b // left_i, "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(i // left_i, "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(f // left_i, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(b // left_i, pd.Series), pd.Series, np.integer) + check(assert_type(i // left_i, pd.Series), pd.Series, np.integer) + check(assert_type(f // left_i, pd.Series), pd.Series, np.floating) if TYPE_CHECKING_INVALID_USAGE: _13 = c // left_i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] _14 = s // left_i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] check(assert_type(d // left_i, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) - check(assert_type(left_i.floordiv(b), "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i.floordiv(i), "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i.floordiv(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left_i.floordiv(b), pd.Series), pd.Series, np.integer) + check(assert_type(left_i.floordiv(i), pd.Series), pd.Series, np.integer) + check(assert_type(left_i.floordiv(f), pd.Series), pd.Series, np.floating) if TYPE_CHECKING_INVALID_USAGE: left_i.floordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] left_i.floordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] - left_i.floordiv(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + # left_i.floordiv(d) # This invalid one cannot be detected by static type checking - check(assert_type(left_i.rfloordiv(b), "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i.rfloordiv(i), "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i.rfloordiv(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left_i.rfloordiv(b), pd.Series), pd.Series, np.integer) + check(assert_type(left_i.rfloordiv(i), pd.Series), pd.Series, np.integer) + check(assert_type(left_i.rfloordiv(f), pd.Series), pd.Series, np.floating) if TYPE_CHECKING_INVALID_USAGE: left_i.rfloordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] left_i.rfloordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] @@ -216,33 +216,33 @@ def test_floordiv_pd_series(left_i: pd.Series) -> None: s = pd.Series([datetime(2025, 10, d) for d in (27, 28, 29)]) d = pd.Series([timedelta(seconds=s + 1) for s in range(3)]) - check(assert_type(left_i // b, "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i // i, "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i // f, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left_i // b, pd.Series), pd.Series, np.integer) + check(assert_type(left_i // i, pd.Series), pd.Series, np.integer) + check(assert_type(left_i // f, pd.Series), pd.Series, np.floating) if TYPE_CHECKING_INVALID_USAGE: _03 = left_i // c # type: ignore[operator] # pyright: ignore[reportOperatorIssue] _04 = left_i // s # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - _05 = left_i // d # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + # _05 = left_i // d # This invalid one cannot be detected by static type checking - check(assert_type(b // left_i, "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(i // left_i, "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(f // left_i, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(b // left_i, pd.Series), pd.Series, np.integer) + check(assert_type(i // left_i, pd.Series), pd.Series, np.integer) + check(assert_type(f // left_i, pd.Series), pd.Series, np.floating) if TYPE_CHECKING_INVALID_USAGE: _13 = c // left_i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] _14 = s // left_i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] - check(assert_type(d // left_i, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) + check(assert_type(d // left_i, pd.Series), pd.Series, pd.Timedelta) - check(assert_type(left_i.floordiv(b), "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i.floordiv(i), "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i.floordiv(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left_i.floordiv(b), pd.Series), pd.Series, np.integer) + check(assert_type(left_i.floordiv(i), pd.Series), pd.Series, np.integer) + check(assert_type(left_i.floordiv(f), pd.Series), pd.Series, np.floating) if TYPE_CHECKING_INVALID_USAGE: left_i.floordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] left_i.floordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] - left_i.floordiv(d) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + # left_i.floordiv(d) # This invalid one cannot be detected by static type checking - check(assert_type(left_i.rfloordiv(b), "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i.rfloordiv(i), "pd.Series[int]"), pd.Series, np.integer) - check(assert_type(left_i.rfloordiv(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left_i.rfloordiv(b), pd.Series), pd.Series, np.integer) + check(assert_type(left_i.rfloordiv(i), pd.Series), pd.Series, np.integer) + check(assert_type(left_i.rfloordiv(f), pd.Series), pd.Series, np.floating) if TYPE_CHECKING_INVALID_USAGE: left_i.rfloordiv(c) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] left_i.rfloordiv(s) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] diff --git a/tests/series/arithmetic/timedelta/test_truediv.py b/tests/series/arithmetic/timedelta/test_truediv.py index da7fad64f..724a17c8e 100644 --- a/tests/series/arithmetic/timedelta/test_truediv.py +++ b/tests/series/arithmetic/timedelta/test_truediv.py @@ -7,6 +7,7 @@ import numpy as np from numpy import typing as npt # noqa: F401 import pandas as pd +import pytest from typing_extensions import ( Never, assert_type, @@ -17,10 +18,15 @@ check, ) -left = pd.Series([pd.Timedelta(1, "s")]) # left operand +@pytest.fixture +def left() -> "pd.Series[pd.Timedelta]": + """Left operand""" + lo = pd.Series([pd.Timedelta(1, "s")]) + return check(assert_type(lo, "pd.Series[pd.Timedelta]"), pd.Series, pd.Timedelta) -def test_truediv_py_scalar() -> None: + +def test_truediv_py_scalar(left: "pd.Series[pd.Timedelta]") -> 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) @@ -81,7 +87,7 @@ def test_truediv_py_scalar() -> None: check(assert_type(left.rdiv(d), "pd.Series[float]"), pd.Series, np.floating) -def test_truediv_py_sequence() -> None: +def test_truediv_py_sequence(left: "pd.Series[pd.Timedelta]") -> 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)] @@ -142,7 +148,7 @@ def test_truediv_py_sequence() -> None: check(assert_type(left.rdiv(d), "pd.Series[float]"), pd.Series, np.floating) -def test_truediv_numpy_array() -> None: +def test_truediv_numpy_array(left: "pd.Series[pd.Timedelta]") -> None: """Test pd.Series[pd.Timedelta] / numpy arrays""" b = np.array([True], np.bool_) i = np.array([2], np.int64) @@ -210,7 +216,7 @@ def test_truediv_numpy_array() -> None: check(assert_type(left.rdiv(d), "pd.Series[float]"), pd.Series, np.floating) -def test_truediv_pd_scalar() -> None: +def test_truediv_pd_scalar(left: "pd.Series[pd.Timedelta]") -> None: """Test pd.Series[pd.Timedelta] / pandas scalars""" s, d = pd.Timestamp(2025, 9, 24), pd.Timedelta(seconds=1) @@ -239,7 +245,7 @@ def test_truediv_pd_scalar() -> None: check(assert_type(left.rdiv(d), "pd.Series[float]"), pd.Series, np.floating) -def test_truediv_pd_index() -> None: +def test_truediv_pd_index(left: "pd.Series[pd.Timedelta]") -> None: """Test pd.Series[pd.Timedelta] / pandas Indexes""" b = pd.Index([True]) i = pd.Index([2]) @@ -303,7 +309,7 @@ def test_truediv_pd_index() -> None: check(assert_type(left.rdiv(d), "pd.Series[float]"), pd.Series, np.floating) -def test_truediv_pd_series() -> None: +def test_truediv_pd_series(left: "pd.Series[pd.Timedelta]") -> None: """Test pd.Series[pd.Timedelta] / pandas Series""" b = pd.Series([True]) i = pd.Series([2]) diff --git a/tests/series/test_series.py b/tests/series/test_series.py index 73bc51bb5..474649999 100644 --- a/tests/series/test_series.py +++ b/tests/series/test_series.py @@ -824,7 +824,6 @@ def test_types_element_wise_arithmetic() -> None: assert_type(s.div(s2, fill_value=0), "pd.Series[float]"), pd.Series, np.float64 ) - _res_floordiv: pd.Series = s // s2 _res_floordiv2: pd.Series = s.floordiv(s2, fill_value=0) _res_mod: pd.Series = s % s2 @@ -854,7 +853,6 @@ def test_types_scalar_arithmetic() -> None: assert_type(s.div(2, fill_value=0), "pd.Series[float]"), pd.Series, np.floating ) - _res_floordiv: pd.Series = s // 2 _res_floordiv2: pd.Series = s.floordiv(2, fill_value=0) _res_mod: pd.Series = s % 2 diff --git a/tests/test_natype.py b/tests/test_natype.py index f9bc17162..7a524bc37 100644 --- a/tests/test_natype.py +++ b/tests/test_natype.py @@ -116,6 +116,7 @@ def test_arithmetic() -> None: # https://github.com/pandas-dev/pandas-stubs/issues/1347 # check( # assert_type(divmod(idx_int, na), tuple[pd.Index, pd.Index]), + # tuple, # ) check(assert_type(divmod(1, na), tuple[NAType, NAType]), tuple) From 32bf36c6e33dc092311fb05928b63fff1ec5aff6 Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Wed, 29 Oct 2025 14:10:00 +0100 Subject: [PATCH 6/9] pyright --- pandas-stubs/core/indexes/range.pyi | 15 +++++++-------- tests/indexes/test_indexes.py | 13 +++++-------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/pandas-stubs/core/indexes/range.pyi b/pandas-stubs/core/indexes/range.pyi index 8194dac79..0c66af309 100644 --- a/pandas-stubs/core/indexes/range.pyi +++ b/pandas-stubs/core/indexes/range.pyi @@ -4,7 +4,6 @@ from collections.abc import ( ) from typing import ( Any, - final, overload, ) @@ -66,16 +65,16 @@ class RangeIndex(_IndexSubclassBase[int, np.int64]): ) -> tuple[np_1darray[np.intp], RangeIndex]: ... @property def size(self) -> int: ... - # Base class returns `Self`, but for `RangeIndex` that's not true. - def __floordiv__( # type: ignore[override] - self, other: float | Sequence[float] | Index[int] | Index[float] - ) -> Index[int]: ... def all(self, *args: Any, **kwargs: Any) -> bool: ... def any(self, *args: Any, **kwargs: Any) -> bool: ... - @final + @overload + def union( # type: ignore[override] + self, other: Sequence[int] | Index[int] | Self, sort: bool | None = None + ) -> Index[int] | Self: ... + @overload def union( # type: ignore[override] - self, other: list[HashableT] | Index, sort: bool | None = None - ) -> Index | Index[int] | RangeIndex: ... + self, other: Sequence[HashableT] | Index, sort: bool | None = None + ) -> Index: ... @overload # type: ignore[override] # pyrefly: ignore # bad-override def __getitem__( diff --git a/tests/indexes/test_indexes.py b/tests/indexes/test_indexes.py index 486bb82ad..13aada23e 100644 --- a/tests/indexes/test_indexes.py +++ b/tests/indexes/test_indexes.py @@ -5,7 +5,6 @@ from typing import ( TYPE_CHECKING, Any, - Union, cast, ) @@ -269,23 +268,21 @@ def test_range_index_union() -> None: check( assert_type( pd.RangeIndex(0, 10).union(pd.RangeIndex(10, 20)), - Union[pd.Index, "pd.Index[int]", pd.RangeIndex], + "pd.Index[int] | pd.RangeIndex", ), pd.RangeIndex, ) check( assert_type( - pd.RangeIndex(0, 10).union([11, 12, 13]), - Union[pd.Index, "pd.Index[int]", pd.RangeIndex], + pd.RangeIndex(0, 10).union([11, 12, 13]), "pd.Index[int] | pd.RangeIndex" ), pd.Index, + int, ) check( - assert_type( - pd.RangeIndex(0, 10).union(["a", "b", "c"]), - Union[pd.Index, "pd.Index[int]", pd.RangeIndex], - ), + assert_type(pd.RangeIndex(0, 10).union(["a", "b", "c"]), pd.Index), pd.Index, + str, ) From 7f7cab4e942644a17713e9eada01a667d37de36f Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Wed, 29 Oct 2025 14:15:11 +0100 Subject: [PATCH 7/9] mypy --- pandas-stubs/core/indexes/range.pyi | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pandas-stubs/core/indexes/range.pyi b/pandas-stubs/core/indexes/range.pyi index 0c66af309..ce0b4e613 100644 --- a/pandas-stubs/core/indexes/range.pyi +++ b/pandas-stubs/core/indexes/range.pyi @@ -67,16 +67,15 @@ class RangeIndex(_IndexSubclassBase[int, np.int64]): def size(self) -> int: ... def all(self, *args: Any, **kwargs: Any) -> bool: ... def any(self, *args: Any, **kwargs: Any) -> bool: ... - @overload - def union( # type: ignore[override] + @overload # type: ignore[override] + def union( self, other: Sequence[int] | Index[int] | Self, sort: bool | None = None ) -> Index[int] | Self: ... @overload - def union( # type: ignore[override] + def union( self, other: Sequence[HashableT] | Index, sort: bool | None = None ) -> Index: ... - @overload # type: ignore[override] - # pyrefly: ignore # bad-override + @overload # type: ignore[override] # pyrefly: ignore[bad-override] def __getitem__( self, idx: slice | np_ndarray_anyint | Sequence[int] | Index | MaskType, From 5b997b686ef48d66259c36e7f088b1064a566131 Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Wed, 29 Oct 2025 14:20:24 +0100 Subject: [PATCH 8/9] pytest --- tests/indexes/test_indexes.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/indexes/test_indexes.py b/tests/indexes/test_indexes.py index 13aada23e..0b5cb6fc1 100644 --- a/tests/indexes/test_indexes.py +++ b/tests/indexes/test_indexes.py @@ -279,11 +279,7 @@ def test_range_index_union() -> None: pd.Index, int, ) - check( - assert_type(pd.RangeIndex(0, 10).union(["a", "b", "c"]), pd.Index), - pd.Index, - str, - ) + check(assert_type(pd.RangeIndex(0, 10).union(["a", "b", "c"]), pd.Index), pd.Index) def test_index_union_sort() -> None: From dca5fa2316b80430cfaa2934c944f3588e6e5fce Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Wed, 29 Oct 2025 15:07:29 +0100 Subject: [PATCH 9/9] pyrefly --- pandas-stubs/_typing.pyi | 3 +-- pandas-stubs/core/indexes/range.pyi | 6 +++--- pandas-stubs/core/series.pyi | 15 +++++---------- tests/indexes/test_indexes.py | 2 +- 4 files changed, 10 insertions(+), 16 deletions(-) diff --git a/pandas-stubs/_typing.pyi b/pandas-stubs/_typing.pyi index 5f0277185..8b9ec6264 100644 --- a/pandas-stubs/_typing.pyi +++ b/pandas-stubs/_typing.pyi @@ -1114,8 +1114,7 @@ Incomplete: TypeAlias = Any class Just(Protocol, Generic[T]): @property # type: ignore[override] @override - # pyrefly: ignore # bad-override - def __class__(self, /) -> type[T]: ... + def __class__(self, /) -> type[T]: ... # pyrefly: ignore[bad-override] @__class__.setter @override def __class__(self, t: type[T], /) -> None: ... diff --git a/pandas-stubs/core/indexes/range.pyi b/pandas-stubs/core/indexes/range.pyi index ce0b4e613..8ffb2e0fa 100644 --- a/pandas-stubs/core/indexes/range.pyi +++ b/pandas-stubs/core/indexes/range.pyi @@ -68,15 +68,15 @@ class RangeIndex(_IndexSubclassBase[int, np.int64]): def all(self, *args: Any, **kwargs: Any) -> bool: ... def any(self, *args: Any, **kwargs: Any) -> bool: ... @overload # type: ignore[override] - def union( + def union( # pyrefly: ignore[bad-override] self, other: Sequence[int] | Index[int] | Self, sort: bool | None = None ) -> Index[int] | Self: ... @overload def union( self, other: Sequence[HashableT] | Index, sort: bool | None = None ) -> Index: ... - @overload # type: ignore[override] # pyrefly: ignore[bad-override] - def __getitem__( + @overload # type: ignore[override] + def __getitem__( # pyrefly: ignore[bad-override] self, idx: slice | np_ndarray_anyint | Sequence[int] | Index | MaskType, ) -> Index: ... diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index 9d99f09cb..7955ba33a 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -2966,16 +2966,14 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): def __pow__(self, other: num | ListLike | Series[S1]) -> Series[S1]: ... # ignore needed for mypy as we want different results based on the arguments @overload # type: ignore[override] - # pyrefly: ignore # bad-override - def __or__( # pyright: ignore[reportOverlappingOverload] + def __or__( # pyright: ignore[reportOverlappingOverload] # pyrefly: ignore[bad-override] self, other: bool | list[int] | MaskType ) -> Series[bool]: ... @overload def __or__(self, other: int | np_ndarray_anyint | Series[int]) -> Series[int]: ... # ignore needed for mypy as we want different results based on the arguments @overload # type: ignore[override] - # pyrefly: ignore # bad-override - def __rand__( # pyright: ignore[reportOverlappingOverload] + def __rand__( # pyright: ignore[reportOverlappingOverload] # pyrefly: ignore[bad-override] self, other: bool | MaskType | list[int] ) -> Series[bool]: ... @overload @@ -2985,16 +2983,14 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): def __rpow__(self, other: num | ListLike | Series[S1]) -> Series[S1]: ... # ignore needed for mypy as we want different results based on the arguments @overload # type: ignore[override] - # pyrefly: ignore # bad-override - def __ror__( # pyright: ignore[reportOverlappingOverload] + def __ror__( # pyright: ignore[reportOverlappingOverload] # pyrefly: ignore[bad-override] self, other: bool | MaskType | list[int] ) -> Series[bool]: ... @overload def __ror__(self, other: int | np_ndarray_anyint | Series[int]) -> Series[int]: ... # ignore needed for mypy as we want different results based on the arguments @overload # type: ignore[override] - # pyrefly: ignore # bad-override - def __rxor__( # pyright: ignore[reportOverlappingOverload] + def __rxor__( # pyright: ignore[reportOverlappingOverload] # pyrefly: ignore[bad-override] self, other: bool | MaskType | list[int] ) -> Series[bool]: ... @overload @@ -4140,8 +4136,7 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): rdiv = rtruediv # ignore needed for mypy as we want different results based on the arguments @overload # type: ignore[override] - # pyrefly: ignore # bad-override - def __xor__( # pyright: ignore[reportOverlappingOverload] + def __xor__( # pyright: ignore[reportOverlappingOverload] # pyrefly: ignore[bad-override] self, other: bool | MaskType | list[int] ) -> Series[bool]: ... @overload diff --git a/tests/indexes/test_indexes.py b/tests/indexes/test_indexes.py index 0b5cb6fc1..92df8721f 100644 --- a/tests/indexes/test_indexes.py +++ b/tests/indexes/test_indexes.py @@ -277,7 +277,7 @@ def test_range_index_union() -> None: pd.RangeIndex(0, 10).union([11, 12, 13]), "pd.Index[int] | pd.RangeIndex" ), pd.Index, - int, + np.integer, ) check(assert_type(pd.RangeIndex(0, 10).union(["a", "b", "c"]), pd.Index), pd.Index)