Skip to content
Open
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ repos:
hooks:
- id: isort
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.12.3
rev: v0.12.10
hooks:
- id: ruff-check
args: [
Expand Down
39 changes: 22 additions & 17 deletions pandas-stubs/core/series.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,6 @@ from pandas._typing import (
np_ndarray_anyint,
np_ndarray_bool,
np_ndarray_complex,
np_ndarray_dt,
np_ndarray_float,
np_ndarray_str,
np_ndarray_td,
Expand Down Expand Up @@ -264,6 +263,16 @@ class _LocIndexerSeries(_LocIndexer, Generic[S1]):
_ListLike: TypeAlias = (
ArrayLike | dict[_str, np.ndarray] | Sequence[S1] | IndexOpsMixin[S1]
)
_NumListLike: TypeAlias = (
ExtensionArray
| np_ndarray_bool
| np_ndarray_anyint
| np_ndarray_float
| np_ndarray_complex
| dict[_str, np.ndarray]
| Sequence[complex]
| IndexOpsMixin[complex]
)

class Series(IndexOpsMixin[S1], NDFrame):
# Define __index__ because mypy thinks Series follows protocol `SupportsIndex` https://github.com/pandas-dev/pandas-stubs/pull/1332#discussion_r2285648790
Expand Down Expand Up @@ -2475,12 +2484,11 @@ class Series(IndexOpsMixin[S1], NDFrame):
@overload
def __rxor__(self, other: int | np_ndarray_anyint | Series[int]) -> Series[int]: ...
@overload
def __sub__(
self: Series[Never],
other: datetime | np.datetime64 | np_ndarray_dt | TimestampSeries,
) -> TimedeltaSeries: ...
def __sub__(self: Series[Never], other: TimestampSeries) -> Never: ...
@overload
def __sub__(self: Series[Never], other: complex | _ListLike | Series) -> Series: ...
def __sub__(
self: Series[Never], other: complex | _NumListLike | Series
) -> Series: ...
@overload
def __sub__(self, other: Series[Never]) -> Series: ... # type: ignore[overload-overlap]
@overload
Expand Down Expand Up @@ -2571,15 +2579,15 @@ class Series(IndexOpsMixin[S1], NDFrame):
@overload
def sub(
self: Series[Never],
other: datetime | np.datetime64 | np_ndarray_dt | TimestampSeries,
other: TimestampSeries,
level: Level | None = None,
fill_value: float | None = None,
axis: int = 0,
) -> TimedeltaSeries: ...
) -> Never: ...
@overload
def sub(
self: Series[Never],
other: complex | _ListLike | Series,
other: complex | _NumListLike | Series,
level: Level | None = None,
fill_value: float | None = None,
axis: int = 0,
Expand Down Expand Up @@ -2705,13 +2713,10 @@ class Series(IndexOpsMixin[S1], NDFrame):
axis: int = 0,
) -> TimedeltaSeries: ...
@overload
def __rsub__( # type: ignore[misc]
self: Series[Never],
other: datetime | np.datetime64 | np_ndarray_dt | TimestampSeries,
) -> TimedeltaSeries: ...
def __rsub__(self: Series[Never], other: TimestampSeries) -> Never: ... # type: ignore[misc]
@overload
def __rsub__(
self: Series[Never], other: complex | _ListLike | Series
self: Series[Never], other: complex | _NumListLike | Series
) -> Series: ...
@overload
def __rsub__(self, other: Series[Never]) -> Series: ...
Expand Down Expand Up @@ -2781,15 +2786,15 @@ class Series(IndexOpsMixin[S1], NDFrame):
@overload
def rsub(
self: Series[Never],
other: datetime | np.datetime64 | np_ndarray_dt | TimestampSeries,
other: TimestampSeries,
level: Level | None = None,
fill_value: float | None = None,
axis: int = 0,
) -> TimedeltaSeries: ...
) -> Never: ...
@overload
def rsub(
self: Series[Never],
other: complex | _ListLike | Series,
other: complex | _NumListLike | Series,
level: Level | None = None,
fill_value: float | None = None,
axis: int = 0,
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ types-pytz = ">= 2022.1.1"
numpy = ">= 1.23.5"

[tool.poetry.group.dev.dependencies]
mypy = "1.17.0"
mypy = "1.17.1"
pandas = "2.3.1"
pyarrow = ">=10.0.1"
pytest = ">=7.1.2"
pyright = ">=1.1.404"
ty = "^0.0.1a8"
ty = "^0.0.1a9"
pyrefly = "^0.21.0"
poethepoet = ">=0.16.5"
loguru = ">=0.6.0"
Expand Down
8 changes: 4 additions & 4 deletions tests/series/arithmetic/str/test_add.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@


def test_add_py_scalar() -> None:
"""Testpd.Series[str]+ Python native 'scalar's"""
"""Test pd.Series[str] + Python native 'scalar's"""
i = 4
r0 = "right"

Expand All @@ -40,7 +40,7 @@ def test_add_py_scalar() -> None:


def test_add_py_sequence() -> None:
"""Testpd.Series[str]+ Python native sequence"""
"""Test pd.Series[str] + Python native sequence"""
i = [3, 5, 8]
r0 = ["a", "bc", "def"]
r1 = tuple(r0)
Expand All @@ -67,7 +67,7 @@ def test_add_py_sequence() -> None:


def test_add_numpy_array() -> None:
"""Testpd.Series[str]+ numpy array"""
"""Test pd.Series[str] + numpy array"""
i = np.array([3, 5, 8], np.int64)
r0 = np.array(["a", "bc", "def"], np.str_)

Expand Down Expand Up @@ -101,7 +101,7 @@ def test_add_numpy_array() -> None:


def test_add_pd_series() -> None:
"""Testpd.Series[str]+ pandas series"""
"""Test pd.Series[str] + pandas series"""
i = pd.Series([3, 5, 8])
r0 = pd.Series(["a", "bc", "def"])

Expand Down
159 changes: 83 additions & 76 deletions tests/series/arithmetic/test_add.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,122 +5,129 @@

from tests import check

left = pd.DataFrame({"a": [1, 2, 3]})["a"] # left operand
# left operands
left_i = pd.DataFrame({"a": [1, 2, 3]})["a"]
left_str = pd.DataFrame({"a": ["1", "2", "3_"]})["a"]


def test_add_py_scalar() -> None:
"""Test pd.Series[Any] + Python native scalars"""
def test_add_i_py_scalar() -> None:
"""Test pd.Series[Any] (int) + Python native scalars"""
b, i, f, c = True, 1, 1.0, 1j

check(assert_type(left + b, pd.Series), pd.Series)
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(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(b + left, 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(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.add(b), 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_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.radd(b), 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)
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_py_sequence() -> None:
"""Test pd.Series[Any] + Python native sequence"""
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]

check(assert_type(left + b, pd.Series), pd.Series)
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(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(b + left, 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(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.add(b), 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_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.radd(b), 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)
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_numpy_array() -> None:
"""Test pd.Series[Any] + numpy array"""
def test_add_i_numpy_array() -> None:
"""Test pd.Series[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 + b, pd.Series), pd.Series)
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(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)

# `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(b + left, "npt.NDArray[np.bool_]"), pd.Series # type: ignore[assert-type]
assert_type(b + left_i, "npt.NDArray[np.bool_]"), pd.Series # type: ignore[assert-type]
)
check(
assert_type(i + left, "npt.NDArray[np.int64]"), pd.Series # type: ignore[assert-type]
assert_type(i + left_i, "npt.NDArray[np.int64]"), pd.Series # type: ignore[assert-type]
)
check(
assert_type(f + left, "npt.NDArray[np.float64]"), pd.Series # type: ignore[assert-type]
assert_type(f + left_i, "npt.NDArray[np.float64]"), pd.Series # type: ignore[assert-type]
)
check(
assert_type(c + left, "npt.NDArray[np.complex128]"), pd.Series # type: ignore[assert-type]
assert_type(c + left_i, "npt.NDArray[np.complex128]"), pd.Series # type: ignore[assert-type]
)

check(assert_type(left.add(b), 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_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.radd(b), 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)
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_pd_series() -> None:
"""Test pd.Series[Any] + pandas series"""
def test_add_i_pd_series() -> None:
"""Test pd.Series[Any] (int) + pandas series"""
a = pd.DataFrame({"a": [1, 2, 3]})["a"]
b = pd.Series([True, False, True])
i = pd.Series([2, 3, 5])
f = pd.Series([1.0, 2.0, 3.0])
c = pd.Series([1.1j, 2.2j, 4.1j])

check(assert_type(left + b, pd.Series), pd.Series)
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(b + left, 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(b), 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(b), 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)
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)
Loading
Loading