From c13e5cd73f5d8bb3cf1c203839662ea1de3a59d3 Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Sun, 13 Jul 2025 18:17:11 +0200 Subject: [PATCH 01/10] refactor: minimal systematic implementation --- pandas-stubs/core/series.pyi | 24 +++++- pyproject.toml | 2 +- tests/series/__init__.py | 0 tests/series/arithmetic/__init__.py | 0 tests/series/arithmetic/int/__init__.py | 0 tests/series/arithmetic/int/test_add.py | 104 +++++++++++++++++++++++ tests/series/arithmetic/test_add.py | 105 ++++++++++++++++++++++++ tests/{ => series}/test_series.py | 7 +- tests/test_frame.py | 22 ++++- 9 files changed, 256 insertions(+), 8 deletions(-) create mode 100644 tests/series/__init__.py create mode 100644 tests/series/arithmetic/__init__.py create mode 100644 tests/series/arithmetic/int/__init__.py create mode 100644 tests/series/arithmetic/int/test_add.py create mode 100644 tests/series/arithmetic/test_add.py rename tests/{ => series}/test_series.py (99%) diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index 3a3ba8c41..d860caed5 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -175,6 +175,8 @@ from pandas._typing import ( VoidDtypeArg, WriteBuffer, np_ndarray_anyint, + np_ndarray_complex, + np_ndarray_float, npt, num, ) @@ -1617,6 +1619,10 @@ class Series(IndexOpsMixin[S1], NDFrame): # just failed to generate these so I couldn't match # them up. @overload + def __add__( + self: Series[int], other: int | Sequence[int] | Series[int] + ) -> Series[int]: ... + @overload def __add__(self, other: S1 | Self) -> Self: ... @overload def __add__( @@ -1743,7 +1749,14 @@ class Series(IndexOpsMixin[S1], NDFrame): # Methods def add( self, - other: Series[S1] | Scalar, + other: ( + Sequence[S1] + | np_ndarray_anyint + | np_ndarray_float + | np_ndarray_complex + | Series[S1] + | Scalar + ), level: Level | None = ..., fill_value: float | None = ..., axis: int = ..., @@ -1987,7 +2000,14 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Scalar: ... def radd( self, - other: Series[S1] | Scalar, + other: ( + Sequence[S1] + | np_ndarray_anyint + | np_ndarray_float + | np_ndarray_complex + | Series[S1] + | Scalar + ), level: Level | None = ..., fill_value: float | None = ..., axis: AxisIndex = ..., diff --git a/pyproject.toml b/pyproject.toml index a60a4f6ba..0de7fe6ce 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,7 +39,7 @@ mypy = "1.17.0" pandas = "2.3.1" pyarrow = ">=10.0.1" pytest = ">=7.1.2" -pyright = ">=1.1.400" +pyright = ">=1.1.403" ty = "^0.0.1a8" pyrefly = "^0.21.0" poethepoet = ">=0.16.5" diff --git a/tests/series/__init__.py b/tests/series/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/series/arithmetic/__init__.py b/tests/series/arithmetic/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/series/arithmetic/int/__init__.py b/tests/series/arithmetic/int/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/series/arithmetic/int/test_add.py b/tests/series/arithmetic/int/test_add.py new file mode 100644 index 000000000..1b6b75ced --- /dev/null +++ b/tests/series/arithmetic/int/test_add.py @@ -0,0 +1,104 @@ +from typing import assert_type + +import pandas as pd + +from tests import check + +left = pd.Series([1, 2, 3]) # left operand + + +def test_add_py_scalar() -> None: + """Test pd.Series[int] + Python native scalars""" + i, f, c = 1, 1.0, 1j + + check(assert_type(left + i, "pd.Series[int]"), pd.Series, int) + # check(assert_type(left + f, "pd.Series[float]"), pd.Series, float) + # check(assert_type(left + c, "pd.Series[complex]"), pd.Series, complex) + + check(assert_type(i + left, "pd.Series[int]"), pd.Series, int) + # check(assert_type(f + left, "pd.Series[float]"), pd.Series, float) + # check(assert_type(c + left, "pd.Series[complex]"), pd.Series, complex) + + check(assert_type(left.add(i), "pd.Series[int]"), pd.Series, int) + # check(assert_type(left.add(f), "pd.Series[float]"), pd.Series, float) + # check(assert_type(left.add(c), "pd.Series[complex]"), pd.Series, complex) + + check(assert_type(left.radd(i), "pd.Series[int]"), pd.Series, int) + + +# check(assert_type(left.radd(f), "pd.Series[float]"), pd.Series, float) +# check(assert_type(left.radd(c), "pd.Series[complex]"), pd.Series, complex) + + +def test_add_py_sequence() -> None: + """Test pd.Series[int] + Python native sequence""" + i, f, c = [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] + + check(assert_type(left + i, "pd.Series[int]"), pd.Series, int) + # check(assert_type(left + f, "pd.Series[float]"), pd.Series, float) + # check(assert_type(left + c, "pd.Series[complex]"), pd.Series, complex) + + # check(assert_type(i + left, "pd.Series[int]"), pd.Series, int) + # check(assert_type(f + left, "pd.Series[float]"), pd.Series, float) + # check(assert_type(c + left, "pd.Series[complex]"), pd.Series, complex) + + check(assert_type(left.add(i), "pd.Series[int]"), pd.Series, int) + + +# check(assert_type(left.add(f), "pd.Series[float]"), pd.Series, float) +# check(assert_type(left.add(c), "pd.Series[complex]"), pd.Series, complex) + +# check(assert_type(left.radd(i), "pd.Series[int]"), pd.Series, int) +# check(assert_type(left.radd(f), "pd.Series[int]"), pd.Series, int) +# check(assert_type(left.radd(c), "pd.Series[complex]"), pd.Series, complex) + + +# def test_add_numpy_array() -> None: +# """Test pd.Series[int] + numpy array""" +# 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.complex64) + +# check(assert_type(left + i, "pd.Series[int]"), pd.Series, int) +# check(assert_type(left + f, "pd.Series[float]"), pd.Series, float) +# check(assert_type(left + c, "pd.Series[complex]"), pd.Series, complex) + +# # check(assert_type(i + l, "pd.Series[int]"), pd.Series, int) +# # check(assert_type(f + l, "pd.Series[float]"), pd.Series, float) +# # check(assert_type(c + l, "pd.Series[complex]"), pd.Series, complex) + +# check(assert_type(left.add(i), "pd.Series[int]"), pd.Series, int) +# check(assert_type(left.add(f), "pd.Series[float]"), pd.Series, float) +# check(assert_type(left.add(c), "pd.Series[complex]"), pd.Series, complex) + +# check(assert_type(left.radd(i), "pd.Series[int]"), pd.Series, int) +# check(assert_type(left.radd(f), "pd.Series[float]"), pd.Series, float) +# check(assert_type(left.radd(c), "pd.Series[complex]"), pd.Series, complex) + + +def test_add_pd_series() -> None: + """Test pd.Series[int] + pandas series""" + i = pd.Series([2, 3, 5]) + # f = pd.Series([1.0, 2.0, 3.0]) + # c = pd.Series([1.1j, 2.2j, 4.1j]) + + check(assert_type(left + i, "pd.Series[int]"), pd.Series, int) + # check(assert_type(left + f, "pd.Series[float]"), pd.Series, float) + # check(assert_type(left + c, "pd.Series[complex]"), pd.Series, complex) + + # check( + # assert_type(i + left, pd.Series), "pd.Series[int]"), pd.Series, int) + # check( + # assert_type(f + left, "pd.Series[float]"), pd.Series, float) + # check( + # assert_type(c + left, pd.Series), "pd.Series[complex]"), pd.Series, complex) + + check(assert_type(left.add(i), "pd.Series[int]"), pd.Series, int) + # check(assert_type(left.add(f), "pd.Series[float]"), pd.Series, float) + # check(assert_type(left.add(c), "pd.Series[complex]"), pd.Series, complex) + + check(assert_type(left.radd(i), "pd.Series[int]"), pd.Series, int) + + +# check(assert_type(left.radd(f), "pd.Series[float]"), pd.Series, float) +# check(assert_type(left.radd(c), "pd.Series[complex]"), pd.Series, complex) diff --git a/tests/series/arithmetic/test_add.py b/tests/series/arithmetic/test_add.py new file mode 100644 index 000000000..2d2c5916a --- /dev/null +++ b/tests/series/arithmetic/test_add.py @@ -0,0 +1,105 @@ +from typing import assert_type + +import numpy as np +import pandas as pd + +from tests import check + +left = pd.DataFrame({"a": [1, 2, 3]})["a"] # left operand + + +def test_add_py_scalar() -> None: + """Test pd.Series[Any] + Python native scalars""" + i, f, c = 1, 1.0, 1j + + # check(assert_type(left + i, pd.Series), pd.Series) # why? + check(assert_type(left + f, pd.Series), pd.Series) + check(assert_type(left + c, pd.Series), pd.Series) + + check(assert_type(i + left, pd.Series), pd.Series) + check(assert_type(f + left, pd.Series), pd.Series) + check(assert_type(c + left, pd.Series), pd.Series) + + check(assert_type(left.add(i), pd.Series), pd.Series) + check(assert_type(left.add(f), pd.Series), pd.Series) + check(assert_type(left.add(c), pd.Series), pd.Series) + + check(assert_type(left.radd(i), pd.Series), pd.Series) + check(assert_type(left.radd(f), pd.Series), pd.Series) + check(assert_type(left.radd(c), pd.Series), pd.Series) + + +def test_add_py_sequence() -> None: + """Test pd.Series[Any] + Python native sequence""" + i, f, c = [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] + + # check(assert_type(left + i, pd.Series), pd.Series) # why? + check(assert_type(left + f, pd.Series), pd.Series) + check(assert_type(left + c, pd.Series), pd.Series) + + check(assert_type(i + left, pd.Series), pd.Series) + check(assert_type(f + left, pd.Series), pd.Series) + check(assert_type(c + left, pd.Series), pd.Series) + + check(assert_type(left.add(i), pd.Series), pd.Series) + check(assert_type(left.add(f), pd.Series), pd.Series) + check(assert_type(left.add(c), pd.Series), pd.Series) + + check(assert_type(left.radd(i), pd.Series), pd.Series) + check(assert_type(left.radd(f), pd.Series), pd.Series) + check(assert_type(left.radd(c), pd.Series), pd.Series) + + +def test_add_numpy_array() -> None: + """Test pd.Series[Any] + numpy array""" + 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.complex64) + + check(assert_type(left + i, pd.Series), pd.Series) + check(assert_type(left + f, pd.Series), pd.Series) + check(assert_type(left + c, pd.Series), pd.Series) + + # check(assert_type(i + l, pd.Series), pd.Series) + # check(assert_type(f + l, pd.Series), pd.Series) + # check(assert_type(c + l, pd.Series), pd.Series) + + check(assert_type(left.add(i), pd.Series), pd.Series) + check(assert_type(left.add(f), pd.Series), pd.Series) + check(assert_type(left.add(c), pd.Series), pd.Series) + + check(assert_type(left.radd(i), pd.Series), pd.Series) + check(assert_type(left.radd(f), pd.Series), pd.Series) + check(assert_type(left.radd(c), pd.Series), pd.Series) + + +def test_add_pd_series() -> None: + """Test pd.Series[Any] + pandas series""" + i = pd.Series([2, 3, 5]) + f = pd.Series([1.0, 2.0, 3.0]) + c = pd.Series([1.1j, 2.2j, 4.1j]) + + # check(assert_type(left + i, pd.Series), pd.Series) # why? + check(assert_type(left + f, pd.Series), pd.Series) + check(assert_type(left + c, pd.Series), pd.Series) + + check( + assert_type(i + left, pd.Series), # pyright: ignore[reportAssertTypeFailure] + pd.Series, + ) + check( + assert_type(f + left, pd.Series), # pyright: ignore[reportAssertTypeFailure] + pd.Series, + ) + check( + assert_type(c + left, pd.Series), # pyright: ignore[reportAssertTypeFailure] + pd.Series, + ) + + check(assert_type(left.add(i), pd.Series), pd.Series) + check(assert_type(left.add(f), pd.Series), pd.Series) + check(assert_type(left.add(c), pd.Series), pd.Series) + + check(assert_type(left.radd(i), pd.Series), pd.Series) + check(assert_type(left.radd(f), pd.Series), pd.Series) + check(assert_type(left.radd(c), pd.Series), pd.Series) diff --git a/tests/test_series.py b/tests/series/test_series.py similarity index 99% rename from tests/test_series.py rename to tests/series/test_series.py index f58d651f4..8c691f940 100644 --- a/tests/test_series.py +++ b/tests/series/test_series.py @@ -1604,7 +1604,10 @@ def test_series_min_max_sub_axis() -> None: ss = s1 - s2 sm = s1 * s2 sd = s1 / s2 - check(assert_type(sa, pd.Series), pd.Series) + check( + assert_type(sa, pd.Series), # pyright: ignore[reportAssertTypeFailure] # why? + pd.Series, + ) check(assert_type(ss, pd.Series), pd.Series) check(assert_type(sm, pd.Series), pd.Series) check(assert_type(sd, pd.Series), pd.Series) @@ -3902,7 +3905,7 @@ def foo(sf: pd.Series) -> None: pass foo(s) - check(assert_type(s + pd.Series([1]), pd.Series), pd.Series) + # check(assert_type(s + pd.Series([1]), pd.Series), pd.Series) # why? def test_series_items() -> None: diff --git a/tests/test_frame.py b/tests/test_frame.py index 2973d25cb..e4a1fde1b 100644 --- a/tests/test_frame.py +++ b/tests/test_frame.py @@ -2819,9 +2819,25 @@ def test_sum_get_add() -> None: summer = df.sum(axis=1) check(assert_type(summer, pd.Series), pd.Series) - check(assert_type(s + summer, pd.Series), pd.Series) - check(assert_type(s + df["y"], pd.Series), pd.Series) - check(assert_type(summer + summer, pd.Series), pd.Series) + check( + assert_type( + s + summer, pd.Series # pyright: ignore[reportAssertTypeFailure] # why? + ), + pd.Series, + ) + check( + assert_type( + s + df["y"], pd.Series # pyright: ignore[reportAssertTypeFailure] # why? + ), + pd.Series, + ) + check( + assert_type( + summer + summer, # pyright: ignore[reportAssertTypeFailure] # why? + pd.Series, + ), + pd.Series, + ) def test_getset_untyped() -> None: From c4945185584dd8949ef9d2d5ffe1f16828ca71bd Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Tue, 15 Jul 2025 16:26:54 +0200 Subject: [PATCH 02/10] feat: Series[int] + --- pandas-stubs/core/series.pyi | 135 ++++++++++++++++++++++-- tests/series/arithmetic/int/test_add.py | 120 ++++++++++----------- tests/series/arithmetic/test_add.py | 17 +-- tests/series/test_series.py | 5 +- tests/test_frame.py | 22 +--- 5 files changed, 191 insertions(+), 108 deletions(-) diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index d860caed5..ecab3153a 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -25,6 +25,7 @@ from typing import ( Generic, Literal, NoReturn, + TypeVar, final, overload, ) @@ -186,6 +187,8 @@ from pandas.core.dtypes.dtypes import CategoricalDtype from pandas.plotting import PlotAccessor +_T_COMPLEX = TypeVar("_T_COMPLEX", bound=complex) + class _iLocIndexerSeries(_iLocIndexer, Generic[S1]): # get item @overload @@ -1620,8 +1623,34 @@ class Series(IndexOpsMixin[S1], NDFrame): # them up. @overload def __add__( - self: Series[int], other: int | Sequence[int] | Series[int] - ) -> Series[int]: ... + self: Series[Never], + other: num | _str | timedelta | Timedelta | _ListLike | Series | np.timedelta64, + ) -> Series: ... + @overload + def __add__(self: Series[int], other: Series[Never]) -> Series: ... + @overload + def __add__( + self: Series[int], other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX] + ) -> Series[_T_COMPLEX]: ... + @overload + def __add__(self: Series[int], other: np_ndarray_anyint) -> Series[int]: ... + @overload + def __add__(self: Series[int], other: np_ndarray_float) -> Series[float]: ... + @overload + def __add__(self: Series[int], other: np_ndarray_complex) -> Series[complex]: ... + @overload + def __add__(self: Series[float], other: Series[Never]) -> Series: ... + @overload + def __add__( + self: Series[float], + other: int | Sequence[int] | np_ndarray_anyint | Series[int], + ) -> Series[float]: ... + @overload + def __add__(self: Series[complex], other: Series[Never]) -> Series: ... + @overload + def __add__( + self: Series[complex], other: int | Sequence[int] | Series[int] + ) -> Series[complex]: ... @overload def __add__(self, other: S1 | Self) -> Self: ... @overload @@ -1669,6 +1698,14 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def __or__(self, other: int | np_ndarray_anyint | Series[int]) -> Series[int]: ... @overload + def __radd__( + self: Series[Never], other: num | _str | _ListLike | Series + ) -> Series: ... + @overload + def __radd__( + self: Series[int], other: _T_COMPLEX | Sequence[_T_COMPLEX] + ) -> Series[_T_COMPLEX]: ... + @overload def __radd__(self, other: S1 | Series[S1]) -> Self: ... @overload def __radd__(self, other: num | _str | _ListLike | Series) -> Series: ... @@ -1747,19 +1784,60 @@ class Series(IndexOpsMixin[S1], NDFrame): @property def loc(self) -> _LocIndexerSeries[S1]: ... # Methods + @overload def add( - self, + self: Series[Never], other: ( - Sequence[S1] + Sequence | np_ndarray_anyint | np_ndarray_float | np_ndarray_complex - | Series[S1] + | Series | Scalar ), level: Level | None = ..., fill_value: float | None = ..., axis: int = ..., + ) -> Series: ... + @overload + def add( + self: Series[int], + other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + level: Level | None = ..., + fill_value: float | None = ..., + axis: int = ..., + ) -> Series[_T_COMPLEX]: ... + @overload + def add( + self: Series[int], + other: np_ndarray_anyint, + level: Level | None = ..., + fill_value: float | None = ..., + axis: int = ..., + ) -> Series[int]: ... + @overload + def add( + self: Series[int], + other: np_ndarray_float, + level: Level | None = ..., + fill_value: float | None = ..., + axis: int = ..., + ) -> Series[float]: ... + @overload + def add( + self: Series[int], + other: np_ndarray_complex, + level: Level | None = ..., + fill_value: float | None = ..., + axis: int = ..., + ) -> Series[complex]: ... + @overload + def add( + self, + other: Series[S1] | Scalar, + level: Level | None = ..., + fill_value: float | None = ..., + axis: int = ..., ) -> Series[S1]: ... def all( self, @@ -1998,19 +2076,60 @@ class Series(IndexOpsMixin[S1], NDFrame): min_count: int = ..., **kwargs: Any, ) -> Scalar: ... + @overload def radd( - self, + self: Series[Never], other: ( - Sequence[S1] + Sequence | np_ndarray_anyint | np_ndarray_float | np_ndarray_complex - | Series[S1] + | Series | Scalar ), level: Level | None = ..., fill_value: float | None = ..., axis: AxisIndex = ..., + ) -> Series: ... + @overload + def radd( + self: Series[int], + other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + level: Level | None = ..., + fill_value: float | None = ..., + axis: int = ..., + ) -> Series[_T_COMPLEX]: ... + @overload + def radd( + self: Series[int], + other: np_ndarray_anyint, + level: Level | None = ..., + fill_value: float | None = ..., + axis: int = ..., + ) -> Series[int]: ... + @overload + def radd( + self: Series[int], + other: np_ndarray_float, + level: Level | None = ..., + fill_value: float | None = ..., + axis: int = ..., + ) -> Series[float]: ... + @overload + def radd( + self: Series[int], + other: np_ndarray_complex, + level: Level | None = ..., + fill_value: float | None = ..., + axis: int = ..., + ) -> Series[complex]: ... + @overload + def radd( + self, + other: Series[S1] | Scalar, + level: Level | None = ..., + fill_value: float | None = ..., + axis: AxisIndex = ..., ) -> Series[S1]: ... def rdivmod( self, diff --git a/tests/series/arithmetic/int/test_add.py b/tests/series/arithmetic/int/test_add.py index 1b6b75ced..7407444dc 100644 --- a/tests/series/arithmetic/int/test_add.py +++ b/tests/series/arithmetic/int/test_add.py @@ -1,5 +1,6 @@ from typing import assert_type +import numpy as np import pandas as pd from tests import check @@ -11,94 +12,85 @@ def test_add_py_scalar() -> None: """Test pd.Series[int] + Python native scalars""" i, f, c = 1, 1.0, 1j - check(assert_type(left + i, "pd.Series[int]"), pd.Series, int) - # check(assert_type(left + f, "pd.Series[float]"), pd.Series, float) - # check(assert_type(left + c, "pd.Series[complex]"), pd.Series, complex) + check(assert_type(left + i, "pd.Series[int]"), pd.Series, np.int64) + check(assert_type(left + f, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left + c, "pd.Series[complex]"), pd.Series, np.complex128) - check(assert_type(i + left, "pd.Series[int]"), pd.Series, int) - # check(assert_type(f + left, "pd.Series[float]"), pd.Series, float) - # check(assert_type(c + left, "pd.Series[complex]"), pd.Series, complex) + check(assert_type(i + left, "pd.Series[int]"), pd.Series, np.int64) + check(assert_type(f + left, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(c + left, "pd.Series[complex]"), pd.Series, np.complex128) - check(assert_type(left.add(i), "pd.Series[int]"), pd.Series, int) - # check(assert_type(left.add(f), "pd.Series[float]"), pd.Series, float) - # check(assert_type(left.add(c), "pd.Series[complex]"), pd.Series, complex) + check(assert_type(left.add(i), "pd.Series[int]"), pd.Series, np.int64) + check(assert_type(left.add(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.add(c), "pd.Series[complex]"), pd.Series, np.complex128) - check(assert_type(left.radd(i), "pd.Series[int]"), pd.Series, int) - - -# check(assert_type(left.radd(f), "pd.Series[float]"), pd.Series, float) -# check(assert_type(left.radd(c), "pd.Series[complex]"), pd.Series, complex) + check(assert_type(left.radd(i), "pd.Series[int]"), pd.Series, np.int64) + check(assert_type(left.radd(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.radd(c), "pd.Series[complex]"), pd.Series, np.complex128) def test_add_py_sequence() -> None: """Test pd.Series[int] + Python native sequence""" i, f, c = [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] - check(assert_type(left + i, "pd.Series[int]"), pd.Series, int) - # check(assert_type(left + f, "pd.Series[float]"), pd.Series, float) - # check(assert_type(left + c, "pd.Series[complex]"), pd.Series, complex) - - # check(assert_type(i + left, "pd.Series[int]"), pd.Series, int) - # check(assert_type(f + left, "pd.Series[float]"), pd.Series, float) - # check(assert_type(c + left, "pd.Series[complex]"), pd.Series, complex) + check(assert_type(left + i, "pd.Series[int]"), pd.Series, np.int64) + check(assert_type(left + f, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left + c, "pd.Series[complex]"), pd.Series, np.complex128) - check(assert_type(left.add(i), "pd.Series[int]"), pd.Series, int) + check(assert_type(i + left, "pd.Series[int]"), pd.Series, np.int64) + check(assert_type(f + left, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(c + left, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.add(i), "pd.Series[int]"), pd.Series, np.int64) + check(assert_type(left.add(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.add(c), "pd.Series[complex]"), pd.Series, np.complex128) -# check(assert_type(left.add(f), "pd.Series[float]"), pd.Series, float) -# check(assert_type(left.add(c), "pd.Series[complex]"), pd.Series, complex) + check(assert_type(left.radd(i), "pd.Series[int]"), pd.Series, np.int64) + check(assert_type(left.radd(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.radd(c), "pd.Series[complex]"), pd.Series, np.complex128) -# check(assert_type(left.radd(i), "pd.Series[int]"), pd.Series, int) -# check(assert_type(left.radd(f), "pd.Series[int]"), pd.Series, int) -# check(assert_type(left.radd(c), "pd.Series[complex]"), pd.Series, complex) +def test_add_numpy_array() -> None: + """Test pd.Series[int] + numpy array""" + 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) -# def test_add_numpy_array() -> None: -# """Test pd.Series[int] + numpy array""" -# 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.complex64) + check(assert_type(left + i, "pd.Series[int]"), pd.Series, np.int64) + check(assert_type(left + f, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left + c, "pd.Series[complex]"), pd.Series, np.complex128) -# check(assert_type(left + i, "pd.Series[int]"), pd.Series, int) -# check(assert_type(left + f, "pd.Series[float]"), pd.Series, float) -# check(assert_type(left + c, "pd.Series[complex]"), pd.Series, complex) + # check(assert_type(i + l, "pd.Series[int]"), pd.Series, np.int64) + # check(assert_type(f + l, "pd.Series[float]"), pd.Series, np.float64) + # check(assert_type(c + l, "pd.Series[complex]"), pd.Series, np.complex128) -# # check(assert_type(i + l, "pd.Series[int]"), pd.Series, int) -# # check(assert_type(f + l, "pd.Series[float]"), pd.Series, float) -# # check(assert_type(c + l, "pd.Series[complex]"), pd.Series, complex) + check(assert_type(left.add(i), "pd.Series[int]"), pd.Series, np.int64) + check(assert_type(left.add(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.add(c), "pd.Series[complex]"), pd.Series, np.complex128) -# check(assert_type(left.add(i), "pd.Series[int]"), pd.Series, int) -# check(assert_type(left.add(f), "pd.Series[float]"), pd.Series, float) -# check(assert_type(left.add(c), "pd.Series[complex]"), pd.Series, complex) - -# check(assert_type(left.radd(i), "pd.Series[int]"), pd.Series, int) -# check(assert_type(left.radd(f), "pd.Series[float]"), pd.Series, float) -# check(assert_type(left.radd(c), "pd.Series[complex]"), pd.Series, complex) + check(assert_type(left.radd(i), "pd.Series[int]"), pd.Series, np.int64) + check(assert_type(left.radd(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.radd(c), "pd.Series[complex]"), pd.Series, np.complex128) def test_add_pd_series() -> None: """Test pd.Series[int] + pandas series""" i = pd.Series([2, 3, 5]) - # f = pd.Series([1.0, 2.0, 3.0]) - # c = pd.Series([1.1j, 2.2j, 4.1j]) - - check(assert_type(left + i, "pd.Series[int]"), pd.Series, int) - # check(assert_type(left + f, "pd.Series[float]"), pd.Series, float) - # check(assert_type(left + c, "pd.Series[complex]"), pd.Series, complex) - - # check( - # assert_type(i + left, pd.Series), "pd.Series[int]"), pd.Series, int) - # check( - # assert_type(f + left, "pd.Series[float]"), pd.Series, float) - # check( - # assert_type(c + left, pd.Series), "pd.Series[complex]"), pd.Series, complex) + f = pd.Series([1.0, 2.0, 3.0]) + c = pd.Series([1.1j, 2.2j, 4.1j]) - check(assert_type(left.add(i), "pd.Series[int]"), pd.Series, int) - # check(assert_type(left.add(f), "pd.Series[float]"), pd.Series, float) - # check(assert_type(left.add(c), "pd.Series[complex]"), pd.Series, complex) + check(assert_type(left + i, "pd.Series[int]"), pd.Series, np.int64) + check(assert_type(left + f, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left + c, "pd.Series[complex]"), pd.Series, np.complex128) - check(assert_type(left.radd(i), "pd.Series[int]"), pd.Series, int) + check(assert_type(i + left, "pd.Series[int]"), pd.Series, np.int64) + check(assert_type(f + left, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(c + left, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.add(i), "pd.Series[int]"), pd.Series, np.int64) + check(assert_type(left.add(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.add(c), "pd.Series[complex]"), pd.Series, np.complex128) -# check(assert_type(left.radd(f), "pd.Series[float]"), pd.Series, float) -# check(assert_type(left.radd(c), "pd.Series[complex]"), pd.Series, complex) + check(assert_type(left.radd(i), "pd.Series[int]"), pd.Series, np.int64) + check(assert_type(left.radd(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.radd(c), "pd.Series[complex]"), pd.Series, np.complex128) diff --git a/tests/series/arithmetic/test_add.py b/tests/series/arithmetic/test_add.py index 2d2c5916a..e833fb053 100644 --- a/tests/series/arithmetic/test_add.py +++ b/tests/series/arithmetic/test_add.py @@ -79,22 +79,13 @@ def test_add_pd_series() -> None: f = pd.Series([1.0, 2.0, 3.0]) c = pd.Series([1.1j, 2.2j, 4.1j]) - # check(assert_type(left + i, pd.Series), pd.Series) # why? + check(assert_type(left + i, pd.Series), pd.Series) check(assert_type(left + f, pd.Series), pd.Series) check(assert_type(left + c, pd.Series), pd.Series) - check( - assert_type(i + left, pd.Series), # pyright: ignore[reportAssertTypeFailure] - pd.Series, - ) - check( - assert_type(f + left, pd.Series), # pyright: ignore[reportAssertTypeFailure] - pd.Series, - ) - check( - assert_type(c + left, pd.Series), # pyright: ignore[reportAssertTypeFailure] - pd.Series, - ) + check(assert_type(i + left, pd.Series), pd.Series) + check(assert_type(f + left, pd.Series), pd.Series) + check(assert_type(c + left, pd.Series), pd.Series) check(assert_type(left.add(i), pd.Series), pd.Series) check(assert_type(left.add(f), pd.Series), pd.Series) diff --git a/tests/series/test_series.py b/tests/series/test_series.py index 8c691f940..ff79c6ada 100644 --- a/tests/series/test_series.py +++ b/tests/series/test_series.py @@ -1604,10 +1604,7 @@ def test_series_min_max_sub_axis() -> None: ss = s1 - s2 sm = s1 * s2 sd = s1 / s2 - check( - assert_type(sa, pd.Series), # pyright: ignore[reportAssertTypeFailure] # why? - pd.Series, - ) + check(assert_type(sa, pd.Series), pd.Series) check(assert_type(ss, pd.Series), pd.Series) check(assert_type(sm, pd.Series), pd.Series) check(assert_type(sd, pd.Series), pd.Series) diff --git a/tests/test_frame.py b/tests/test_frame.py index e4a1fde1b..2973d25cb 100644 --- a/tests/test_frame.py +++ b/tests/test_frame.py @@ -2819,25 +2819,9 @@ def test_sum_get_add() -> None: summer = df.sum(axis=1) check(assert_type(summer, pd.Series), pd.Series) - check( - assert_type( - s + summer, pd.Series # pyright: ignore[reportAssertTypeFailure] # why? - ), - pd.Series, - ) - check( - assert_type( - s + df["y"], pd.Series # pyright: ignore[reportAssertTypeFailure] # why? - ), - pd.Series, - ) - check( - assert_type( - summer + summer, # pyright: ignore[reportAssertTypeFailure] # why? - pd.Series, - ), - pd.Series, - ) + check(assert_type(s + summer, pd.Series), pd.Series) + check(assert_type(s + df["y"], pd.Series), pd.Series) + check(assert_type(summer + summer, pd.Series), pd.Series) def test_getset_untyped() -> None: From 566d8ec2c0ccafdbe5282136dfc7726511a668ee Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Tue, 15 Jul 2025 17:03:18 +0200 Subject: [PATCH 03/10] feat: Series[float] + --- pandas-stubs/core/series.pyi | 66 +++++++++++++++- tests/series/arithmetic/float/__init__.py | 0 tests/series/arithmetic/float/test_add.py | 96 +++++++++++++++++++++++ 3 files changed, 160 insertions(+), 2 deletions(-) create mode 100644 tests/series/arithmetic/float/__init__.py create mode 100644 tests/series/arithmetic/float/test_add.py diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index ecab3153a..fd06789f8 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -1643,13 +1643,21 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def __add__( self: Series[float], - other: int | Sequence[int] | np_ndarray_anyint | Series[int], + other: int | Sequence[int] | np_ndarray_anyint | np_ndarray_float | Series[int], ) -> Series[float]: ... @overload + def __add__( + self: Series[float], + other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + ) -> Series[_T_COMPLEX]: ... + @overload + def __add__(self: Series[float], other: np_ndarray_complex) -> Series[complex]: ... + @overload def __add__(self: Series[complex], other: Series[Never]) -> Series: ... @overload def __add__( - self: Series[complex], other: int | Sequence[int] | Series[int] + self: Series[complex], + other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], ) -> Series[complex]: ... @overload def __add__(self, other: S1 | Self) -> Self: ... @@ -1706,6 +1714,12 @@ class Series(IndexOpsMixin[S1], NDFrame): self: Series[int], other: _T_COMPLEX | Sequence[_T_COMPLEX] ) -> Series[_T_COMPLEX]: ... @overload + def __radd__(self: Series[float], other: int | Sequence[int]) -> Series[float]: ... + @overload + def __radd__( + self: Series[float], other: _T_COMPLEX | Sequence[_T_COMPLEX] + ) -> Series[_T_COMPLEX]: ... + @overload def __radd__(self, other: S1 | Series[S1]) -> Self: ... @overload def __radd__(self, other: num | _str | _ListLike | Series) -> Series: ... @@ -1832,6 +1846,30 @@ class Series(IndexOpsMixin[S1], NDFrame): axis: int = ..., ) -> Series[complex]: ... @overload + def add( + self: Series[float], + other: int | Sequence[int] | np_ndarray_anyint | np_ndarray_float | Series[int], + level: Level | None = ..., + fill_value: float | None = ..., + axis: int = ..., + ) -> Series[float]: ... + @overload + def add( + self: Series[float], + other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + level: Level | None = ..., + fill_value: float | None = ..., + axis: int = ..., + ) -> Series[_T_COMPLEX]: ... + @overload + def add( + self: Series[float], + other: np_ndarray_complex, + level: Level | None = ..., + fill_value: float | None = ..., + axis: int = ..., + ) -> Series[complex]: ... + @overload def add( self, other: Series[S1] | Scalar, @@ -2124,6 +2162,30 @@ class Series(IndexOpsMixin[S1], NDFrame): axis: int = ..., ) -> Series[complex]: ... @overload + def radd( + self: Series[float], + other: int | Sequence[int] | np_ndarray_anyint | np_ndarray_float | Series[int], + level: Level | None = ..., + fill_value: float | None = ..., + axis: int = ..., + ) -> Series[float]: ... + @overload + def radd( + self: Series[float], + other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + level: Level | None = ..., + fill_value: float | None = ..., + axis: int = ..., + ) -> Series[_T_COMPLEX]: ... + @overload + def radd( + self: Series[float], + other: np_ndarray_complex, + level: Level | None = ..., + fill_value: float | None = ..., + axis: int = ..., + ) -> Series[complex]: ... + @overload def radd( self, other: Series[S1] | Scalar, diff --git a/tests/series/arithmetic/float/__init__.py b/tests/series/arithmetic/float/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/series/arithmetic/float/test_add.py b/tests/series/arithmetic/float/test_add.py new file mode 100644 index 000000000..b5651e022 --- /dev/null +++ b/tests/series/arithmetic/float/test_add.py @@ -0,0 +1,96 @@ +from typing import assert_type + +import numpy as np +import pandas as pd + +from tests import check + +left = pd.Series([1.0, 2.0, 3.0]) # left operand + + +def test_add_py_scalar() -> None: + """Test pd.Series[float] + Python native scalars""" + i, f, c = 1, 1.0, 1j + + check(assert_type(left + i, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left + f, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left + c, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(i + left, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(f + left, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(c + left, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.add(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.add(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.add(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.radd(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.radd(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.radd(c), "pd.Series[complex]"), pd.Series, np.complex128) + + +def test_add_py_sequence() -> None: + """Test pd.Series[float] + Python native sequence""" + i, f, c = [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] + + check(assert_type(left + i, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left + f, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left + c, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(i + left, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(f + left, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(c + left, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.add(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.add(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.add(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.radd(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.radd(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.radd(c), "pd.Series[complex]"), pd.Series, np.complex128) + + +def test_add_numpy_array() -> None: + """Test pd.Series[float] + numpy array""" + 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, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left + f, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left + c, "pd.Series[complex]"), pd.Series, np.complex128) + + # check(assert_type(i + l, "pd.Series[float]"), pd.Series, np.float64) + # check(assert_type(f + l, "pd.Series[float]"), pd.Series, np.float64) + # check(assert_type(c + l, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.add(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.add(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.add(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.radd(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.radd(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.radd(c), "pd.Series[complex]"), pd.Series, np.complex128) + + +def test_add_pd_series() -> None: + """Test pd.Series[float] + pandas series""" + i = pd.Series([2, 3, 5]) + f = pd.Series([1.0, 2.0, 3.0]) + c = pd.Series([1.1j, 2.2j, 4.1j]) + + check(assert_type(left + i, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left + f, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left + c, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(i + left, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(f + left, "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(c + left, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.add(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.add(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.add(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.radd(i), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.radd(f), "pd.Series[float]"), pd.Series, np.float64) + check(assert_type(left.radd(c), "pd.Series[complex]"), pd.Series, np.complex128) From 2581638d5d567a08267aec93a68cda456cf44efc Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Tue, 15 Jul 2025 17:14:12 +0200 Subject: [PATCH 04/10] refactor: py310 and remove why --- tests/series/arithmetic/float/test_add.py | 3 +-- tests/series/arithmetic/int/test_add.py | 3 +-- tests/series/arithmetic/test_add.py | 7 +++---- tests/series/test_series.py | 2 +- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/tests/series/arithmetic/float/test_add.py b/tests/series/arithmetic/float/test_add.py index b5651e022..4ecdd744c 100644 --- a/tests/series/arithmetic/float/test_add.py +++ b/tests/series/arithmetic/float/test_add.py @@ -1,7 +1,6 @@ -from typing import assert_type - import numpy as np import pandas as pd +from typing_extensions import assert_type from tests import check diff --git a/tests/series/arithmetic/int/test_add.py b/tests/series/arithmetic/int/test_add.py index 7407444dc..bb4aec791 100644 --- a/tests/series/arithmetic/int/test_add.py +++ b/tests/series/arithmetic/int/test_add.py @@ -1,7 +1,6 @@ -from typing import assert_type - import numpy as np import pandas as pd +from typing_extensions import assert_type from tests import check diff --git a/tests/series/arithmetic/test_add.py b/tests/series/arithmetic/test_add.py index e833fb053..e1d054d25 100644 --- a/tests/series/arithmetic/test_add.py +++ b/tests/series/arithmetic/test_add.py @@ -1,7 +1,6 @@ -from typing import assert_type - import numpy as np import pandas as pd +from typing_extensions import assert_type from tests import check @@ -12,7 +11,7 @@ def test_add_py_scalar() -> None: """Test pd.Series[Any] + Python native scalars""" i, f, c = 1, 1.0, 1j - # check(assert_type(left + i, pd.Series), pd.Series) # why? + check(assert_type(left + i, pd.Series), pd.Series) check(assert_type(left + f, pd.Series), pd.Series) check(assert_type(left + c, pd.Series), pd.Series) @@ -33,7 +32,7 @@ def test_add_py_sequence() -> None: """Test pd.Series[Any] + Python native sequence""" i, f, c = [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] - # check(assert_type(left + i, pd.Series), pd.Series) # why? + check(assert_type(left + i, pd.Series), pd.Series) check(assert_type(left + f, pd.Series), pd.Series) check(assert_type(left + c, pd.Series), pd.Series) diff --git a/tests/series/test_series.py b/tests/series/test_series.py index ff79c6ada..f58d651f4 100644 --- a/tests/series/test_series.py +++ b/tests/series/test_series.py @@ -3902,7 +3902,7 @@ def foo(sf: pd.Series) -> None: pass foo(s) - # check(assert_type(s + pd.Series([1]), pd.Series), pd.Series) # why? + check(assert_type(s + pd.Series([1]), pd.Series), pd.Series) def test_series_items() -> None: From 6f8e00a0755b88b419972a5db5dc80c6799b5001 Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Tue, 15 Jul 2025 18:56:50 +0200 Subject: [PATCH 05/10] feat: Series[complex] + --- pandas-stubs/core/series.pyi | 41 ++++++++- tests/series/arithmetic/complex/__init__.py | 0 tests/series/arithmetic/complex/test_add.py | 95 +++++++++++++++++++++ 3 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 tests/series/arithmetic/complex/__init__.py create mode 100644 tests/series/arithmetic/complex/test_add.py diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index fd06789f8..6707bf968 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -1657,7 +1657,14 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def __add__( self: Series[complex], - other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX], + other: ( + _T_COMPLEX + | Sequence[_T_COMPLEX] + | Series[_T_COMPLEX] + | np_ndarray_anyint + | np_ndarray_float + | np_ndarray_complex + ), ) -> Series[complex]: ... @overload def __add__(self, other: S1 | Self) -> Self: ... @@ -1720,6 +1727,10 @@ class Series(IndexOpsMixin[S1], NDFrame): self: Series[float], other: _T_COMPLEX | Sequence[_T_COMPLEX] ) -> Series[_T_COMPLEX]: ... @overload + def __radd__( + self: Series[complex], other: _T_COMPLEX | Sequence[_T_COMPLEX] + ) -> Series[complex]: ... + @overload def __radd__(self, other: S1 | Series[S1]) -> Self: ... @overload def __radd__(self, other: num | _str | _ListLike | Series) -> Series: ... @@ -1870,6 +1881,20 @@ class Series(IndexOpsMixin[S1], NDFrame): axis: int = ..., ) -> Series[complex]: ... @overload + def add( + self: Series[complex], + other: ( + Sequence[_T_COMPLEX] + | np_ndarray_anyint + | np_ndarray_float + | np_ndarray_complex + | Series[_T_COMPLEX] + ), + level: Level | None = ..., + fill_value: float | None = ..., + axis: int = ..., + ) -> Series[complex]: ... + @overload def add( self, other: Series[S1] | Scalar, @@ -2186,6 +2211,20 @@ class Series(IndexOpsMixin[S1], NDFrame): axis: int = ..., ) -> Series[complex]: ... @overload + def radd( + self: Series[complex], + other: ( + Sequence[_T_COMPLEX] + | np_ndarray_anyint + | np_ndarray_float + | np_ndarray_complex + | Series[_T_COMPLEX] + ), + level: Level | None = ..., + fill_value: float | None = ..., + axis: int = ..., + ) -> Series[complex]: ... + @overload def radd( self, other: Series[S1] | Scalar, diff --git a/tests/series/arithmetic/complex/__init__.py b/tests/series/arithmetic/complex/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/series/arithmetic/complex/test_add.py b/tests/series/arithmetic/complex/test_add.py new file mode 100644 index 000000000..3b0f910bf --- /dev/null +++ b/tests/series/arithmetic/complex/test_add.py @@ -0,0 +1,95 @@ +import numpy as np +import pandas as pd +from typing_extensions import assert_type + +from tests import check + +left = pd.Series([1j, 2j, 3j]) # left operand + + +def test_add_py_scalar() -> None: + """Test pd.Series[complex] + Python native scalars""" + i, f, c = 1, 1.0, 1j + + check(assert_type(left + i, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left + f, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left + c, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(i + left, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(f + left, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(c + left, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.add(i), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.add(f), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.add(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.radd(i), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.radd(f), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.radd(c), "pd.Series[complex]"), pd.Series, np.complex128) + + +def test_add_py_sequence() -> None: + """Test pd.Series[complex] + Python native sequence""" + i, f, c = [2, 3, 5], [1.0, 2.0, 3.0], [1j, 1j, 4j] + + check(assert_type(left + i, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left + f, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left + c, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(i + left, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(f + left, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(c + left, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.add(i), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.add(f), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.add(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.radd(i), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.radd(f), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.radd(c), "pd.Series[complex]"), pd.Series, np.complex128) + + +def test_add_numpy_array() -> None: + """Test pd.Series[complex] + numpy array""" + 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, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left + f, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left + c, "pd.Series[complex]"), pd.Series, np.complex128) + + # check(assert_type(i + l, "pd.Series[complex]"), pd.Series, np.complex128) + # check(assert_type(f + l, "pd.Series[complex]"), pd.Series, np.complex128) + # check(assert_type(c + l, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.add(i), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.add(f), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.add(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.radd(i), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.radd(f), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.radd(c), "pd.Series[complex]"), pd.Series, np.complex128) + + +def test_add_pd_series() -> None: + """Test pd.Series[complex] + pandas series""" + i = pd.Series([2, 3, 5]) + f = pd.Series([1.0, 2.0, 3.0]) + c = pd.Series([1.1j, 2.2j, 4.1j]) + + check(assert_type(left + i, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left + f, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left + c, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(i + left, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(f + left, "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(c + left, "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.add(i), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.add(f), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.add(c), "pd.Series[complex]"), pd.Series, np.complex128) + + check(assert_type(left.radd(i), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.radd(f), "pd.Series[complex]"), pd.Series, np.complex128) + check(assert_type(left.radd(c), "pd.Series[complex]"), pd.Series, np.complex128) From 7fa0a3edbe1288e435ae0eacc66ad9ba027aa77a Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Wed, 16 Jul 2025 22:05:59 +0200 Subject: [PATCH 06/10] fix(comment): https://github.com/pandas-dev/pandas-stubs/pull/1275#discussion_r2211363732 --- pandas-stubs/core/series.pyi | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index 6707bf968..fbe925b7e 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -1627,7 +1627,7 @@ class Series(IndexOpsMixin[S1], NDFrame): other: num | _str | timedelta | Timedelta | _ListLike | Series | np.timedelta64, ) -> Series: ... @overload - def __add__(self: Series[int], other: Series[Never]) -> Series: ... + def __add__(self: Series, other: Series[Never]) -> Series: ... @overload def __add__( self: Series[int], other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX] @@ -1639,8 +1639,6 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def __add__(self: Series[int], other: np_ndarray_complex) -> Series[complex]: ... @overload - def __add__(self: Series[float], other: Series[Never]) -> Series: ... - @overload def __add__( self: Series[float], other: int | Sequence[int] | np_ndarray_anyint | np_ndarray_float | Series[int], @@ -1653,8 +1651,6 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def __add__(self: Series[float], other: np_ndarray_complex) -> Series[complex]: ... @overload - def __add__(self: Series[complex], other: Series[Never]) -> Series: ... - @overload def __add__( self: Series[complex], other: ( From caa271b6e93dfeddc8bba606ac7654183bef672f Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Wed, 16 Jul 2025 22:59:24 +0200 Subject: [PATCH 07/10] fix(comment): https://github.com/pandas-dev/pandas-stubs/pull/1275/files#r2211559024 --- pandas-stubs/core/series.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index fbe925b7e..7f9dfcb47 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -1724,7 +1724,7 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Series[_T_COMPLEX]: ... @overload def __radd__( - self: Series[complex], other: _T_COMPLEX | Sequence[_T_COMPLEX] + self: Series[complex], other: complex | Sequence[complex] ) -> Series[complex]: ... @overload def __radd__(self, other: S1 | Series[S1]) -> Self: ... From fe4e10a358efaa02b5ff3593463b08cf60f64ed7 Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Wed, 16 Jul 2025 23:20:05 +0200 Subject: [PATCH 08/10] fix(comment): https://github.com/pandas-dev/pandas-stubs/pull/1275/files#r2211571551 --- tests/series/arithmetic/complex/test_add.py | 25 ++++++++++++++++++--- tests/series/arithmetic/float/test_add.py | 25 ++++++++++++++++++--- tests/series/arithmetic/int/test_add.py | 25 ++++++++++++++++++--- tests/series/arithmetic/test_add.py | 22 +++++++++++++++--- 4 files changed, 85 insertions(+), 12 deletions(-) diff --git a/tests/series/arithmetic/complex/test_add.py b/tests/series/arithmetic/complex/test_add.py index 3b0f910bf..5c43763e0 100644 --- a/tests/series/arithmetic/complex/test_add.py +++ b/tests/series/arithmetic/complex/test_add.py @@ -59,9 +59,28 @@ def test_add_numpy_array() -> None: check(assert_type(left + f, "pd.Series[complex]"), pd.Series, np.complex128) check(assert_type(left + c, "pd.Series[complex]"), pd.Series, np.complex128) - # check(assert_type(i + l, "pd.Series[complex]"), pd.Series, np.complex128) - # check(assert_type(f + l, "pd.Series[complex]"), pd.Series, np.complex128) - # check(assert_type(c + l, "pd.Series[complex]"), pd.Series, np.complex128) + # numpy typing gives ndarray instead of `pd.Series[...]` in reality, which we cannot fix + check( + assert_type( # type: ignore[assert-type] + i + left, "pd.Series[complex]" # pyright: ignore[reportAssertTypeFailure] + ), + pd.Series, + np.complex128, + ) + check( + assert_type( # type: ignore[assert-type] + f + left, "pd.Series[complex]" # pyright: ignore[reportAssertTypeFailure] + ), + pd.Series, + np.complex128, + ) + check( + assert_type( # type: ignore[assert-type] + c + left, "pd.Series[complex]" # pyright: ignore[reportAssertTypeFailure] + ), + pd.Series, + np.complex128, + ) check(assert_type(left.add(i), "pd.Series[complex]"), pd.Series, np.complex128) check(assert_type(left.add(f), "pd.Series[complex]"), pd.Series, np.complex128) diff --git a/tests/series/arithmetic/float/test_add.py b/tests/series/arithmetic/float/test_add.py index 4ecdd744c..16085f366 100644 --- a/tests/series/arithmetic/float/test_add.py +++ b/tests/series/arithmetic/float/test_add.py @@ -59,9 +59,28 @@ def test_add_numpy_array() -> None: check(assert_type(left + f, "pd.Series[float]"), pd.Series, np.float64) check(assert_type(left + c, "pd.Series[complex]"), pd.Series, np.complex128) - # check(assert_type(i + l, "pd.Series[float]"), pd.Series, np.float64) - # check(assert_type(f + l, "pd.Series[float]"), pd.Series, np.float64) - # check(assert_type(c + l, "pd.Series[complex]"), pd.Series, np.complex128) + # numpy typing gives ndarray instead of `pd.Series[...]` in reality, which we cannot fix + check( + assert_type( # type: ignore[assert-type] + i + left, "pd.Series[float]" # pyright: ignore[reportAssertTypeFailure] + ), + pd.Series, + np.float64, + ) + check( + assert_type( # type: ignore[assert-type] + f + left, "pd.Series[float]" # pyright: ignore[reportAssertTypeFailure] + ), + pd.Series, + np.float64, + ) + check( + assert_type( # type: ignore[assert-type] + c + left, "pd.Series[complex]" # pyright: ignore[reportAssertTypeFailure] + ), + pd.Series, + np.complex128, + ) check(assert_type(left.add(i), "pd.Series[float]"), pd.Series, np.float64) check(assert_type(left.add(f), "pd.Series[float]"), pd.Series, np.float64) diff --git a/tests/series/arithmetic/int/test_add.py b/tests/series/arithmetic/int/test_add.py index bb4aec791..cb78181c6 100644 --- a/tests/series/arithmetic/int/test_add.py +++ b/tests/series/arithmetic/int/test_add.py @@ -59,9 +59,28 @@ def test_add_numpy_array() -> None: check(assert_type(left + f, "pd.Series[float]"), pd.Series, np.float64) check(assert_type(left + c, "pd.Series[complex]"), pd.Series, np.complex128) - # check(assert_type(i + l, "pd.Series[int]"), pd.Series, np.int64) - # check(assert_type(f + l, "pd.Series[float]"), pd.Series, np.float64) - # check(assert_type(c + l, "pd.Series[complex]"), pd.Series, np.complex128) + # numpy typing gives ndarray instead of `pd.Series[...]` in reality, which we cannot fix + check( + assert_type( # type: ignore[assert-type] + i + left, "pd.Series[int]" # pyright: ignore[reportAssertTypeFailure] + ), + pd.Series, + np.int64, + ) + check( + assert_type( # type: ignore[assert-type] + f + left, "pd.Series[float]" # pyright: ignore[reportAssertTypeFailure] + ), + pd.Series, + np.float64, + ) + check( + assert_type( # type: ignore[assert-type] + c + left, "pd.Series[complex]" # pyright: ignore[reportAssertTypeFailure] + ), + pd.Series, + np.complex128, + ) check(assert_type(left.add(i), "pd.Series[int]"), pd.Series, np.int64) check(assert_type(left.add(f), "pd.Series[float]"), pd.Series, np.float64) diff --git a/tests/series/arithmetic/test_add.py b/tests/series/arithmetic/test_add.py index e1d054d25..0001f6ec7 100644 --- a/tests/series/arithmetic/test_add.py +++ b/tests/series/arithmetic/test_add.py @@ -59,9 +59,25 @@ def test_add_numpy_array() -> None: check(assert_type(left + f, pd.Series), pd.Series) check(assert_type(left + c, pd.Series), pd.Series) - # check(assert_type(i + l, pd.Series), pd.Series) - # check(assert_type(f + l, pd.Series), pd.Series) - # check(assert_type(c + l, pd.Series), pd.Series) + # numpy typing gives ndarray instead of `pd.Series[...]` in reality, which we cannot fix + check( + assert_type( # type: ignore[assert-type] + i + left, pd.Series # pyright: ignore[reportAssertTypeFailure] + ), + pd.Series, + ) + check( + assert_type( # type: ignore[assert-type] + f + left, pd.Series # pyright: ignore[reportAssertTypeFailure] + ), + pd.Series, + ) + check( + assert_type( # type: ignore[assert-type] + c + left, pd.Series # pyright: ignore[reportAssertTypeFailure] + ), + pd.Series, + ) check(assert_type(left.add(i), pd.Series), pd.Series) check(assert_type(left.add(f), pd.Series), pd.Series) From 25766407f6b7f6cb27bc1283598a091b854e2d71 Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Mon, 28 Jul 2025 12:10:16 +0200 Subject: [PATCH 09/10] fix(comment): argument types https://github.com/pandas-dev/pandas-stubs/pull/1275#pullrequestreview-3053086297 --- pandas-stubs/core/series.pyi | 41 ++++++++---------------------------- 1 file changed, 9 insertions(+), 32 deletions(-) diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index 7f9dfcb47..631709b80 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -1624,10 +1624,10 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def __add__( self: Series[Never], - other: num | _str | timedelta | Timedelta | _ListLike | Series | np.timedelta64, + other: Scalar | _ListLike | Series, ) -> Series: ... @overload - def __add__(self: Series, other: Series[Never]) -> Series: ... + def __add__(self, other: Series[Never]) -> Series: ... @overload def __add__( self: Series[int], other: _T_COMPLEX | Sequence[_T_COMPLEX] | Series[_T_COMPLEX] @@ -1664,11 +1664,6 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Series[complex]: ... @overload def __add__(self, other: S1 | Self) -> Self: ... - @overload - def __add__( - self, - other: num | _str | timedelta | Timedelta | _ListLike | Series | np.timedelta64, - ) -> Series: ... # ignore needed for mypy as we want different results based on the arguments @overload # type: ignore[override] def __and__( # pyright: ignore[reportOverlappingOverload] @@ -1709,9 +1704,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def __or__(self, other: int | np_ndarray_anyint | Series[int]) -> Series[int]: ... @overload - def __radd__( - self: Series[Never], other: num | _str | _ListLike | Series - ) -> Series: ... + def __radd__(self: Series[Never], other: Scalar | _ListLike | Series) -> Series: ... @overload def __radd__( self: Series[int], other: _T_COMPLEX | Sequence[_T_COMPLEX] @@ -1728,8 +1721,6 @@ class Series(IndexOpsMixin[S1], NDFrame): ) -> Series[complex]: ... @overload def __radd__(self, other: S1 | Series[S1]) -> Self: ... - @overload - def __radd__(self, other: num | _str | _ListLike | Series) -> Series: ... # ignore needed for mypy as we want different results based on the arguments @overload # type: ignore[override] def __rand__( # pyright: ignore[reportOverlappingOverload] @@ -1808,14 +1799,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def add( self: Series[Never], - other: ( - Sequence - | np_ndarray_anyint - | np_ndarray_float - | np_ndarray_complex - | Series - | Scalar - ), + other: Scalar | _ListLike | Series, level: Level | None = ..., fill_value: float | None = ..., axis: int = ..., @@ -1893,11 +1877,11 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def add( self, - other: Series[S1] | Scalar, + other: S1 | Series[S1], level: Level | None = ..., fill_value: float | None = ..., axis: int = ..., - ) -> Series[S1]: ... + ) -> Self: ... def all( self, axis: AxisIndex = ..., @@ -2138,14 +2122,7 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def radd( self: Series[Never], - other: ( - Sequence - | np_ndarray_anyint - | np_ndarray_float - | np_ndarray_complex - | Series - | Scalar - ), + other: Scalar | _ListLike | Series, level: Level | None = ..., fill_value: float | None = ..., axis: AxisIndex = ..., @@ -2223,11 +2200,11 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def radd( self, - other: Series[S1] | Scalar, + other: S1 | Series[S1], level: Level | None = ..., fill_value: float | None = ..., axis: AxisIndex = ..., - ) -> Series[S1]: ... + ) -> Self: ... def rdivmod( self, other: Series[S1] | Scalar, From 4f114052e106b9b7b9ff49cd43108c80387c8b91 Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Tue, 29 Jul 2025 10:29:21 +0200 Subject: [PATCH 10/10] fix(comment): https://github.com/pandas-dev/pandas-stubs/pull/1275#pullrequestreview-3064771853 --- pandas-stubs/core/series.pyi | 27 +++++++++++++++---- tests/series/arithmetic/complex/test_add.py | 29 +++++---------------- tests/series/arithmetic/float/test_add.py | 29 +++++---------------- tests/series/arithmetic/int/test_add.py | 25 +++++------------- tests/series/arithmetic/test_add.py | 22 +++++++--------- 5 files changed, 52 insertions(+), 80 deletions(-) diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index 631709b80..f9afa8115 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -1704,23 +1704,40 @@ class Series(IndexOpsMixin[S1], NDFrame): @overload def __or__(self, other: int | np_ndarray_anyint | Series[int]) -> Series[int]: ... @overload - def __radd__(self: Series[Never], other: Scalar | _ListLike | Series) -> Series: ... + def __radd__(self: Series[Never], other: Scalar | _ListLike) -> Series: ... @overload def __radd__( self: Series[int], other: _T_COMPLEX | Sequence[_T_COMPLEX] ) -> Series[_T_COMPLEX]: ... @overload - def __radd__(self: Series[float], other: int | Sequence[int]) -> Series[float]: ... + def __radd__(self: Series[int], other: np_ndarray_anyint) -> Series[int]: ... + @overload + def __radd__(self: Series[int], other: np_ndarray_float) -> Series[float]: ... + @overload + def __radd__(self: Series[int], other: np_ndarray_complex) -> Series[complex]: ... + @overload + def __radd__( + self: Series[float], + other: int | Sequence[int] | np_ndarray_anyint | np_ndarray_float, + ) -> Series[float]: ... @overload def __radd__( self: Series[float], other: _T_COMPLEX | Sequence[_T_COMPLEX] ) -> Series[_T_COMPLEX]: ... @overload + def __radd__(self: Series[float], other: np_ndarray_complex) -> Series[complex]: ... + @overload def __radd__( - self: Series[complex], other: complex | Sequence[complex] + self: Series[complex], + other: ( + np_ndarray_anyint + | np_ndarray_float + | np_ndarray_complex + | Sequence[_T_COMPLEX] + ), ) -> Series[complex]: ... @overload - def __radd__(self, other: S1 | Series[S1]) -> Self: ... + def __radd__(self, other: S1) -> Self: ... # ignore needed for mypy as we want different results based on the arguments @overload # type: ignore[override] def __rand__( # pyright: ignore[reportOverlappingOverload] @@ -2608,7 +2625,7 @@ class PeriodSeries(Series[Period]): ) -> Never: ... class OffsetSeries(Series[BaseOffset]): - @overload # type: ignore[override] + @overload def __radd__(self, other: Period) -> PeriodSeries: ... @overload def __radd__( # pyright: ignore[reportIncompatibleMethodOverride] diff --git a/tests/series/arithmetic/complex/test_add.py b/tests/series/arithmetic/complex/test_add.py index 5c43763e0..2ab7d1afc 100644 --- a/tests/series/arithmetic/complex/test_add.py +++ b/tests/series/arithmetic/complex/test_add.py @@ -1,4 +1,5 @@ import numpy as np +from numpy import typing as npt # noqa: F401 import pandas as pd from typing_extensions import assert_type @@ -59,28 +60,12 @@ def test_add_numpy_array() -> None: check(assert_type(left + f, "pd.Series[complex]"), pd.Series, np.complex128) check(assert_type(left + c, "pd.Series[complex]"), pd.Series, np.complex128) - # numpy typing gives ndarray instead of `pd.Series[...]` in reality, which we cannot fix - check( - assert_type( # type: ignore[assert-type] - i + left, "pd.Series[complex]" # pyright: ignore[reportAssertTypeFailure] - ), - pd.Series, - np.complex128, - ) - check( - assert_type( # type: ignore[assert-type] - f + left, "pd.Series[complex]" # pyright: ignore[reportAssertTypeFailure] - ), - pd.Series, - np.complex128, - ) - check( - assert_type( # type: ignore[assert-type] - c + left, "pd.Series[complex]" # pyright: ignore[reportAssertTypeFailure] - ), - pd.Series, - np.complex128, - ) + # `numpy` typing gives the corresponding `ndarray`s in the static type + # checking, where our `__radd__` cannot override. At runtime, they return + # `Series`s with the correct element type. + check(assert_type(i + left, "npt.NDArray[np.int64]"), pd.Series, np.complex128) + check(assert_type(f + left, "npt.NDArray[np.float64]"), pd.Series, np.complex128) + check(assert_type(c + left, "npt.NDArray[np.complex128]"), pd.Series, np.complex128) check(assert_type(left.add(i), "pd.Series[complex]"), pd.Series, np.complex128) check(assert_type(left.add(f), "pd.Series[complex]"), pd.Series, np.complex128) diff --git a/tests/series/arithmetic/float/test_add.py b/tests/series/arithmetic/float/test_add.py index 16085f366..61b77742c 100644 --- a/tests/series/arithmetic/float/test_add.py +++ b/tests/series/arithmetic/float/test_add.py @@ -1,4 +1,5 @@ import numpy as np +from numpy import typing as npt # noqa: F401 import pandas as pd from typing_extensions import assert_type @@ -59,28 +60,12 @@ def test_add_numpy_array() -> None: check(assert_type(left + f, "pd.Series[float]"), pd.Series, np.float64) check(assert_type(left + c, "pd.Series[complex]"), pd.Series, np.complex128) - # numpy typing gives ndarray instead of `pd.Series[...]` in reality, which we cannot fix - check( - assert_type( # type: ignore[assert-type] - i + left, "pd.Series[float]" # pyright: ignore[reportAssertTypeFailure] - ), - pd.Series, - np.float64, - ) - check( - assert_type( # type: ignore[assert-type] - f + left, "pd.Series[float]" # pyright: ignore[reportAssertTypeFailure] - ), - pd.Series, - np.float64, - ) - check( - assert_type( # type: ignore[assert-type] - c + left, "pd.Series[complex]" # pyright: ignore[reportAssertTypeFailure] - ), - pd.Series, - np.complex128, - ) + # `numpy` typing gives the corresponding `ndarray`s in the static type + # checking, where our `__radd__` cannot override. At runtime, they return + # `Series`s with the correct element type. + check(assert_type(i + left, "npt.NDArray[np.int64]"), pd.Series, np.float64) + check(assert_type(f + left, "npt.NDArray[np.float64]"), pd.Series, np.float64) + check(assert_type(c + left, "npt.NDArray[np.complex128]"), pd.Series, np.complex128) check(assert_type(left.add(i), "pd.Series[float]"), pd.Series, np.float64) check(assert_type(left.add(f), "pd.Series[float]"), pd.Series, np.float64) diff --git a/tests/series/arithmetic/int/test_add.py b/tests/series/arithmetic/int/test_add.py index cb78181c6..ad25aeb30 100644 --- a/tests/series/arithmetic/int/test_add.py +++ b/tests/series/arithmetic/int/test_add.py @@ -1,4 +1,5 @@ import numpy as np +from numpy import typing as npt # noqa: F401 import pandas as pd from typing_extensions import assert_type @@ -59,25 +60,13 @@ def test_add_numpy_array() -> None: check(assert_type(left + f, "pd.Series[float]"), pd.Series, np.float64) check(assert_type(left + c, "pd.Series[complex]"), pd.Series, np.complex128) - # numpy typing gives ndarray instead of `pd.Series[...]` in reality, which we cannot fix + # `numpy` typing gives the corresponding `ndarray`s in the static type + # checking, where our `__radd__` cannot override. At runtime, they return + # `Series`s with the correct element type. + check(assert_type(i + left, "npt.NDArray[np.int64]"), pd.Series, np.int64) + check(assert_type(f + left, "npt.NDArray[np.float64]"), pd.Series, np.float64) check( - assert_type( # type: ignore[assert-type] - i + left, "pd.Series[int]" # pyright: ignore[reportAssertTypeFailure] - ), - pd.Series, - np.int64, - ) - check( - assert_type( # type: ignore[assert-type] - f + left, "pd.Series[float]" # pyright: ignore[reportAssertTypeFailure] - ), - pd.Series, - np.float64, - ) - check( - assert_type( # type: ignore[assert-type] - c + left, "pd.Series[complex]" # pyright: ignore[reportAssertTypeFailure] - ), + assert_type(c + left, "npt.NDArray[np.complex128]"), pd.Series, np.complex128, ) diff --git a/tests/series/arithmetic/test_add.py b/tests/series/arithmetic/test_add.py index 0001f6ec7..d5407dc76 100644 --- a/tests/series/arithmetic/test_add.py +++ b/tests/series/arithmetic/test_add.py @@ -1,4 +1,6 @@ import numpy as np +from numpy import typing as npt # noqa: F401 +from numpy._typing import _32Bit # noqa: F401 import pandas as pd from typing_extensions import assert_type @@ -59,24 +61,18 @@ def test_add_numpy_array() -> None: check(assert_type(left + f, pd.Series), pd.Series) check(assert_type(left + c, pd.Series), pd.Series) - # numpy typing gives ndarray instead of `pd.Series[...]` in reality, which we cannot fix + # `numpy` typing gives the corresponding `ndarray`s in the static type + # checking, where our `__radd__` cannot override. At runtime, they return + # `Series`s. + # `mypy` thinks the return types are `Any`, which is a bug. check( - assert_type( # type: ignore[assert-type] - i + left, pd.Series # pyright: ignore[reportAssertTypeFailure] - ), - pd.Series, + assert_type(i + left, "npt.NDArray[np.int64]"), pd.Series # type: ignore[assert-type] ) check( - assert_type( # type: ignore[assert-type] - f + left, pd.Series # pyright: ignore[reportAssertTypeFailure] - ), - pd.Series, + assert_type(f + left, "npt.NDArray[np.float64]"), pd.Series # type: ignore[assert-type] ) check( - assert_type( # type: ignore[assert-type] - c + left, pd.Series # pyright: ignore[reportAssertTypeFailure] - ), - pd.Series, + assert_type(c + left, "npt.NDArray[np.complexfloating[_32Bit, _32Bit]]"), pd.Series # type: ignore[assert-type] ) check(assert_type(left.add(i), pd.Series), pd.Series)