Skip to content

Commit 8e5c754

Browse files
authored
fix(series): #1372 🧱✖️ cumprod (#1374)
fix(series): #1372 cumprod
1 parent c98adb3 commit 8e5c754

File tree

3 files changed

+66
-38
lines changed

3 files changed

+66
-38
lines changed

pandas-stubs/core/series.pyi

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,10 @@ from pandas.plotting import PlotAccessor
210210
class _SupportsAdd(Protocol[_T_co]):
211211
def __add__(self, value: Self, /) -> _T_co: ...
212212

213+
@type_check_only
214+
class _SupportsMul(Protocol[_T_co]):
215+
def __mul__(self, value: Self, /) -> _T_co: ...
216+
213217
class _iLocIndexerSeries(_iLocIndexer, Generic[S1]):
214218
# get item
215219
@overload
@@ -3821,23 +3825,23 @@ class Series(IndexOpsMixin[S1], NDFrame):
38213825
) -> Series[S1]: ...
38223826
@overload
38233827
def cumprod(
3824-
self: Series[_str],
3828+
self: Series[Never],
38253829
axis: AxisIndex = ...,
38263830
skipna: _bool = ...,
38273831
*args: Any,
38283832
**kwargs: Any,
3829-
) -> Never: ...
3833+
) -> Series: ...
38303834
@overload
38313835
def cumprod(
3832-
self: Series[Timestamp],
3836+
self: Series[bool],
38333837
axis: AxisIndex = ...,
38343838
skipna: _bool = ...,
38353839
*args: Any,
38363840
**kwargs: Any,
3837-
) -> Never: ...
3841+
) -> Series[int]: ...
38383842
@overload
38393843
def cumprod(
3840-
self,
3844+
self: SupportsGetItem[Scalar, _SupportsMul[S1]],
38413845
axis: AxisIndex = ...,
38423846
skipna: _bool = ...,
38433847
*args: Any,
@@ -4369,39 +4373,18 @@ class TimedeltaSeries(_SeriesSubclassBase[Timedelta, np.timedelta64]):
43694373
*args: Any,
43704374
**kwargs: Any,
43714375
) -> TimedeltaSeries: ...
4372-
def cumprod( # pyrefly: ignore
4373-
self,
4374-
axis: AxisIndex = ...,
4375-
skipna: _bool = ...,
4376-
*args: Any,
4377-
**kwargs: Any,
4378-
) -> Never: ...
43794376

43804377
class PeriodSeries(_SeriesSubclassBase[Period, np.object_]):
43814378
@property
43824379
def dt(self) -> PeriodProperties: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
43834380
def __sub__(self, other: PeriodSeries) -> OffsetSeries: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
43844381
def diff(self, periods: int = ...) -> OffsetSeries: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
4385-
def cumprod(
4386-
self,
4387-
axis: AxisIndex = ...,
4388-
skipna: _bool = ...,
4389-
*args: Any,
4390-
**kwargs: Any,
4391-
) -> Never: ...
43924382

43934383
class OffsetSeries(_SeriesSubclassBase[BaseOffset, np.object_]):
43944384
@overload # type: ignore[override]
43954385
def __radd__(self, other: Period) -> PeriodSeries: ...
43964386
@overload
43974387
def __radd__(self, other: BaseOffset) -> OffsetSeries: ...
4398-
def cumprod( # pyrefly: ignore
4399-
self,
4400-
axis: AxisIndex = ...,
4401-
skipna: _bool = ...,
4402-
*args: Any,
4403-
**kwargs: Any,
4404-
) -> Never: ...
44054388

44064389
class IntervalSeries(
44074390
_SeriesSubclassBase[Interval[_OrderableT], np.object_], Generic[_OrderableT]

tests/series/test_cumul.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import numpy as np
2+
import pandas as pd
3+
from typing_extensions import assert_type
4+
5+
from tests import (
6+
TYPE_CHECKING_INVALID_USAGE,
7+
check,
8+
)
9+
10+
11+
def test_cumul_any_float() -> None:
12+
series = pd.DataFrame({"A": [1.0, float("nan"), 2.0]})["A"]
13+
check(assert_type(series.cumprod(), pd.Series), pd.Series, np.floating)
14+
15+
16+
def test_cumul_bool() -> None:
17+
series = pd.Series([True, False, True])
18+
check(assert_type(series.cumprod(), "pd.Series[int]"), pd.Series, np.integer)
19+
20+
21+
def test_cumul_int() -> None:
22+
series = pd.Series([3, 1, 2])
23+
check(assert_type(series.cumprod(), "pd.Series[int]"), pd.Series, np.integer)
24+
25+
26+
def test_cumul_float() -> None:
27+
series = pd.Series([3.0, float("nan"), 2.0])
28+
check(assert_type(series.cumprod(), "pd.Series[float]"), pd.Series, np.floating)
29+
30+
31+
def test_cumul_complex() -> None:
32+
series = pd.Series([3j, 3 + 4j, 2j])
33+
check(
34+
assert_type(series.cumprod(), "pd.Series[complex]"),
35+
pd.Series,
36+
np.complexfloating,
37+
)
38+
39+
40+
def test_cumul_str() -> None:
41+
series = pd.Series(["1", "a", "🐼"])
42+
if TYPE_CHECKING_INVALID_USAGE:
43+
series.cumprod() # type: ignore[misc] # pyright: ignore[reportAttributeAccessIssue]
44+
45+
46+
def test_cumul_ts() -> None:
47+
series = pd.Series(pd.to_datetime(["2025-09-18", "2025-09-18", "2025-09-18"]))
48+
check(assert_type(series, "pd.Series[pd.Timestamp]"), pd.Series, pd.Timestamp)
49+
50+
if TYPE_CHECKING_INVALID_USAGE:
51+
series.cumprod() # type: ignore[misc] # pyright: ignore[reportAttributeAccessIssue]

tests/series/test_series.py

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3946,24 +3946,18 @@ def test_timedelta_index_cumprod() -> None:
39463946
offset_series = as_period_series - as_period_series
39473947

39483948
if TYPE_CHECKING_INVALID_USAGE:
3949-
assert_type(pd.Series(["a", "b"]).cumprod(), Never)
3949+
offset_series.cumprod() # type: ignore[misc] # pyright: ignore[reportAttributeAccessIssue]
39503950

39513951
if TYPE_CHECKING_INVALID_USAGE:
3952-
assert_type(offset_series.cumprod(), Never)
3952+
pd.Series([pd.Timedelta(0), pd.Timedelta(1)]).cumprod() # type: ignore[misc] # pyright: ignore[reportAttributeAccessIssue]
39533953

39543954
if TYPE_CHECKING_INVALID_USAGE:
3955-
assert_type(pd.Series([pd.Timedelta(0), pd.Timedelta(1)]).cumprod(), Never)
3955+
pd.Series( # type: ignore[misc]
3956+
[pd.Timestamp("2024-04-29"), pd.Timestamp("2034-08-28")]
3957+
).cumprod() # pyright: ignore[reportAttributeAccessIssue]
39563958

39573959
if TYPE_CHECKING_INVALID_USAGE:
3958-
assert_type(
3959-
pd.Series(
3960-
[pd.Timestamp("2024-04-29"), pd.Timestamp("2034-08-28")]
3961-
).cumprod(),
3962-
Never,
3963-
)
3964-
3965-
if TYPE_CHECKING_INVALID_USAGE:
3966-
assert_type(as_period_series.cumprod(), Never)
3960+
as_period_series.cumprod() # type: ignore[misc] # pyright: ignore[reportAttributeAccessIssue]
39673961

39683962

39693963
def test_series_str_methods() -> None:

0 commit comments

Comments
 (0)