Skip to content

Commit 6bc10ad

Browse files
TYP: GH1654 pipe method (#1665)
* GH1654 Pipe method * GH1654 PR Feedback * GH1654 PR Feedback
1 parent 1a40972 commit 6bc10ad

File tree

12 files changed

+100
-10
lines changed

12 files changed

+100
-10
lines changed

pandas-stubs/api/typing/__init__.pyi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ from pandas.core.groupby import (
22
DataFrameGroupBy as DataFrameGroupBy,
33
SeriesGroupBy as SeriesGroupBy,
44
)
5+
from pandas.core.indexes.frozen import FrozenList as FrozenList
56
from pandas.core.resample import (
67
DatetimeIndexResamplerGroupby as DatetimeIndexResamplerGroupby,
78
PeriodIndexResamplerGroupby as PeriodIndexResamplerGroupby,

pandas-stubs/core/accessor.pyi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ class PandasDelegate: ...
77
def register_dataframe_accessor(name: str) -> Callable[[TypeT], TypeT]: ...
88
def register_series_accessor(name: str) -> Callable[[TypeT], TypeT]: ...
99
def register_index_accessor(name: str) -> Callable[[TypeT], TypeT]: ...
10+
11+
class DirNamesMixin: ...

pandas-stubs/core/base.pyi

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ from typing import (
1818
import numpy as np
1919
import numpy.typing as npt
2020
from pandas._stubs_only import T_contra
21+
from pandas.core.accessor import DirNamesMixin
2122
from pandas.core.arraylike import OpsMixin
2223
from pandas.core.arrays import ExtensionArray
2324
from pandas.core.arrays.categorical import Categorical
@@ -57,6 +58,8 @@ T_INTERVAL_NP = TypeVar("T_INTERVAL_NP", bound=np.bytes_ | np.str_)
5758
class NoNewAttributesMixin:
5859
def __setattr__(self, key: str, value: Any) -> None: ...
5960

61+
class PandasObject(DirNamesMixin): ...
62+
6063
class IndexOpsMixin(OpsMixin, Generic[S1, GenericT_co]):
6164
__array_priority__: int = ...
6265
@property

pandas-stubs/core/groupby/base.pyi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ ReductionKernelType: TypeAlias = Literal[
3232
"sem",
3333
"size",
3434
"skew",
35+
"kurt",
3536
"std",
3637
"sum",
3738
"var",

pandas-stubs/core/indexes/base.pyi

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ from pandas.core.base import (
5858
from pandas.core.frame import DataFrame
5959
from pandas.core.indexes.category import CategoricalIndex
6060
from pandas.core.indexes.datetimes import DatetimeIndex
61+
from pandas.core.indexes.frozen import FrozenList
6162
from pandas.core.indexes.interval import IntervalIndex
6263
from pandas.core.indexes.multi import MultiIndex
6364
from pandas.core.indexes.period import PeriodIndex
@@ -413,7 +414,7 @@ class Index(IndexOpsMixin[S1], ElementOpsMixin[S1]):
413414
@name.setter
414415
def name(self, value: Hashable) -> None: ...
415416
@property
416-
def names(self) -> list[Hashable | None]: ...
417+
def names(self) -> FrozenList[Hashable | None]: ...
417418
@names.setter
418419
def names(self, names: SequenceNotStr[Hashable | None]) -> None: ...
419420
def set_names(
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from typing import (
2+
Generic,
3+
TypeVar,
4+
)
5+
6+
from pandas.core.base import PandasObject
7+
8+
_T = TypeVar("_T")
9+
10+
class FrozenList(PandasObject, list[_T], Generic[_T]): ...

pandas-stubs/core/indexes/multi.pyi

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ from typing import (
1414

1515
import numpy as np
1616
import pandas as pd
17+
from pandas.api.typing import FrozenList
1718
from pandas.core.indexes.base import Index
1819

1920
from pandas._typing import (
@@ -87,7 +88,7 @@ class MultiIndex(Index):
8788
names: SequenceNotStr[Hashable] | None = None,
8889
) -> Self: ...
8990
@property # Should be read-only
90-
def levels(self) -> list[Index]: ...
91+
def levels(self) -> FrozenList[Index]: ...
9192
@overload
9293
def set_levels(
9394
self,
@@ -105,7 +106,7 @@ class MultiIndex(Index):
105106
verify_integrity: bool = True,
106107
) -> MultiIndex: ...
107108
@property
108-
def codes(self) -> list[np_1darray_int8]: ...
109+
def codes(self) -> FrozenList[np_1darray_int8]: ...
109110
@overload
110111
def set_codes(
111112
self,

pandas-stubs/core/window/rolling.pyi

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ from collections.abc import (
77
import datetime as dt
88
from typing import (
99
Any,
10+
Concatenate,
1011
Generic,
1112
Self,
1213
overload,
@@ -28,7 +29,9 @@ from pandas._typing import (
2829
CalculationMethod,
2930
IntervalClosedType,
3031
NDFrameT,
32+
P,
3133
QuantileInterpolation,
34+
T,
3235
WindowingEngine,
3336
WindowingEngineKwargs,
3437
WindowingRankType,
@@ -171,6 +174,20 @@ class RollingAndExpandingMixin(BaseWindow[NDFrameT]):
171174
def first(self, numeric_only: bool = False) -> NDFrameT: ...
172175
def last(self, numeric_only: bool = False) -> NDFrameT: ...
173176
def nunique(self, numeric_only: bool = False) -> NDFrameT: ...
177+
@overload
178+
def pipe(
179+
self,
180+
func: Callable[Concatenate[Self, P], T],
181+
*args: P.args,
182+
**kwargs: P.kwargs,
183+
) -> T: ...
184+
@overload
185+
def pipe(
186+
self,
187+
func: tuple[Callable[Concatenate[Self, P], T], str],
188+
*args: P.args,
189+
**kwargs: P.kwargs,
190+
) -> T: ...
174191

175192
class Rolling(RollingAndExpandingMixin[NDFrameT]): ...
176193
class RollingGroupby(BaseWindowGroupby[NDFrameT], Rolling[NDFrameT]): ...

tests/frame/test_frame.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
DatetimeIndexResampler,
4242
Resampler,
4343
)
44+
from pandas.core.window.expanding import Expanding
45+
from pandas.core.window.rolling import Rolling
4446
import pytest
4547
import xarray as xr
4648

@@ -4324,3 +4326,31 @@ def test_expanding_nunique() -> None:
43244326
assert_type(df.expanding().nunique(numeric_only=False), pd.DataFrame),
43254327
pd.DataFrame,
43264328
)
4329+
4330+
4331+
def test_frame_pipe() -> None:
4332+
"""Test Rolling.pipe and Expanding.pipe."""
4333+
df = pd.DataFrame(
4334+
{
4335+
"B": np.random.default_rng(2).standard_normal(10),
4336+
"C": np.random.default_rng(2).standard_normal(10),
4337+
}
4338+
)
4339+
4340+
def func_r(x: Rolling[pd.DataFrame], k: int) -> pd.DataFrame:
4341+
return x.max() - k * x.min()
4342+
4343+
def func_e(x: Expanding[pd.DataFrame], k: int) -> pd.DataFrame:
4344+
return x.max() - k * x.min()
4345+
4346+
check(
4347+
assert_type(df.rolling(2).pipe(lambda x: x.min() - x.max()), pd.DataFrame),
4348+
pd.DataFrame,
4349+
)
4350+
check(assert_type(df.rolling(2).pipe(func_r, k=2), pd.DataFrame), pd.DataFrame)
4351+
4352+
check(
4353+
assert_type(df.expanding().pipe(lambda x: x.min() - x.max()), pd.DataFrame),
4354+
pd.DataFrame,
4355+
)
4356+
check(assert_type(df.expanding().pipe(func_e, k=2), pd.DataFrame), pd.DataFrame)

tests/indexes/test_indexes.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from pandas.core.indexes.base import Index
2424
from pandas.core.indexes.category import CategoricalIndex
2525
from pandas.core.indexes.datetimes import DatetimeIndex
26+
from pandas.core.indexes.frozen import FrozenList
2627
import pytest
2728

2829
from tests import (
@@ -1399,20 +1400,20 @@ def test_index_naming() -> None:
13991400
"""
14001401
Test index names type both for the getter and the setter.
14011402
The names of an index should be settable with a sequence (not str) and names
1402-
property is a list[Hashable | None] (FrozenList).
1403+
property is a FrozenList[Hashable | None].
14031404
"""
14041405
df = pd.DataFrame({"a": ["a", "b", "c"], "i": [10, 11, 12]})
14051406

14061407
df.index.names = ["idx"]
1407-
check(assert_type(df.index.names, list[Hashable | None]), list)
1408+
check(assert_type(df.index.names, FrozenList[Hashable | None]), FrozenList)
14081409
df.index.names = [3]
1409-
check(assert_type(df.index.names, list[Hashable | None]), list)
1410+
check(assert_type(df.index.names, FrozenList[Hashable | None]), FrozenList)
14101411
df.index.names = ("idx2",)
1411-
check(assert_type(df.index.names, list[Hashable | None]), list)
1412+
check(assert_type(df.index.names, FrozenList[Hashable | None]), FrozenList)
14121413
df.index.names = [None]
1413-
check(assert_type(df.index.names, list[Hashable | None]), list)
1414+
check(assert_type(df.index.names, FrozenList[Hashable | None]), FrozenList)
14141415
df.index.names = (None,)
1415-
check(assert_type(df.index.names, list[Hashable | None]), list)
1416+
check(assert_type(df.index.names, FrozenList[Hashable | None]), FrozenList)
14161417

14171418

14181419
def test_index_searchsorted() -> None:

0 commit comments

Comments
 (0)