diff --git a/pandas-stubs/_typing.pyi b/pandas-stubs/_typing.pyi index 0f0d0f30..95e18435 100644 --- a/pandas-stubs/_typing.pyi +++ b/pandas-stubs/_typing.pyi @@ -845,6 +845,8 @@ MaskType: TypeAlias = Series[bool] | np_ndarray_bool | list[bool] # Scratch types for generics +T_INT = TypeVar("T_INT", bound=int) +T_COMPLEX = TypeVar("T_COMPLEX", bound=complex) SeriesDType: TypeAlias = ( str | bytes diff --git a/pandas-stubs/core/arraylike.pyi b/pandas-stubs/core/arraylike.pyi index 8eaaf5e1..ac981e29 100644 --- a/pandas-stubs/core/arraylike.pyi +++ b/pandas-stubs/core/arraylike.pyi @@ -19,8 +19,6 @@ class OpsMixin: def __rxor__(self, other: Any) -> Self: ... # ------------------------------------------------------------- # Arithmetic Methods - def __add__(self, other: Any) -> Self: ... - def __radd__(self, other: Any) -> Self: ... def __sub__(self, other: Any) -> Self: ... def __rsub__(self, other: Any) -> Self: ... def __mul__(self, other: Any) -> Self: ... diff --git a/pandas-stubs/core/frame.pyi b/pandas-stubs/core/frame.pyi index 10bff7b2..ae4c6a83 100644 --- a/pandas-stubs/core/frame.pyi +++ b/pandas-stubs/core/frame.pyi @@ -1772,6 +1772,7 @@ class DataFrame(NDFrame, OpsMixin, _GetItemHack): # methods @final def abs(self) -> Self: ... + def __add__(self, other: Any) -> Self: ... def add( self, other: num | ListLike | DataFrame, @@ -1779,6 +1780,14 @@ class DataFrame(NDFrame, OpsMixin, _GetItemHack): level: Level | None = None, fill_value: float | None = None, ) -> Self: ... + def __radd__(self, other: Any) -> Self: ... + def radd( + self, + other, + axis: Axis = "columns", + level: Level | None = None, + fill_value: float | None = None, + ) -> Self: ... @final def add_prefix(self, prefix: _str, axis: Axis | None = None) -> Self: ... @final @@ -2222,13 +2231,6 @@ class DataFrame(NDFrame, OpsMixin, _GetItemHack): min_count: int = 0, **kwargs: Any, ) -> Series: ... - def radd( - self, - other, - axis: Axis = "columns", - level: Level | None = None, - fill_value: float | None = None, - ) -> Self: ... @final def rank( self, diff --git a/pandas-stubs/core/indexes/base.pyi b/pandas-stubs/core/indexes/base.pyi index b193dccf..14a02923 100644 --- a/pandas-stubs/core/indexes/base.pyi +++ b/pandas-stubs/core/indexes/base.pyi @@ -39,12 +39,15 @@ from pandas.core.strings.accessor import StringMethods from typing_extensions import ( Never, Self, + TypeAlias, ) from pandas._libs.interval import _OrderableT from pandas._typing import ( C2, S1, + T_COMPLEX, + T_INT, AnyAll, ArrayLike, AxesData, @@ -70,18 +73,32 @@ from pandas._typing import ( TimestampDtypeArg, np_1darray, np_ndarray_anyint, + np_ndarray_bool, np_ndarray_complex, np_ndarray_float, + np_ndarray_str, type_t, ) class InvalidIndexError(Exception): ... +_ListLike: TypeAlias = ArrayLike | dict[_str, np.ndarray] | SequenceNotStr[S1] + class Index(IndexOpsMixin[S1]): __hash__: ClassVar[None] # type: ignore[assignment] # overloads with additional dtypes @overload def __new__( # pyright: ignore[reportOverlappingOverload] + cls, + data: Sequence[bool | np.bool_] | IndexOpsMixin[bool] | np_ndarray_bool, + *, + dtype: Literal["bool"] | type_t[bool | np.bool_] = ..., + copy: bool = ..., + name: Hashable = ..., + tupleize_cols: bool = ..., + ) -> Index[bool]: ... + @overload + def __new__( cls, data: Sequence[int | np.integer] | IndexOpsMixin[int] | np_ndarray_anyint, *, @@ -460,6 +477,155 @@ class Index(IndexOpsMixin[S1]): def __gt__(self, other: Self | S1) -> np_1darray[np.bool]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] # overwrite inherited methods from OpsMixin @overload + def __add__(self: Index[Never], other: _str) -> Never: ... + @overload + def __add__(self: Index[Never], other: complex | _ListLike | Index) -> Index: ... + @overload + def __add__(self, other: Index[Never]) -> Index: ... + @overload + def __add__( + self: Index[bool], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX], + ) -> Index[T_COMPLEX]: ... + @overload + def __add__(self: Index[bool], other: np_ndarray_bool) -> Index[bool]: ... + @overload + def __add__(self: Index[bool], other: np_ndarray_anyint) -> Index[int]: ... + @overload + def __add__(self: Index[bool], other: np_ndarray_float) -> Index[float]: ... + @overload + def __add__(self: Index[bool], other: np_ndarray_complex) -> Index[complex]: ... + @overload + def __add__( + self: Index[int], + other: ( + bool | Sequence[bool] | np_ndarray_bool | np_ndarray_anyint | Index[bool] + ), + ) -> Index[int]: ... + @overload + def __add__( + self: Index[int], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX], + ) -> Index[T_COMPLEX]: ... + @overload + def __add__(self: Index[int], other: np_ndarray_float) -> Index[float]: ... + @overload + def __add__(self: Index[int], other: np_ndarray_complex) -> Index[complex]: ... + @overload + def __add__( + self: Index[float], + other: ( + int + | Sequence[int] + | np_ndarray_bool + | np_ndarray_anyint + | np_ndarray_float + | Index[T_INT] + ), + ) -> Index[float]: ... + @overload + def __add__( + self: Index[float], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX], + ) -> Index[T_COMPLEX]: ... + @overload + def __add__(self: Index[float], other: np_ndarray_complex) -> Index[complex]: ... + @overload + def __add__( + self: Index[complex], + other: ( + T_COMPLEX + | Sequence[T_COMPLEX] + | np_ndarray_bool + | np_ndarray_anyint + | np_ndarray_float + | np_ndarray_complex + | Index[T_COMPLEX] + ), + ) -> Index[complex]: ... + @overload + def __add__( + self: Index[_str], + other: ( + np_ndarray_bool | np_ndarray_anyint | np_ndarray_float | np_ndarray_complex + ), + ) -> Never: ... + @overload + def __add__( + self: Index[_str], other: _str | Sequence[_str] | np_ndarray_str | Index[_str] + ) -> Index[_str]: ... + @overload + def __radd__(self: Index[Never], other: _str) -> Never: ... + @overload + def __radd__(self: Index[Never], other: complex | _ListLike | Index) -> Index: ... + @overload + def __radd__( + self: Index[bool], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX], + ) -> Index[T_COMPLEX]: ... + @overload + def __radd__(self: Index[bool], other: np_ndarray_bool) -> Index[bool]: ... + @overload + def __radd__(self: Index[bool], other: np_ndarray_anyint) -> Index[int]: ... + @overload + def __radd__(self: Index[bool], other: np_ndarray_float) -> Index[float]: ... + @overload + def __radd__( + self: Index[int], + other: ( + bool | Sequence[bool] | np_ndarray_bool | np_ndarray_anyint | Index[bool] + ), + ) -> Index[int]: ... + @overload + def __radd__( + self: Index[int], other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] + ) -> Index[T_COMPLEX]: ... + @overload + def __radd__(self: Index[int], other: np_ndarray_float) -> Index[float]: ... + @overload + def __radd__( + self: Index[float], + other: ( + int + | Sequence[int] + | np_ndarray_bool + | np_ndarray_anyint + | np_ndarray_float + | Index[T_INT] + ), + ) -> Index[float]: ... + @overload + def __radd__( + self: Index[float], other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] + ) -> Index[T_COMPLEX]: ... + @overload + def __radd__( + self: Index[complex], + other: ( + T_COMPLEX + | Sequence[T_COMPLEX] + | np_ndarray_bool + | np_ndarray_anyint + | np_ndarray_float + | Index[T_COMPLEX] + ), + ) -> Index[complex]: ... + @overload + def __radd__( + self: Index[T_COMPLEX], other: np_ndarray_complex + ) -> Index[complex]: ... + @overload + def __radd__( + self: Index[_str], + other: ( + np_ndarray_bool | np_ndarray_anyint | np_ndarray_float | np_ndarray_complex + ), + ) -> Never: ... + @overload + def __radd__( + self: Index[_str], other: _str | Sequence[_str] | np_ndarray_str | Index[_str] + ) -> Index[_str]: ... + @overload def __mul__( self: Index[int] | Index[float], other: timedelta ) -> TimedeltaIndex: ... diff --git a/pandas-stubs/core/indexes/datetimes.pyi b/pandas-stubs/core/indexes/datetimes.pyi index 29c8f112..3e4e14f6 100644 --- a/pandas-stubs/core/indexes/datetimes.pyi +++ b/pandas-stubs/core/indexes/datetimes.pyi @@ -61,10 +61,10 @@ class DatetimeIndex( def __reduce__(self): ... # various ignores needed for mypy, as we do want to restrict what can be used in # arithmetic for these types - @overload + @overload # type: ignore[override] def __add__(self, other: TimedeltaSeries) -> TimestampSeries: ... @overload - def __add__( + def __add__( # pyright: ignore[reportIncompatibleMethodOverride] self, other: timedelta | Timedelta | TimedeltaIndex | BaseOffset ) -> DatetimeIndex: ... @overload diff --git a/pandas-stubs/core/indexes/timedeltas.pyi b/pandas-stubs/core/indexes/timedeltas.pyi index eb0d073c..309770db 100644 --- a/pandas-stubs/core/indexes/timedeltas.pyi +++ b/pandas-stubs/core/indexes/timedeltas.pyi @@ -49,12 +49,14 @@ class TimedeltaIndex( ) -> Self: ... # various ignores needed for mypy, as we do want to restrict what can be used in # arithmetic for these types - @overload + @overload # type: ignore[override] def __add__(self, other: Period) -> PeriodIndex: ... @overload def __add__(self, other: DatetimeIndex) -> DatetimeIndex: ... @overload - def __add__(self, other: dt.timedelta | Timedelta | Self) -> Self: ... + def __add__( # pyright: ignore[reportIncompatibleMethodOverride] + self, other: dt.timedelta | Timedelta | Self + ) -> Self: ... def __radd__(self, other: dt.datetime | Timestamp | DatetimeIndex) -> DatetimeIndex: ... # type: ignore[override] def __sub__(self, other: dt.timedelta | Timedelta | Self) -> Self: ... def __mul__(self, other: num) -> Self: ... diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index a4e4a675..be005260 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -26,7 +26,6 @@ from typing import ( Generic, Literal, NoReturn, - TypeVar, final, overload, type_check_only, @@ -108,6 +107,8 @@ from pandas._libs.tslibs.offsets import DateOffset from pandas._typing import ( S1, S2, + T_COMPLEX, + T_INT, AggFuncTypeBase, AggFuncTypeDictFrame, AggFuncTypeSeriesToFrame, @@ -198,9 +199,6 @@ from pandas.core.dtypes.dtypes import CategoricalDtype from pandas.plotting import PlotAccessor -_T_INT = TypeVar("_T_INT", bound=int) -_T_COMPLEX = TypeVar("_T_COMPLEX", bound=complex) - class _iLocIndexerSeries(_iLocIndexer, Generic[S1]): # get item @overload @@ -1633,14 +1631,16 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def __add__(self: Series[Never], other: _str) -> Never: ... @overload - def __add__(self: Series[Never], other: complex | _ListLike | Series) -> Series: ... + def __add__( + self: Series[Never], other: complex | _ListLike | Index | Series + ) -> Series: ... @overload - def __add__(self, other: Series[Never]) -> Series: ... + def __add__(self, other: Index[Never] | Series[Never]) -> Series: ... @overload def __add__( self: Series[bool], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], - ) -> Series[_T_COMPLEX]: ... + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], + ) -> Series[T_COMPLEX]: ... @overload def __add__(self: Series[bool], other: np_ndarray_bool) -> Series[bool]: ... @overload @@ -1653,14 +1653,19 @@ class Series(IndexOpsMixin[S1], NDFrame): def __add__( self: Series[int], other: ( - bool | Sequence[bool] | np_ndarray_bool | np_ndarray_anyint | Series[bool] + bool + | Sequence[bool] + | np_ndarray_bool + | np_ndarray_anyint + | Index[bool] + | Series[bool] ), ) -> Series[int]: ... @overload def __add__( self: Series[int], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], - ) -> Series[_T_COMPLEX]: ... + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], + ) -> Series[T_COMPLEX]: ... @overload def __add__(self: Series[int], other: np_ndarray_float) -> Series[float]: ... @overload @@ -1674,27 +1679,29 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_INT] + | Index[T_INT] + | Series[T_INT] ), ) -> Series[float]: ... @overload def __add__( self: Series[float], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], - ) -> Series[_T_COMPLEX]: ... + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], + ) -> Series[T_COMPLEX]: ... @overload def __add__(self: Series[float], other: np_ndarray_complex) -> Series[complex]: ... @overload def __add__( self: Series[complex], other: ( - _T_COMPLEX - | Sequence[_T_COMPLEX] + T_COMPLEX + | Sequence[T_COMPLEX] | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float | np_ndarray_complex - | Series[_T_COMPLEX] + | Index[T_COMPLEX] + | Series[T_COMPLEX] ), ) -> Series[complex]: ... @overload @@ -1706,7 +1713,8 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Never: ... @overload def __add__( - self: Series[_str], other: _str | Sequence[_str] | np_ndarray_str | Series[_str] + self: Series[_str], + other: _str | Sequence[_str] | np_ndarray_str | Index[_str] | Series[_str], ) -> Series[_str]: ... @overload def add( @@ -1719,7 +1727,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def add( self: Series[Never], - other: complex | _ListLike | Series, + other: complex | _ListLike | Index | Series, level: Level | None = None, fill_value: float | None = None, axis: int = 0, @@ -1735,11 +1743,11 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def add( self: Series[bool], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], level: Level | None = None, fill_value: float | None = None, axis: int = 0, - ) -> Series[_T_COMPLEX]: ... + ) -> Series[T_COMPLEX]: ... @overload def add( self: Series[bool], @@ -1776,7 +1784,12 @@ class Series(IndexOpsMixin[S1], NDFrame): def add( self: Series[int], other: ( - bool | Sequence[bool] | np_ndarray_bool | np_ndarray_anyint | Series[bool] + bool + | Sequence[bool] + | np_ndarray_bool + | np_ndarray_anyint + | Index[bool] + | Series[bool] ), level: Level | None = None, fill_value: float | None = None, @@ -1785,11 +1798,11 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def add( self: Series[int], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], level: Level | None = None, fill_value: float | None = None, axis: int = 0, - ) -> Series[_T_COMPLEX]: ... + ) -> Series[T_COMPLEX]: ... @overload def add( self: Series[int], @@ -1815,7 +1828,8 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_INT] + | Index[T_INT] + | Series[T_INT] ), level: Level | None = None, fill_value: float | None = None, @@ -1824,11 +1838,11 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def add( self: Series[float], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], level: Level | None = None, fill_value: float | None = None, axis: int = 0, - ) -> Series[_T_COMPLEX]: ... + ) -> Series[T_COMPLEX]: ... @overload def add( self: Series[float], @@ -1841,13 +1855,14 @@ class Series(IndexOpsMixin[S1], NDFrame): def add( self: Series[complex], other: ( - _T_COMPLEX - | Sequence[_T_COMPLEX] + T_COMPLEX + | Sequence[T_COMPLEX] | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float | np_ndarray_complex - | Series[_T_COMPLEX] + | Index[T_COMPLEX] + | Series[T_COMPLEX] ), level: Level | None = None, fill_value: float | None = None, @@ -1856,22 +1871,22 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def add( self: Series[_str], - other: _str | Sequence[_str] | np_ndarray_str | Series[_str], + other: _str | Sequence[_str] | np_ndarray_str | Index[_str] | Series[_str], level: Level | None = None, fill_value: float | None = None, axis: int = 0, ) -> Series[_str]: ... - @overload # type: ignore[override] + @overload def __radd__(self: Series[Never], other: _str) -> Never: ... @overload def __radd__( - self: Series[Never], other: complex | _ListLike | Series + self: Series[Never], other: complex | _ListLike | Index | Series ) -> Series: ... @overload def __radd__( self: Series[bool], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], - ) -> Series[_T_COMPLEX]: ... + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], + ) -> Series[T_COMPLEX]: ... @overload def __radd__(self: Series[bool], other: np_ndarray_bool) -> Series[bool]: ... @overload @@ -1882,13 +1897,19 @@ class Series(IndexOpsMixin[S1], NDFrame): def __radd__( self: Series[int], other: ( - bool | Sequence[bool] | np_ndarray_bool | np_ndarray_anyint | Series[bool] + bool + | Sequence[bool] + | np_ndarray_bool + | np_ndarray_anyint + | Index[bool] + | Series[bool] ), ) -> Series[int]: ... @overload def __radd__( - self: Series[int], other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX] - ) -> Series[_T_COMPLEX]: ... + self: Series[int], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], + ) -> Series[T_COMPLEX]: ... @overload def __radd__(self: Series[int], other: np_ndarray_float) -> Series[float]: ... @overload @@ -1900,29 +1921,31 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_INT] + | Index[T_INT] + | Series[T_INT] ), ) -> Series[float]: ... @overload def __radd__( self: Series[float], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], - ) -> Series[_T_COMPLEX]: ... + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], + ) -> Series[T_COMPLEX]: ... @overload def __radd__( self: Series[complex], other: ( - _T_COMPLEX - | Sequence[_T_COMPLEX] + T_COMPLEX + | Sequence[T_COMPLEX] | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_COMPLEX] + | Index[T_COMPLEX] + | Series[T_COMPLEX] ), ) -> Series[complex]: ... @overload def __radd__( - self: Series[_T_COMPLEX], other: np_ndarray_complex + self: Series[T_COMPLEX], other: np_ndarray_complex ) -> Series[complex]: ... @overload def __radd__( @@ -1933,7 +1956,8 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Never: ... @overload def __radd__( - self: Series[_str], other: _str | Sequence[_str] | np_ndarray_str | Series[_str] + self: Series[_str], + other: _str | Sequence[_str] | np_ndarray_str | Index[_str] | Series[_str], ) -> Series[_str]: ... @overload def radd( @@ -1946,7 +1970,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def radd( self: Series[Never], - other: complex | _ListLike | Series, + other: complex | _ListLike | Index | Series, level: Level | None = None, fill_value: float | None = None, axis: int = 0, @@ -1962,11 +1986,11 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def radd( self: Series[bool], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], level: Level | None = None, fill_value: float | None = None, axis: int = 0, - ) -> Series[_T_COMPLEX]: ... + ) -> Series[T_COMPLEX]: ... @overload def radd( self: Series[bool], @@ -1995,7 +2019,12 @@ class Series(IndexOpsMixin[S1], NDFrame): def radd( self: Series[int], other: ( - bool | Sequence[bool] | np_ndarray_bool | np_ndarray_anyint | Series[bool] + bool + | Sequence[bool] + | np_ndarray_bool + | np_ndarray_anyint + | Index[bool] + | Series[bool] ), level: Level | None = None, fill_value: float | None = None, @@ -2004,11 +2033,11 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def radd( self: Series[int], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], level: Level | None = None, fill_value: float | None = None, axis: int = 0, - ) -> Series[_T_COMPLEX]: ... + ) -> Series[T_COMPLEX]: ... @overload def radd( self: Series[int], @@ -2026,7 +2055,8 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_INT] + | Index[T_INT] + | Series[T_INT] ), level: Level | None = None, fill_value: float | None = None, @@ -2035,21 +2065,22 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def radd( self: Series[float], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Index[T_COMPLEX] | Series[T_COMPLEX], level: Level | None = None, fill_value: float | None = None, axis: int = 0, - ) -> Series[_T_COMPLEX]: ... + ) -> Series[T_COMPLEX]: ... @overload def radd( self: Series[complex], other: ( - _T_COMPLEX - | Sequence[_T_COMPLEX] + T_COMPLEX + | Sequence[T_COMPLEX] | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_COMPLEX] + | Index[T_COMPLEX] + | Series[T_COMPLEX] ), level: Level | None = None, fill_value: float | None = None, @@ -2057,7 +2088,7 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Series[complex]: ... @overload def radd( - self: Series[_T_COMPLEX], + self: Series[T_COMPLEX], other: np_ndarray_complex, level: Level | None = None, fill_value: float | None = None, @@ -2066,7 +2097,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def radd( self: Series[_str], - other: _str | Sequence[_str] | np_ndarray_str | Series[_str], + other: _str | Sequence[_str] | np_ndarray_str | Index[_str] | Series[_str], level: Level | None = None, fill_value: float | None = None, axis: int = 0, @@ -2101,8 +2132,8 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def __mul__( self: Series[bool], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], - ) -> Series[_T_COMPLEX]: ... + other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], + ) -> Series[T_COMPLEX]: ... @overload def __mul__(self: Series[bool], other: np_ndarray_bool) -> Series[bool]: ... @overload @@ -2119,8 +2150,8 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def __mul__( self: Series[int], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], - ) -> Series[_T_COMPLEX]: ... + other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], + ) -> Series[T_COMPLEX]: ... @overload def __mul__(self: Series[int], other: np_ndarray_float) -> Series[float]: ... @overload @@ -2132,29 +2163,29 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_INT] + | Series[T_INT] ), ) -> Series[float]: ... @overload def __mul__( self: Series[float], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], - ) -> Series[_T_COMPLEX]: ... + other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], + ) -> Series[T_COMPLEX]: ... @overload def __mul__( self: Series[complex], other: ( - _T_COMPLEX - | Sequence[_T_COMPLEX] + T_COMPLEX + | Sequence[T_COMPLEX] | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_COMPLEX] + | Series[T_COMPLEX] ), ) -> Series[complex]: ... @overload def __mul__( - self: Series[_T_COMPLEX], other: np_ndarray_complex + self: Series[T_COMPLEX], other: np_ndarray_complex ) -> Series[complex]: ... @overload def __mul__( @@ -2179,11 +2210,11 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def mul( self: Series[bool], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], level: Level | None = None, fill_value: float | None = None, axis: int = 0, - ) -> Series[_T_COMPLEX]: ... + ) -> Series[T_COMPLEX]: ... @overload def mul( self: Series[bool], @@ -2221,11 +2252,11 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def mul( self: Series[int], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], level: Level | None = None, fill_value: float | None = None, axis: int = 0, - ) -> Series[_T_COMPLEX]: ... + ) -> Series[T_COMPLEX]: ... @overload def mul( self: Series[int], @@ -2243,7 +2274,7 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_INT] + | Series[T_INT] ), level: Level | None = None, fill_value: float | None = None, @@ -2252,21 +2283,21 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def mul( self: Series[float], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], level: Level | None = None, fill_value: float | None = None, axis: int = 0, - ) -> Series[_T_COMPLEX]: ... + ) -> Series[T_COMPLEX]: ... @overload def mul( self: Series[complex], other: ( - _T_COMPLEX - | Sequence[_T_COMPLEX] + T_COMPLEX + | Sequence[T_COMPLEX] | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_COMPLEX] + | Series[T_COMPLEX] ), level: Level | None = None, fill_value: float | None = None, @@ -2274,7 +2305,7 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Series[complex]: ... @overload def mul( - self: Series[_T_COMPLEX], + self: Series[T_COMPLEX], other: np_ndarray_complex, level: Level | None = None, fill_value: float | None = None, @@ -2297,8 +2328,8 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def __rmul__( self: Series[bool], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], - ) -> Series[_T_COMPLEX]: ... + other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], + ) -> Series[T_COMPLEX]: ... @overload def __rmul__(self: Series[bool], other: np_ndarray_bool) -> Series[bool]: ... @overload @@ -2314,8 +2345,8 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Series[int]: ... @overload def __rmul__( - self: Series[int], other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX] - ) -> Series[_T_COMPLEX]: ... + self: Series[int], other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX] + ) -> Series[T_COMPLEX]: ... @overload def __rmul__(self: Series[int], other: np_ndarray_float) -> Series[float]: ... @overload @@ -2327,29 +2358,29 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_INT] + | Series[T_INT] ), ) -> Series[float]: ... @overload def __rmul__( self: Series[float], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], - ) -> Series[_T_COMPLEX]: ... + other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], + ) -> Series[T_COMPLEX]: ... @overload def __rmul__( self: Series[complex], other: ( - _T_COMPLEX - | Sequence[_T_COMPLEX] + T_COMPLEX + | Sequence[T_COMPLEX] | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_COMPLEX] + | Series[T_COMPLEX] ), ) -> Series[complex]: ... @overload def __rmul__( - self: Series[_T_COMPLEX], other: np_ndarray_complex + self: Series[T_COMPLEX], other: np_ndarray_complex ) -> Series[complex]: ... @overload def __rmul__( @@ -2374,11 +2405,11 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def rmul( self: Series[bool], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], level: Level | None = None, fill_value: float | None = None, axis: int = 0, - ) -> Series[_T_COMPLEX]: ... + ) -> Series[T_COMPLEX]: ... @overload def rmul( self: Series[bool], @@ -2416,11 +2447,11 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def rmul( self: Series[int], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], level: Level | None = None, fill_value: float | None = None, axis: int = 0, - ) -> Series[_T_COMPLEX]: ... + ) -> Series[T_COMPLEX]: ... @overload def rmul( self: Series[int], @@ -2438,7 +2469,7 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_INT] + | Series[T_INT] ), level: Level | None = None, fill_value: float | None = None, @@ -2447,21 +2478,21 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def rmul( self: Series[float], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], level: Level | None = None, fill_value: float | None = None, axis: int = 0, - ) -> Series[_T_COMPLEX]: ... + ) -> Series[T_COMPLEX]: ... @overload def rmul( self: Series[complex], other: ( - _T_COMPLEX - | Sequence[_T_COMPLEX] + T_COMPLEX + | Sequence[T_COMPLEX] | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_COMPLEX] + | Series[T_COMPLEX] ), level: Level | None = None, fill_value: float | None = None, @@ -2469,7 +2500,7 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Series[complex]: ... @overload def rmul( - self: Series[_T_COMPLEX], + self: Series[T_COMPLEX], other: np_ndarray_complex, level: Level | None = None, fill_value: float | None = None, @@ -2571,17 +2602,17 @@ class Series(IndexOpsMixin[S1], NDFrame): def __sub__( self: Series[complex], other: ( - _T_COMPLEX - | Sequence[_T_COMPLEX] + T_COMPLEX + | Sequence[T_COMPLEX] | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_COMPLEX] + | Series[T_COMPLEX] ), ) -> Series[complex]: ... @overload def __sub__( - self: Series[_T_COMPLEX], + self: Series[T_COMPLEX], other: ( Just[complex] | Sequence[Just[complex]] @@ -2695,12 +2726,12 @@ class Series(IndexOpsMixin[S1], NDFrame): def sub( self: Series[complex], other: ( - _T_COMPLEX - | Sequence[_T_COMPLEX] + T_COMPLEX + | Sequence[T_COMPLEX] | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_COMPLEX] + | Series[T_COMPLEX] ), level: Level | None = None, fill_value: float | None = None, @@ -2708,7 +2739,7 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Series[complex]: ... @overload def sub( - self: Series[_T_COMPLEX], + self: Series[T_COMPLEX], other: ( Just[complex] | Sequence[Just[complex]] @@ -2800,17 +2831,17 @@ class Series(IndexOpsMixin[S1], NDFrame): def __rsub__( self: Series[complex], other: ( - _T_COMPLEX - | Sequence[_T_COMPLEX] + T_COMPLEX + | Sequence[T_COMPLEX] | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_COMPLEX] + | Series[T_COMPLEX] ), ) -> Series[complex]: ... @overload def __rsub__( - self: Series[_T_COMPLEX], + self: Series[T_COMPLEX], other: ( Just[complex] | Sequence[Just[complex]] @@ -2902,12 +2933,12 @@ class Series(IndexOpsMixin[S1], NDFrame): def rsub( self: Series[complex], other: ( - _T_COMPLEX - | Sequence[_T_COMPLEX] + T_COMPLEX + | Sequence[T_COMPLEX] | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_COMPLEX] + | Series[T_COMPLEX] ), level: Level | None = None, fill_value: float | None = None, @@ -2915,7 +2946,7 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Series[complex]: ... @overload def rsub( - self: Series[_T_COMPLEX], + self: Series[T_COMPLEX], other: ( Just[complex] | Sequence[Just[complex]] @@ -2961,14 +2992,14 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_INT] + | Series[T_INT] ), ) -> Series[float]: ... @overload def __truediv__( self: Series[int], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], - ) -> Series[_T_COMPLEX]: ... + other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], + ) -> Series[T_COMPLEX]: ... @overload def __truediv__( self: Series[float], @@ -2978,29 +3009,29 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_INT] + | Series[T_INT] ), ) -> Series[float]: ... @overload def __truediv__( self: Series[float], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], - ) -> Series[_T_COMPLEX]: ... + other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], + ) -> Series[T_COMPLEX]: ... @overload def __truediv__( self: Series[complex], other: ( - _T_COMPLEX - | Sequence[_T_COMPLEX] + T_COMPLEX + | Sequence[T_COMPLEX] | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_COMPLEX] + | Series[T_COMPLEX] ), ) -> Series[complex]: ... @overload def __truediv__( - self: Series[_T_COMPLEX], other: np_ndarray_complex + self: Series[T_COMPLEX], other: np_ndarray_complex ) -> Series[complex]: ... @overload def __truediv__(self, other: Path) -> Series: ... @@ -3053,7 +3084,7 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_INT] + | Series[T_INT] ), level: Level | None = None, fill_value: float | None = None, @@ -3062,11 +3093,11 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def truediv( self: Series[int], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], level: Level | None = None, fill_value: float | None = None, axis: AxisIndex = 0, - ) -> Series[_T_COMPLEX]: ... + ) -> Series[T_COMPLEX]: ... @overload def truediv( self: Series[float], @@ -3076,7 +3107,7 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_INT] + | Series[T_INT] ), level: Level | None = None, fill_value: float | None = None, @@ -3085,21 +3116,21 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def truediv( self: Series[float], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], level: Level | None = None, fill_value: float | None = None, axis: AxisIndex = 0, - ) -> Series[_T_COMPLEX]: ... + ) -> Series[T_COMPLEX]: ... @overload def truediv( self: Series[complex], other: ( - _T_COMPLEX - | Sequence[_T_COMPLEX] + T_COMPLEX + | Sequence[T_COMPLEX] | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_COMPLEX] + | Series[T_COMPLEX] ), level: Level | None = None, fill_value: float | None = None, @@ -3107,7 +3138,7 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Series[complex]: ... @overload def truediv( - self: Series[_T_COMPLEX], + self: Series[T_COMPLEX], other: np_ndarray_complex, level: Level | None = None, fill_value: float | None = None, @@ -3157,13 +3188,13 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_INT] + | Series[T_INT] ), ) -> Series[float]: ... @overload def __rtruediv__( - self: Series[int], other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX] - ) -> Series[_T_COMPLEX]: ... + self: Series[int], other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX] + ) -> Series[T_COMPLEX]: ... @overload def __rtruediv__( self: Series[float], @@ -3173,29 +3204,29 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_INT] + | Series[T_INT] ), ) -> Series[float]: ... @overload def __rtruediv__( self: Series[float], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], - ) -> Series[_T_COMPLEX]: ... + other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], + ) -> Series[T_COMPLEX]: ... @overload def __rtruediv__( self: Series[complex], other: ( - _T_COMPLEX - | Sequence[_T_COMPLEX] + T_COMPLEX + | Sequence[T_COMPLEX] | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_COMPLEX] + | Series[T_COMPLEX] ), ) -> Series[complex]: ... @overload def __rtruediv__( - self: Series[_T_COMPLEX], other: np_ndarray_complex + self: Series[T_COMPLEX], other: np_ndarray_complex ) -> Series[complex]: ... @overload def __rtruediv__(self, other: Path) -> Series: ... @@ -3248,7 +3279,7 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_INT] + | Series[T_INT] ), level: Level | None = None, fill_value: float | None = None, @@ -3257,11 +3288,11 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def rtruediv( self: Series[int], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], level: Level | None = None, fill_value: float | None = None, axis: AxisIndex = 0, - ) -> Series[_T_COMPLEX]: ... + ) -> Series[T_COMPLEX]: ... @overload def rtruediv( self: Series[float], @@ -3271,7 +3302,7 @@ class Series(IndexOpsMixin[S1], NDFrame): | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_INT] + | Series[T_INT] ), level: Level | None = None, fill_value: float | None = None, @@ -3280,21 +3311,21 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def rtruediv( self: Series[float], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + other: T_COMPLEX | Sequence[T_COMPLEX] | Series[T_COMPLEX], level: Level | None = None, fill_value: float | None = None, axis: AxisIndex = 0, - ) -> Series[_T_COMPLEX]: ... + ) -> Series[T_COMPLEX]: ... @overload def rtruediv( self: Series[complex], other: ( - _T_COMPLEX - | Sequence[_T_COMPLEX] + T_COMPLEX + | Sequence[T_COMPLEX] | np_ndarray_bool | np_ndarray_anyint | np_ndarray_float - | Series[_T_COMPLEX] + | Series[T_COMPLEX] ), level: Level | None = None, fill_value: float | None = None, @@ -3302,7 +3333,7 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Series[complex]: ... @overload def rtruediv( - self: Series[_T_COMPLEX], + self: Series[T_COMPLEX], other: np_ndarray_complex, level: Level | None = None, fill_value: float | None = None, diff --git a/tests/indexes/__init__.py b/tests/indexes/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/indexes/arithmetic/__init__.py b/tests/indexes/arithmetic/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/indexes/arithmetic/bool/__init__.py b/tests/indexes/arithmetic/bool/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/indexes/arithmetic/bool/test_add.py b/tests/indexes/arithmetic/bool/test_add.py new file mode 100644 index 00000000..1d826a90 --- /dev/null +++ b/tests/indexes/arithmetic/bool/test_add.py @@ -0,0 +1,83 @@ +import numpy as np +from numpy import typing as npt # noqa: F401 +import pandas as pd +from typing_extensions import assert_type + +from tests import check + +# left operand +left = pd.Index([True, True, False]) + + +def test_add_py_scalar() -> None: + """Test pd.Index[bool] + Python native scalars""" + b, i, f, c = True, 1, 1.0, 1j + + left.__add__(b) + check(assert_type(left + b, "pd.Index[bool]"), pd.Index, np.bool_) + check(assert_type(left + i, "pd.Index[int]"), pd.Index, np.integer) + check(assert_type(left + f, "pd.Index[float]"), pd.Index, np.floating) + check(assert_type(left + c, "pd.Index[complex]"), pd.Index, np.complexfloating) + + check(assert_type(b + left, "pd.Index[bool]"), pd.Index, np.bool_) + check(assert_type(i + left, "pd.Index[int]"), pd.Index, np.integer) + check(assert_type(f + left, "pd.Index[float]"), pd.Index, np.floating) + check(assert_type(c + left, "pd.Index[complex]"), pd.Index, np.complexfloating) + + +def test_add_py_sequence() -> None: + """Test pd.Index[bool] + Python native sequence""" + b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] + + check(assert_type(left + b, "pd.Index[bool]"), pd.Index, np.bool_) + check(assert_type(left + i, "pd.Index[int]"), pd.Index, np.integer) + check(assert_type(left + f, "pd.Index[float]"), pd.Index, np.floating) + check(assert_type(left + c, "pd.Index[complex]"), pd.Index, np.complexfloating) + + check(assert_type(b + left, "pd.Index[bool]"), pd.Index, np.bool_) + check(assert_type(i + left, "pd.Index[int]"), pd.Index, np.integer) + check(assert_type(f + left, "pd.Index[float]"), pd.Index, np.floating) + check(assert_type(c + left, "pd.Index[complex]"), pd.Index, np.complexfloating) + + +def test_add_numpy_array() -> None: + """Test pd.Index[bool] + numpy array""" + 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) + + check(assert_type(left + b, "pd.Index[bool]"), pd.Index, np.bool_) + check(assert_type(left + i, "pd.Index[int]"), pd.Index, np.integer) + check(assert_type(left + f, "pd.Index[float]"), pd.Index, np.floating) + check(assert_type(left + c, "pd.Index[complex]"), pd.Index, np.complexfloating) + + # `numpy` typing gives the corresponding `ndarray`s in the static type + # checking, where our `__radd__` cannot override. At runtime, they return + # `Index`s with the correct element type. + check(assert_type(b + left, "npt.NDArray[np.bool_]"), pd.Index, np.bool_) + check(assert_type(i + left, "npt.NDArray[np.int64]"), pd.Index, np.integer) + check(assert_type(f + left, "npt.NDArray[np.float64]"), pd.Index, np.floating) + check( + assert_type(c + left, "npt.NDArray[np.complex128]"), + pd.Index, + np.complexfloating, + ) + + +def test_add_pd_index() -> None: + """Test pd.Index[bool] + pandas index""" + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) + + check(assert_type(left + b, "pd.Index[bool]"), pd.Index, np.bool_) + check(assert_type(left + i, "pd.Index[int]"), pd.Index, np.integer) + check(assert_type(left + f, "pd.Index[float]"), pd.Index, np.floating) + check(assert_type(left + c, "pd.Index[complex]"), pd.Index, np.complexfloating) + + check(assert_type(b + left, "pd.Index[bool]"), pd.Index, np.bool_) + check(assert_type(i + left, "pd.Index[int]"), pd.Index, np.integer) + check(assert_type(f + left, "pd.Index[float]"), pd.Index, np.floating) + check(assert_type(c + left, "pd.Index[complex]"), pd.Index, np.complexfloating) diff --git a/tests/indexes/arithmetic/complex/__init__.py b/tests/indexes/arithmetic/complex/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/indexes/arithmetic/complex/test_add.py b/tests/indexes/arithmetic/complex/test_add.py new file mode 100644 index 00000000..4454664f --- /dev/null +++ b/tests/indexes/arithmetic/complex/test_add.py @@ -0,0 +1,84 @@ +import numpy as np +from numpy import typing as npt # noqa: F401 +import pandas as pd +from typing_extensions import assert_type + +from tests import check + +# left operand +left = pd.Index([1j, 2j, 3j]) + + +def test_add_py_scalar() -> None: + """Test pd.Index[complex] + Python native scalars""" + b, i, f, c = True, 1, 1.0, 1j + + check(assert_type(left + b, "pd.Index[complex]"), pd.Index, np.complexfloating) + check(assert_type(left + i, "pd.Index[complex]"), pd.Index, np.complexfloating) + check(assert_type(left + f, "pd.Index[complex]"), pd.Index, np.complexfloating) + check(assert_type(left + c, "pd.Index[complex]"), pd.Index, np.complexfloating) + + check(assert_type(b + left, "pd.Index[complex]"), pd.Index, np.complexfloating) + check(assert_type(i + left, "pd.Index[complex]"), pd.Index, np.complexfloating) + check(assert_type(f + left, "pd.Index[complex]"), pd.Index, np.complexfloating) + check(assert_type(c + left, "pd.Index[complex]"), pd.Index, np.complexfloating) + + +def test_add_py_sequence() -> None: + """Test pd.Index[complex] + Python native sequence""" + b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] + + check(assert_type(left + b, "pd.Index[complex]"), pd.Index, np.complexfloating) + check(assert_type(left + i, "pd.Index[complex]"), pd.Index, np.complexfloating) + check(assert_type(left + f, "pd.Index[complex]"), pd.Index, np.complexfloating) + check(assert_type(left + c, "pd.Index[complex]"), pd.Index, np.complexfloating) + + check(assert_type(b + left, "pd.Index[complex]"), pd.Index, np.complexfloating) + check(assert_type(i + left, "pd.Index[complex]"), pd.Index, np.complexfloating) + check(assert_type(f + left, "pd.Index[complex]"), pd.Index, np.complexfloating) + check(assert_type(c + left, "pd.Index[complex]"), pd.Index, np.complexfloating) + + +def test_add_numpy_array() -> None: + """Test pd.Index[complex] + numpy array""" + 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) + + check(assert_type(left + b, "pd.Index[complex]"), pd.Index, np.complexfloating) + check(assert_type(left + i, "pd.Index[complex]"), pd.Index, np.complexfloating) + check(assert_type(left + f, "pd.Index[complex]"), pd.Index, np.complexfloating) + check(assert_type(left + c, "pd.Index[complex]"), pd.Index, np.complexfloating) + + # `numpy` typing gives the corresponding `ndarray`s in the static type + # checking, where our `__radd__` cannot override. At runtime, they return + # `Index`s with the correct element type. + check(assert_type(b + left, "npt.NDArray[np.bool_]"), pd.Index, np.complexfloating) + check(assert_type(i + left, "npt.NDArray[np.int64]"), pd.Index, np.complexfloating) + check( + assert_type(f + left, "npt.NDArray[np.float64]"), pd.Index, np.complexfloating + ) + check( + assert_type(c + left, "npt.NDArray[np.complex128]"), + pd.Index, + np.complexfloating, + ) + + +def test_add_pd_index() -> None: + """Test pd.Index[complex] + pandas index""" + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) + + check(assert_type(left + b, "pd.Index[complex]"), pd.Index, np.complexfloating) + check(assert_type(left + i, "pd.Index[complex]"), pd.Index, np.complexfloating) + check(assert_type(left + f, "pd.Index[complex]"), pd.Index, np.complexfloating) + check(assert_type(left + c, "pd.Index[complex]"), pd.Index, np.complexfloating) + + check(assert_type(b + left, "pd.Index[complex]"), pd.Index, np.complexfloating) + check(assert_type(i + left, "pd.Index[complex]"), pd.Index, np.complexfloating) + check(assert_type(f + left, "pd.Index[complex]"), pd.Index, np.complexfloating) + check(assert_type(c + left, "pd.Index[complex]"), pd.Index, np.complexfloating) diff --git a/tests/indexes/arithmetic/float/__init__.py b/tests/indexes/arithmetic/float/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/indexes/arithmetic/float/test_add.py b/tests/indexes/arithmetic/float/test_add.py new file mode 100644 index 00000000..12809c17 --- /dev/null +++ b/tests/indexes/arithmetic/float/test_add.py @@ -0,0 +1,82 @@ +import numpy as np +from numpy import typing as npt # noqa: F401 +import pandas as pd +from typing_extensions import assert_type + +from tests import check + +# left operand +left = pd.Index([1.0, 2.0, 3.0]) + + +def test_add_py_scalar() -> None: + """Test pd.Index[float] + Python native scalars""" + b, i, f, c = True, 1, 1.0, 1j + + 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) + + 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) + + +def test_add_py_sequence() -> None: + """Test pd.Index[float] + Python native sequence""" + b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] + + check(assert_type(left + b, "pd.Index[float]"), pd.Index, np.floating) + 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) + + 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) + + +def test_add_numpy_array() -> None: + """Test pd.Index[float] + numpy array""" + 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) + + 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) + + # `numpy` typing gives the corresponding `ndarray`s in the static type + # checking, where our `__radd__` cannot override. At runtime, they return + # `Index`s with the correct element type. + check(assert_type(b + left, "npt.NDArray[np.bool_]"), pd.Index, np.floating) + check(assert_type(i + left, "npt.NDArray[np.int64]"), pd.Index, np.floating) + check(assert_type(f + left, "npt.NDArray[np.float64]"), pd.Index, np.floating) + check( + assert_type(c + left, "npt.NDArray[np.complex128]"), + pd.Index, + np.complexfloating, + ) + + +def test_add_pd_index() -> None: + """Test pd.Index[float] + pandas index""" + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) + + 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) + + 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) diff --git a/tests/indexes/arithmetic/int/__init__.py b/tests/indexes/arithmetic/int/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/indexes/arithmetic/int/test_add.py b/tests/indexes/arithmetic/int/test_add.py new file mode 100644 index 00000000..8c714e88 --- /dev/null +++ b/tests/indexes/arithmetic/int/test_add.py @@ -0,0 +1,82 @@ +import numpy as np +from numpy import typing as npt # noqa: F401 +import pandas as pd +from typing_extensions import assert_type + +from tests import check + +# left operand +left = pd.Index([1, 2, 3]) + + +def test_add_py_scalar() -> None: + """Test pd.Index[int] + Python native scalars""" + b, i, f, c = True, 1, 1.0, 1j + + 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) + check(assert_type(left + c, "pd.Index[complex]"), pd.Index, np.complexfloating) + + 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) + check(assert_type(c + left, "pd.Index[complex]"), pd.Index, np.complexfloating) + + +def test_add_py_sequence() -> None: + """Test pd.Index[int] + Python native sequence""" + b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] + + check(assert_type(left + b, "pd.Index[int]"), pd.Index, np.integer) + check(assert_type(left + i, "pd.Index[int]"), pd.Index, np.integer) + check(assert_type(left + f, "pd.Index[float]"), pd.Index, np.floating) + check(assert_type(left + c, "pd.Index[complex]"), pd.Index, np.complexfloating) + + 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) + check(assert_type(c + left, "pd.Index[complex]"), pd.Index, np.complexfloating) + + +def test_add_numpy_array() -> None: + """Test pd.Index[int] + numpy array""" + 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) + + 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) + check(assert_type(left + c, "pd.Index[complex]"), pd.Index, np.complexfloating) + + # `numpy` typing gives the corresponding `ndarray`s in the static type + # checking, where our `__radd__` cannot override. At runtime, they return + # `Index`s with the correct element type. + check(assert_type(b + left, "npt.NDArray[np.bool_]"), pd.Index, np.integer) + check(assert_type(i + left, "npt.NDArray[np.int64]"), pd.Index, np.integer) + check(assert_type(f + left, "npt.NDArray[np.float64]"), pd.Index, np.floating) + check( + assert_type(c + left, "npt.NDArray[np.complex128]"), + pd.Index, + np.complexfloating, + ) + + +def test_add_pd_index() -> None: + """Test pd.Index[int] + pandas index""" + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) + + 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) + check(assert_type(left + c, "pd.Index[complex]"), pd.Index, np.complexfloating) + + 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) + check(assert_type(c + left, "pd.Index[complex]"), pd.Index, np.complexfloating) diff --git a/tests/indexes/arithmetic/str/__init__.py b/tests/indexes/arithmetic/str/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/indexes/arithmetic/str/test_add.py b/tests/indexes/arithmetic/str/test_add.py new file mode 100644 index 00000000..1b8de718 --- /dev/null +++ b/tests/indexes/arithmetic/str/test_add.py @@ -0,0 +1,88 @@ +import sys +from typing import Any + +import numpy as np +from numpy import typing as npt # noqa: F401 +import pandas as pd +from typing_extensions import ( + Never, + assert_type, +) + +from tests import ( + TYPE_CHECKING_INVALID_USAGE, + check, +) + +left = pd.Index(["1", "23", "456"]) # left operand + + +def test_add_py_scalar() -> None: + """Test pd.Index[str] + Python native 'scalar's""" + i = 4 + r0 = "right" + + if TYPE_CHECKING_INVALID_USAGE: + _0 = left + i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left + r0, "pd.Index[str]"), pd.Index, str) + + if TYPE_CHECKING_INVALID_USAGE: + _1 = i + left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(r0 + left, "pd.Index[str]"), pd.Index, str) + + +def test_add_py_sequence() -> None: + """Test pd.Index[str] + Python native sequence""" + i = [3, 5, 8] + r0 = ["a", "bc", "def"] + r1 = tuple(r0) + + if TYPE_CHECKING_INVALID_USAGE: + _0 = left + i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left + r0, "pd.Index[str]"), pd.Index, str) + check(assert_type(left + r1, "pd.Index[str]"), pd.Index, str) + + if TYPE_CHECKING_INVALID_USAGE: + _1 = i + left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(r0 + left, "pd.Index[str]"), pd.Index, str) + check(assert_type(r1 + left, "pd.Index[str]"), pd.Index, str) + + +def test_add_numpy_array() -> None: + """Test pd.Index[str] + numpy array""" + i = np.array([3, 5, 8], np.int64) + r0 = np.array(["a", "bc", "def"], np.str_) + + if TYPE_CHECKING_INVALID_USAGE: + assert_type(left + i, Never) + check(assert_type(left + r0, "pd.Index[str]"), pd.Index, str) + + # `numpy` typing gives `npt.NDArray[np.int64]` in the static type + # checking, where our `__radd__` cannot override. At runtime, they return + # `Index`s. + if TYPE_CHECKING_INVALID_USAGE: + assert_type(i + left, "npt.NDArray[np.int64]") + if sys.version_info >= (3, 11): + # `numpy` typing gives `npt.NDArray[np.int64]` in the static type + # checking, where our `__radd__` cannot override. At runtime, they return + # `Index`s. + check(assert_type(r0 + left, "npt.NDArray[np.str_]"), pd.Index, str) + else: + # Python 3.10 uses NumPy 2.2.6, and it has for r0 ndarray[tuple[int,...], dtype[str_]] + # Python 3.11+ uses NumPy 2.3.2, and it has for r0 ndarray[tuple[Any,...,dtype[str_]] + # https://github.com/pandas-dev/pandas-stubs/pull/1274#discussion_r2291498975 + check(assert_type(r0 + left, Any), pd.Index, str) + + +def test_add_pd_index() -> None: + """Test pd.Index[str] + pandas index""" + i = pd.Index([3, 5, 8]) + r0 = pd.Index(["a", "bc", "def"]) + + if TYPE_CHECKING_INVALID_USAGE: + _0 = left + i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left + r0, "pd.Index[str]"), pd.Index, str) + + if TYPE_CHECKING_INVALID_USAGE: + _1 = i + left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(r0 + left, "pd.Index[str]"), pd.Index, str) diff --git a/tests/indexes/arithmetic/test_add.py b/tests/indexes/arithmetic/test_add.py new file mode 100644 index 00000000..dea1ec7d --- /dev/null +++ b/tests/indexes/arithmetic/test_add.py @@ -0,0 +1,106 @@ +import numpy as np +from numpy import typing as npt # noqa: F401 +import pandas as pd +from typing_extensions import ( + Never, + assert_type, +) + +from tests import ( + TYPE_CHECKING_INVALID_USAGE, + check, +) + +# left operands +left_i = pd.MultiIndex.from_tuples([(1,), (2,), (3,)]).levels[0] +left_str = pd.MultiIndex.from_tuples([("1",), ("2",), ("3_",)]).levels[0] + + +def test_add_i_py_scalar() -> None: + """Test pd.Index[Any] (int) + Python native scalars""" + b, i, f, c = True, 1, 1.0, 1j + + check(assert_type(left_i + b, pd.Index), pd.Index) + check(assert_type(left_i + i, pd.Index), pd.Index) + check(assert_type(left_i + f, pd.Index), pd.Index) + check(assert_type(left_i + c, pd.Index), pd.Index) + + check(assert_type(b + left_i, pd.Index), pd.Index) + check(assert_type(i + left_i, pd.Index), pd.Index) + check(assert_type(f + left_i, pd.Index), pd.Index) + check(assert_type(c + left_i, pd.Index), pd.Index) + + +def test_add_i_py_sequence() -> None: + """Test pd.Index[Any] (int) + Python native sequence""" + b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] + + check(assert_type(left_i + b, pd.Index), pd.Index) + check(assert_type(left_i + i, pd.Index), pd.Index) + check(assert_type(left_i + f, pd.Index), pd.Index) + check(assert_type(left_i + c, pd.Index), pd.Index) + + check(assert_type(b + left_i, pd.Index), pd.Index) + check(assert_type(i + left_i, pd.Index), pd.Index) + check(assert_type(f + left_i, pd.Index), pd.Index) + check(assert_type(c + left_i, pd.Index), pd.Index) + + +def test_add_i_numpy_array() -> None: + """Test pd.Index[Any] (int) + numpy array""" + 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) + + check(assert_type(left_i + b, pd.Index), pd.Index) + check(assert_type(left_i + i, pd.Index), pd.Index) + check(assert_type(left_i + f, pd.Index), pd.Index) + check(assert_type(left_i + c, pd.Index), pd.Index) + + # `numpy` typing gives the corresponding `ndarray`s in the static type + # checking, where our `__radd__` cannot override. At runtime, they return + # `Index`s. + # `mypy` thinks the return types are `Any`, which is a bug. + check( + assert_type(b + left_i, "npt.NDArray[np.bool_]"), pd.Index # type: ignore[assert-type] + ) + check( + assert_type(i + left_i, "npt.NDArray[np.int64]"), pd.Index # type: ignore[assert-type] + ) + check( + assert_type(f + left_i, "npt.NDArray[np.float64]"), pd.Index # type: ignore[assert-type] + ) + check( + assert_type(c + left_i, "npt.NDArray[np.complex128]"), pd.Index # type: ignore[assert-type] + ) + + +def test_add_i_pd_index() -> None: + """Test pd.Index[Any] (int) + pandas index""" + a = pd.MultiIndex.from_tuples([(1,), (2,), (3,)]).levels[0] + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) + + check(assert_type(left_i + a, pd.Index), pd.Index) + check(assert_type(left_i + b, pd.Index), pd.Index) + check(assert_type(left_i + i, pd.Index), pd.Index) + check(assert_type(left_i + f, pd.Index), pd.Index) + check(assert_type(left_i + c, pd.Index), pd.Index) + + check(assert_type(a + left_i, pd.Index), pd.Index) + check(assert_type(b + left_i, pd.Index), pd.Index) + check(assert_type(i + left_i, pd.Index), pd.Index) + check(assert_type(f + left_i, pd.Index), pd.Index) + check(assert_type(c + left_i, pd.Index), pd.Index) + + +def test_add_i_py_str() -> None: + """Test pd.Index[Any] (int) + Python str""" + s = "abc" + + if TYPE_CHECKING_INVALID_USAGE: + assert_type(left_i + s, Never) + assert_type(s + left_i, Never) diff --git a/tests/test_indexes.py b/tests/indexes/test_indexes.py similarity index 99% rename from tests/test_indexes.py rename to tests/indexes/test_indexes.py index 280b5726..116155f3 100644 --- a/tests/test_indexes.py +++ b/tests/indexes/test_indexes.py @@ -262,12 +262,10 @@ 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(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) check(assert_type(3 / idx, "pd.Index[float]"), pd.Index, np.float64) diff --git a/tests/series/arithmetic/bool/test_add.py b/tests/series/arithmetic/bool/test_add.py index d2a77d55..7ba110fc 100644 --- a/tests/series/arithmetic/bool/test_add.py +++ b/tests/series/arithmetic/bool/test_add.py @@ -127,3 +127,33 @@ def test_add_pd_series() -> None: check( assert_type(left.radd(c), "pd.Series[complex]"), pd.Series, np.complexfloating ) + + +def test_add_pd_index() -> None: + """Test pd.Series[bool] + pandas index""" + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) + + check(assert_type(left + b, "pd.Series[bool]"), pd.Series, np.bool_) + check(assert_type(left + i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left + f, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left + c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(b + left, "pd.Series[bool]"), pd.Series, np.bool_) + check(assert_type(i + left, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(f + left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(c + left, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.add(b), "pd.Series[bool]"), pd.Series, np.bool_) + check(assert_type(left.add(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.add(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.add(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.radd(b), "pd.Series[bool]"), pd.Series, np.bool_) + check(assert_type(left.radd(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.radd(f), "pd.Series[float]"), pd.Series, np.floating) + check( + assert_type(left.radd(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) diff --git a/tests/series/arithmetic/complex/test_add.py b/tests/series/arithmetic/complex/test_add.py index e3668b33..5614a627 100644 --- a/tests/series/arithmetic/complex/test_add.py +++ b/tests/series/arithmetic/complex/test_add.py @@ -153,3 +153,39 @@ def test_add_pd_series() -> None: check( assert_type(left.radd(c), "pd.Series[complex]"), pd.Series, np.complexfloating ) + + +def test_add_pd_index() -> None: + """Test pd.Series[complex] + pandas index""" + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) + + check(assert_type(left + b, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left + i, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left + f, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left + c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(b + left, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(i + left, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(f + left, "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(c + left, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.add(b), "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left.add(i), "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left.add(f), "pd.Series[complex]"), pd.Series, np.complexfloating) + check(assert_type(left.add(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check( + assert_type(left.radd(b), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + check( + assert_type(left.radd(i), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + check( + assert_type(left.radd(f), "pd.Series[complex]"), pd.Series, np.complexfloating + ) + check( + assert_type(left.radd(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) diff --git a/tests/series/arithmetic/float/test_add.py b/tests/series/arithmetic/float/test_add.py index 41fc6b96..63ef7d90 100644 --- a/tests/series/arithmetic/float/test_add.py +++ b/tests/series/arithmetic/float/test_add.py @@ -127,3 +127,33 @@ def test_add_pd_series() -> None: check( assert_type(left.radd(c), "pd.Series[complex]"), pd.Series, np.complexfloating ) + + +def test_add_pd_index() -> None: + """Test pd.Series[float] + pandas index""" + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) + + check(assert_type(left + b, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left + i, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left + f, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left + c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(b + left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(i + left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(f + left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(c + left, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.add(b), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.add(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.add(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.add(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.radd(b), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.radd(i), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.radd(f), "pd.Series[float]"), pd.Series, np.floating) + check( + assert_type(left.radd(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) diff --git a/tests/series/arithmetic/int/test_add.py b/tests/series/arithmetic/int/test_add.py index b68b5e23..cc2d7bd2 100644 --- a/tests/series/arithmetic/int/test_add.py +++ b/tests/series/arithmetic/int/test_add.py @@ -127,3 +127,33 @@ def test_add_pd_series() -> None: check( assert_type(left.radd(c), "pd.Series[complex]"), pd.Series, np.complexfloating ) + + +def test_add_pd_index() -> None: + """Test pd.Series[int] + pandas index""" + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) + + check(assert_type(left + b, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left + i, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left + f, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left + c, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(b + left, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(i + left, "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(f + left, "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(c + left, "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.add(b), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.add(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.add(f), "pd.Series[float]"), pd.Series, np.floating) + check(assert_type(left.add(c), "pd.Series[complex]"), pd.Series, np.complexfloating) + + check(assert_type(left.radd(b), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.radd(i), "pd.Series[int]"), pd.Series, np.integer) + check(assert_type(left.radd(f), "pd.Series[float]"), pd.Series, np.floating) + check( + assert_type(left.radd(c), "pd.Series[complex]"), pd.Series, np.complexfloating + ) diff --git a/tests/series/arithmetic/str/test_add.py b/tests/series/arithmetic/str/test_add.py index a58fe663..9668bdba 100644 --- a/tests/series/arithmetic/str/test_add.py +++ b/tests/series/arithmetic/str/test_add.py @@ -120,3 +120,25 @@ def test_add_pd_series() -> None: if TYPE_CHECKING_INVALID_USAGE: left.radd(i) # type: ignore[arg-type] # pyright: ignore[reportArgumentType, reportCallIssue] check(assert_type(left.radd(r0), "pd.Series[str]"), pd.Series, str) + + +def test_add_pd_index() -> None: + """Test pd.Series[str] + pandas index""" + i = pd.Index([3, 5, 8]) + r0 = pd.Index(["a", "bc", "def"]) + + if TYPE_CHECKING_INVALID_USAGE: + _0 = left + i # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(left + r0, "pd.Series[str]"), pd.Series, str) + + if TYPE_CHECKING_INVALID_USAGE: + _1 = i + left # type: ignore[operator] # pyright: ignore[reportOperatorIssue] + check(assert_type(r0 + left, "pd.Series[str]"), pd.Series, str) + + if TYPE_CHECKING_INVALID_USAGE: + left.add(i) # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + check(assert_type(left.add(r0), "pd.Series[str]"), pd.Series, str) + + if TYPE_CHECKING_INVALID_USAGE: + left.radd(i) # type: ignore[arg-type] # pyright: ignore[reportArgumentType, reportCallIssue] + check(assert_type(left.radd(r0), "pd.Series[str]"), pd.Series, str) diff --git a/tests/series/arithmetic/test_add.py b/tests/series/arithmetic/test_add.py index a739ddae..b0f867b5 100644 --- a/tests/series/arithmetic/test_add.py +++ b/tests/series/arithmetic/test_add.py @@ -1,3 +1,8 @@ +from typing import ( + Any, + cast, +) + import numpy as np from numpy import typing as npt # noqa: F401 import pandas as pd @@ -43,23 +48,32 @@ def test_add_i_py_scalar() -> None: def test_add_i_py_sequence() -> None: """Test pd.Series[Any] (int) + Python native sequence""" - b, i, f, c = [True, False, True], [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] + # mypy believe it is already list[Any], whereas pyright gives list[bool | int | complex] + a = cast(list[Any], [True, 3, 5j]) # type: ignore[redundant-cast] + b = [True, False, True] + i = [2, 3, 5] + f = [1.0, 2.0, 3.0] + c = [1j, 1j, 4j] + check(assert_type(left_i + a, pd.Series), pd.Series) check(assert_type(left_i + b, pd.Series), pd.Series) check(assert_type(left_i + i, pd.Series), pd.Series) check(assert_type(left_i + f, pd.Series), pd.Series) check(assert_type(left_i + c, pd.Series), pd.Series) + check(assert_type(a + left_i, pd.Series), pd.Series) check(assert_type(b + left_i, pd.Series), pd.Series) check(assert_type(i + left_i, pd.Series), pd.Series) check(assert_type(f + left_i, pd.Series), pd.Series) check(assert_type(c + left_i, pd.Series), pd.Series) + check(assert_type(left_i.add(a), pd.Series), pd.Series) check(assert_type(left_i.add(b), pd.Series), pd.Series) check(assert_type(left_i.add(i), pd.Series), pd.Series) check(assert_type(left_i.add(f), pd.Series), pd.Series) check(assert_type(left_i.add(c), pd.Series), pd.Series) + check(assert_type(left_i.radd(a), pd.Series), pd.Series) check(assert_type(left_i.radd(b), pd.Series), pd.Series) check(assert_type(left_i.radd(i), pd.Series), pd.Series) check(assert_type(left_i.radd(f), pd.Series), pd.Series) @@ -139,6 +153,39 @@ def test_add_i_pd_series() -> None: check(assert_type(left_i.radd(c), pd.Series), pd.Series) +def test_add_i_pd_index() -> None: + """Test pd.Series[Any] (int) + pandas index""" + a = pd.MultiIndex.from_tuples([(1,), (2,), (3,)]).levels[0] + b = pd.Index([True, False, True]) + i = pd.Index([2, 3, 5]) + f = pd.Index([1.0, 2.0, 3.0]) + c = pd.Index([1.1j, 2.2j, 4.1j]) + + check(assert_type(left_i + a, pd.Series), pd.Series) + check(assert_type(left_i + b, pd.Series), pd.Series) + check(assert_type(left_i + i, pd.Series), pd.Series) + check(assert_type(left_i + f, pd.Series), pd.Series) + check(assert_type(left_i + c, pd.Series), pd.Series) + + check(assert_type(a + left_i, pd.Series), pd.Series) + check(assert_type(b + left_i, pd.Series), pd.Series) + check(assert_type(i + left_i, pd.Series), pd.Series) + check(assert_type(f + left_i, pd.Series), pd.Series) + check(assert_type(c + left_i, pd.Series), pd.Series) + + check(assert_type(left_i.add(a), pd.Series), pd.Series) + check(assert_type(left_i.add(b), pd.Series), pd.Series) + check(assert_type(left_i.add(i), pd.Series), pd.Series) + check(assert_type(left_i.add(f), pd.Series), pd.Series) + check(assert_type(left_i.add(c), pd.Series), pd.Series) + + check(assert_type(left_i.radd(a), pd.Series), pd.Series) + check(assert_type(left_i.radd(b), pd.Series), pd.Series) + check(assert_type(left_i.radd(i), pd.Series), pd.Series) + check(assert_type(left_i.radd(f), pd.Series), pd.Series) + check(assert_type(left_i.radd(c), pd.Series), pd.Series) + + def test_add_i_py_str() -> None: """Test pd.Series[Any] (int) + Python str""" s = "abc"