Skip to content

Commit ffa88e5

Browse files
authored
type IndexOpsMixin (#1357)
1 parent 58d59f2 commit ffa88e5

File tree

3 files changed

+47
-19
lines changed

3 files changed

+47
-19
lines changed

pandas-stubs/core/base.pyi

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ from typing import (
66
Any,
77
Generic,
88
Literal,
9+
TypeAlias,
910
final,
1011
overload,
1112
)
@@ -22,18 +23,22 @@ from typing_extensions import Self
2223

2324
from pandas._typing import (
2425
S1,
26+
ArrayLike,
2527
AxisIndex,
2628
DropKeep,
2729
DTypeLike,
2830
GenericT,
2931
GenericT_co,
3032
NDFrameT,
3133
Scalar,
34+
SequenceNotStr,
3235
SupportsDType,
3336
np_1darray,
3437
)
3538
from pandas.util._decorators import cache_readonly
3639

40+
_ListLike: TypeAlias = ArrayLike | dict[str, np.ndarray] | SequenceNotStr[S1]
41+
3742
class NoNewAttributesMixin:
3843
def __setattr__(self, key: str, value: Any) -> None: ...
3944

@@ -51,7 +56,7 @@ class IndexOpsMixin(OpsMixin, Generic[S1, GenericT_co]):
5156
@property
5257
def T(self) -> Self: ...
5358
@property
54-
def shape(self) -> tuple: ...
59+
def shape(self) -> tuple[int, ...]: ...
5560
@property
5661
def ndim(self) -> int: ...
5762
def item(self) -> S1: ...
@@ -67,41 +72,45 @@ class IndexOpsMixin(OpsMixin, Generic[S1, GenericT_co]):
6772
dtype: None = None,
6873
copy: bool = False,
6974
na_value: Scalar = ...,
70-
**kwargs,
75+
**kwargs: Any,
7176
) -> np_1darray[GenericT_co]: ...
7277
@overload
7378
def to_numpy(
7479
self,
7580
dtype: np.dtype[GenericT] | SupportsDType[GenericT] | type[GenericT],
7681
copy: bool = False,
7782
na_value: Scalar = ...,
78-
**kwargs,
83+
**kwargs: Any,
7984
) -> np_1darray[GenericT]: ...
8085
@overload
8186
def to_numpy(
8287
self,
8388
dtype: DTypeLike,
8489
copy: bool = False,
8590
na_value: Scalar = ...,
86-
**kwargs,
91+
**kwargs: Any,
8792
) -> np_1darray: ...
8893
@property
8994
def empty(self) -> bool: ...
90-
def max(self, axis=..., skipna: bool = ..., **kwargs): ...
91-
def min(self, axis=..., skipna: bool = ..., **kwargs): ...
95+
def max(
96+
self, axis: AxisIndex | None = ..., skipna: bool = ..., **kwargs: Any
97+
) -> S1: ...
98+
def min(
99+
self, axis: AxisIndex | None = ..., skipna: bool = ..., **kwargs: Any
100+
) -> S1: ...
92101
def argmax(
93102
self,
94103
axis: AxisIndex | None = ...,
95104
skipna: bool = True,
96-
*args,
97-
**kwargs,
105+
*args: Any,
106+
**kwargs: Any,
98107
) -> np.int64: ...
99108
def argmin(
100109
self,
101110
axis: AxisIndex | None = ...,
102111
skipna: bool = True,
103-
*args,
104-
**kwargs,
112+
*args: Any,
113+
**kwargs: Any,
105114
) -> np.int64: ...
106115
def tolist(self) -> list[S1]: ...
107116
def to_list(self) -> list[S1]: ...
@@ -114,7 +123,7 @@ class IndexOpsMixin(OpsMixin, Generic[S1, GenericT_co]):
114123
normalize: Literal[False] = ...,
115124
sort: bool = ...,
116125
ascending: bool = ...,
117-
bins=...,
126+
bins: int | None = ...,
118127
dropna: bool = ...,
119128
) -> Series[int]: ...
120129
@overload
@@ -123,7 +132,7 @@ class IndexOpsMixin(OpsMixin, Generic[S1, GenericT_co]):
123132
normalize: Literal[True],
124133
sort: bool = ...,
125134
ascending: bool = ...,
126-
bins=...,
135+
bins: int | None = ...,
127136
dropna: bool = ...,
128137
) -> Series[float]: ...
129138
def nunique(self, dropna: bool = True) -> int: ...
@@ -136,7 +145,18 @@ class IndexOpsMixin(OpsMixin, Generic[S1, GenericT_co]):
136145
def factorize(
137146
self, sort: bool = False, use_na_sentinel: bool = True
138147
) -> tuple[np_1darray, np_1darray | Index | Categorical]: ...
148+
@overload
149+
def searchsorted(
150+
self,
151+
value: _ListLike,
152+
side: Literal["left", "right"] = ...,
153+
sorter: _ListLike | None = ...,
154+
) -> np_1darray[np.intp]: ...
155+
@overload
139156
def searchsorted(
140-
self, value, side: Literal["left", "right"] = ..., sorter=...
141-
) -> int | list[int]: ...
157+
self,
158+
value: Scalar,
159+
side: Literal["left", "right"] = ...,
160+
sorter: _ListLike | None = ...,
161+
) -> np.intp: ...
142162
def drop_duplicates(self, *, keep: DropKeep = ...) -> Self: ...

pandas-stubs/core/series.pyi

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -851,14 +851,14 @@ class Series(IndexOpsMixin[S1], NDFrame):
851851
value: _ListLike,
852852
side: Literal["left", "right"] = ...,
853853
sorter: _ListLike | None = ...,
854-
) -> list[int]: ...
854+
) -> np_1darray[np.intp]: ...
855855
@overload
856856
def searchsorted(
857857
self,
858858
value: Scalar,
859859
side: Literal["left", "right"] = ...,
860860
sorter: _ListLike | None = ...,
861-
) -> int: ...
861+
) -> np.intp: ...
862862
@overload
863863
def compare(
864864
self,

tests/indexes/test_indexes.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@
1919
assert_type,
2020
)
2121

22-
if TYPE_CHECKING:
23-
from tests import Dtype # noqa: F401
24-
2522
from tests import (
2623
PD_LTE_23,
2724
TYPE_CHECKING_INVALID_USAGE,
@@ -30,6 +27,9 @@
3027
pytest_warns_bounded,
3128
)
3229

30+
if TYPE_CHECKING:
31+
from tests import Dtype # noqa: F401
32+
3333

3434
def test_index_unique() -> None:
3535
df = pd.DataFrame({"x": [1, 2, 3, 4]}, index=pd.Index([1, 2, 3, 2]))
@@ -1489,6 +1489,14 @@ def test_index_naming() -> None:
14891489
check(assert_type(df.index.names, list[Hashable | None]), list)
14901490

14911491

1492+
def test_index_searchsorted() -> None:
1493+
idx = pd.Index([1, 2, 3])
1494+
check(assert_type(idx.searchsorted(1), np.intp), np.intp)
1495+
check(assert_type(idx.searchsorted([1]), "np_1darray[np.intp]"), np_1darray)
1496+
check(assert_type(idx.searchsorted(1, side="left"), np.intp), np.intp)
1497+
check(assert_type(idx.searchsorted(1, sorter=[1, 0, 2]), np.intp), np.intp)
1498+
1499+
14921500
def test_period_index_constructor() -> None:
14931501
check(
14941502
assert_type(pd.PeriodIndex(["2000"], dtype="period[D]"), pd.PeriodIndex),

0 commit comments

Comments
 (0)