Skip to content

Commit 72e2d7d

Browse files
Merge branch 'main' of github.com:loicdiridollou/pandas-stubs into gh1484_ty_29a
2 parents 61e1dce + 852ef64 commit 72e2d7d

File tree

8 files changed

+174
-62
lines changed

8 files changed

+174
-62
lines changed

pandas-stubs/core/base.pyi

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ from typing import (
1010
Literal,
1111
Protocol,
1212
TypeAlias,
13+
TypeVar,
1314
final,
1415
overload,
1516
type_check_only,
@@ -53,6 +54,8 @@ from pandas._typing import (
5354
)
5455
from pandas.util._decorators import cache_readonly
5556

57+
T_INTERVAL_NP = TypeVar("T_INTERVAL_NP", bound=np.bytes_ | np.str_)
58+
5659
class NoNewAttributesMixin:
5760
def __setattr__(self, key: str, value: Any) -> None: ...
5861

pandas-stubs/core/indexes/base.pyi

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import numpy as np
3232
from pandas.core.arrays.boolean import BooleanArray
3333
from pandas.core.arrays.floating import FloatingArray
3434
from pandas.core.base import (
35+
T_INTERVAL_NP,
3536
ArrayIndexTimedeltaNoSeq,
3637
ElementOpsMixin,
3738
IndexComplex,
@@ -106,6 +107,7 @@ from pandas._typing import (
106107
PandasFloatDtypeArg,
107108
PyArrowFloatDtypeArg,
108109
ReindexMethod,
110+
Renamer,
109111
S2_contra,
110112
Scalar,
111113
SequenceNotStr,
@@ -532,39 +534,59 @@ class Index(IndexOpsMixin[S1], ElementOpsMixin[S1]):
532534
) -> Index[C2]: ...
533535
@overload
534536
def append(self, other: Index | Sequence[Index]) -> Index: ...
535-
def putmask(self, mask, value): ...
537+
def putmask(
538+
self,
539+
mask: Sequence[bool] | np_ndarray_bool | BooleanArray | IndexOpsMixin[bool],
540+
value: Scalar,
541+
) -> Index: ...
536542
def equals(self, other: Any) -> bool: ...
537543
@final
538544
def identical(self, other: Any) -> bool: ...
539545
@final
540-
def asof(self, label): ...
541-
def asof_locs(self, where, mask): ...
546+
def asof(self, label: Scalar) -> Scalar: ...
547+
def asof_locs(
548+
self, where: DatetimeIndex, mask: np_ndarray_bool
549+
) -> np_1darray_intp: ...
550+
@overload
551+
def sort_values(
552+
self,
553+
*,
554+
return_indexer: Literal[False] = False,
555+
ascending: bool = True,
556+
na_position: NaPosition = "last",
557+
key: Callable[[Index], Index] | None = None,
558+
) -> Self: ...
559+
@overload
542560
def sort_values(
543561
self,
544562
*,
545-
return_indexer: bool = ...,
546-
ascending: bool = ...,
547-
na_position: NaPosition = ...,
563+
return_indexer: Literal[True],
564+
ascending: bool = True,
565+
na_position: NaPosition = "last",
548566
key: Callable[[Index], Index] | None = None,
549-
): ...
567+
) -> tuple[Self, np_1darray_intp]: ...
550568
@final
551569
def sort(self, *args: Any, **kwargs: Any) -> None: ...
552570
def argsort(self, *args: Any, **kwargs: Any) -> np_1darray_intp: ...
553-
def get_indexer_non_unique(self, target): ...
571+
def get_indexer_non_unique(
572+
self, target: Index
573+
) -> tuple[np_1darray_intp, np_1darray_intp]: ...
554574
@final
555-
def get_indexer_for(self, target, **kwargs: Any): ...
556-
def map(self, mapper, na_action=...) -> Index: ...
575+
def get_indexer_for(self, target: Index) -> np_1darray_intp: ...
576+
def map(
577+
self, mapper: Renamer, na_action: Literal["ignore"] | None = None
578+
) -> Index: ...
557579
def isin(self, values, level=...) -> np_1darray_bool: ...
558580
def slice_indexer(
559581
self,
560582
start: Label | None = None,
561583
end: Label | None = None,
562584
step: int | None = None,
563-
): ...
564-
def get_slice_bound(self, label, side): ...
585+
) -> slice: ...
586+
def get_slice_bound(self, label: Scalar, side: Literal["left", "right"]) -> int: ...
565587
def slice_locs(
566588
self, start: SliceType = None, end: SliceType = None, step: int | None = None
567-
): ...
589+
) -> tuple[int | np.intp, int | np.intp]: ...
568590
def delete(
569591
self, loc: np.integer | int | AnyArrayLikeInt | Sequence[int]
570592
) -> Self: ...
@@ -1168,6 +1190,14 @@ class Index(IndexOpsMixin[S1], ElementOpsMixin[S1]):
11681190

11691191
@type_check_only
11701192
class _IndexSubclassBase(Index[S1], Generic[S1, GenericT_co]):
1193+
@overload
1194+
def to_numpy(
1195+
self: _IndexSubclassBase[Interval],
1196+
dtype: type[T_INTERVAL_NP],
1197+
copy: bool = False,
1198+
na_value: Scalar = ...,
1199+
**kwargs: Any,
1200+
) -> np_1darray: ...
11711201
@overload
11721202
def to_numpy(
11731203
self,
@@ -1185,7 +1215,7 @@ class _IndexSubclassBase(Index[S1], Generic[S1, GenericT_co]):
11851215
**kwargs: Any,
11861216
) -> np_1darray[GenericT]: ...
11871217
@overload
1188-
def to_numpy(
1218+
def to_numpy( # pyright: ignore[reportIncompatibleMethodOverride]
11891219
self,
11901220
dtype: DTypeLike,
11911221
copy: bool = False,

pandas-stubs/core/indexes/interval.pyi

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,6 @@ class IntervalIndex(ExtensionIndex[IntervalT, np.object_], IntervalMixin):
214214
@property
215215
def is_overlapping(self) -> bool: ...
216216
def get_loc(self, key: Label) -> int | slice | np_1darray_bool: ...
217-
def get_indexer_non_unique(
218-
self, target: Index
219-
) -> tuple[npt.NDArray[np.intp], npt.NDArray[np.intp]]: ...
220217
@property
221218
def left(self) -> Index: ...
222219
@property

pandas-stubs/core/series.pyi

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ from typing import (
2929
NoReturn,
3030
Protocol,
3131
TypeAlias,
32-
TypeVar,
3332
final,
3433
overload,
3534
type_check_only,
@@ -71,6 +70,7 @@ from pandas.core.arrays.datetimes import DatetimeArray
7170
from pandas.core.arrays.floating import FloatingArray
7271
from pandas.core.arrays.timedeltas import TimedeltaArray
7372
from pandas.core.base import (
73+
T_INTERVAL_NP,
7474
ArrayIndexSeriesTimedeltaNoSeq,
7575
ArrayIndexTimedeltaNoSeq,
7676
ElementOpsMixin,
@@ -189,6 +189,7 @@ from pandas._typing import (
189189
MaskType,
190190
NaPosition,
191191
NsmallestNlargestKeep,
192+
NumpyStrDtypeArg,
192193
ObjectDtypeArg,
193194
PandasAstypeComplexDtypeArg,
194195
PandasAstypeFloatDtypeArg,
@@ -251,8 +252,6 @@ from pandas.core.dtypes.dtypes import CategoricalDtype
251252

252253
from pandas.plotting import PlotAccessor
253254

254-
_T_INTERVAL_NP = TypeVar("_T_INTERVAL_NP", bound=np.bytes_ | np.str_)
255-
256255
@type_check_only
257256
class _SupportsAdd(Protocol[_T_co]):
258257
def __add__(self, value: Self, /) -> _T_co: ...
@@ -4507,7 +4506,7 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame):
45074506
copy: bool = False,
45084507
na_value: Scalar = ...,
45094508
**kwargs: Any,
4510-
) -> np_1darray_bytes: ...
4509+
) -> np_1darray: ...
45114510
@overload
45124511
def to_numpy(
45134512
self: Series[Interval],
@@ -4519,11 +4518,11 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame):
45194518
@overload
45204519
def to_numpy(
45214520
self: Series[Interval],
4522-
dtype: type[_T_INTERVAL_NP],
4521+
dtype: type[T_INTERVAL_NP],
45234522
copy: bool = False,
45244523
na_value: Scalar = ...,
45254524
**kwargs: Any,
4526-
) -> np_1darray[_T_INTERVAL_NP]: ...
4525+
) -> np_1darray: ...
45274526
@overload
45284527
def to_numpy(
45294528
self: Series[int],
@@ -4559,12 +4558,28 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame):
45594558
@overload
45604559
def to_numpy(
45614560
self: Series[_str],
4562-
dtype: DTypeLike | None = None,
4561+
dtype: NumpyStrDtypeArg,
45634562
copy: bool = False,
45644563
na_value: Scalar = ...,
45654564
**kwargs: Any,
45664565
) -> np_1darray_str: ...
45674566
@overload
4567+
def to_numpy(
4568+
self: Series[_str],
4569+
dtype: DTypeLike,
4570+
copy: bool = False,
4571+
na_value: Scalar = ...,
4572+
**kwargs: Any,
4573+
) -> np_1darray: ...
4574+
@overload
4575+
def to_numpy(
4576+
self: Series[_str],
4577+
dtype: None = None,
4578+
copy: bool = False,
4579+
na_value: Scalar = ...,
4580+
**kwargs: Any,
4581+
) -> np_1darray_object: ...
4582+
@overload
45684583
def to_numpy(
45694584
self: Series[bytes],
45704585
dtype: DTypeLike | None = None,

tests/__init__.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -439,11 +439,11 @@
439439
_S = TypeVar("_S", bound=tuple[int, ...])
440440
# Separately define here so pytest works
441441
np_1darray: TypeAlias = np.ndarray[tuple[int], np.dtype[_G]]
442-
np_1darray_bool: TypeAlias = np.ndarray[tuple[int], np.bool_]
443-
np_1darray_str: TypeAlias = np.ndarray[tuple[int], np.str_]
444-
np_1darray_bytes: TypeAlias = np.ndarray[tuple[int], np.bytes_]
445-
np_1darray_complex: TypeAlias = np.ndarray[tuple[int], np.complexfloating]
446-
np_1darray_object: TypeAlias = np.ndarray[tuple[int], np.object_]
442+
np_1darray_bool: TypeAlias = np_1darray[np.bool_]
443+
np_1darray_str: TypeAlias = np_1darray[np.str_]
444+
np_1darray_bytes: TypeAlias = np_1darray[np.bytes_]
445+
np_1darray_complex: TypeAlias = np_1darray[np.complexfloating]
446+
np_1darray_object: TypeAlias = np_1darray[np.object_]
447447
np_1darray_intp: TypeAlias = np_1darray[np.intp]
448448
np_1darray_int64: TypeAlias = np_1darray[np.int64]
449449
np_1darray_anyint: TypeAlias = np_1darray[np.integer]

tests/indexes/test_indexes.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
assert_type,
2424
)
2525

26+
from pandas._typing import Scalar # noqa: F401
27+
2628
from tests import (
2729
PD_LTE_23,
2830
TYPE_CHECKING_INVALID_USAGE,
@@ -1582,3 +1584,77 @@ def test_index_setitem() -> None:
15821584
idx = pd.Index([1, 2])
15831585
if TYPE_CHECKING_INVALID_USAGE:
15841586
idx[0] = 999 # type: ignore[index] # pyright: ignore[reportIndexIssue]
1587+
1588+
1589+
def test_index_putmask() -> None:
1590+
idx = pd.Index([1, 2])
1591+
check(assert_type(idx.putmask([True, False], 11.4), "pd.Index"), pd.Index)
1592+
check(assert_type(idx.putmask(np.array([True, False]), 11.4), "pd.Index"), pd.Index)
1593+
check(
1594+
assert_type(idx.putmask(pd.Series([True, False]), 11.4), "pd.Index"), pd.Index
1595+
)
1596+
check(assert_type(idx.putmask(pd.Index([True, False]), 11.4), "pd.Index"), pd.Index)
1597+
check(assert_type(idx.putmask(pd.array([True, False]), 11.5), "pd.Index"), pd.Index)
1598+
1599+
1600+
def test_index_asof() -> None:
1601+
check(assert_type(pd.Index([1, 2]).asof(1), "Scalar"), np.integer)
1602+
check(assert_type(pd.Index(["a", "b", "c"]).asof("c"), "Scalar"), str)
1603+
1604+
1605+
def test_index_asof_locs() -> None:
1606+
idx = pd.DatetimeIndex(["2020-01-01", "2020-01-02", "2020-01-03"])
1607+
check(
1608+
assert_type(
1609+
idx.asof_locs(
1610+
pd.DatetimeIndex(["2020-01-01 11:00"]), np.array([True, True, True])
1611+
),
1612+
np_1darray_intp,
1613+
),
1614+
np_1darray_intp,
1615+
)
1616+
1617+
1618+
def test_index_sort_values() -> None:
1619+
idx = pd.DatetimeIndex(["2020-01-01", "2020-01-02", "2020-01-03"])
1620+
check(assert_type(idx.sort_values(), pd.DatetimeIndex), pd.DatetimeIndex)
1621+
sorted_index, indexer = idx.sort_values(return_indexer=True)
1622+
check(assert_type(sorted_index, pd.DatetimeIndex), pd.DatetimeIndex)
1623+
check(assert_type(indexer, np_1darray_intp), np_1darray_intp)
1624+
1625+
1626+
def test_index_get_indexer_non_unique() -> None:
1627+
idx = pd.Index([1, 3])
1628+
indexer, missing = idx.get_indexer_non_unique(pd.Index([3]))
1629+
check(assert_type(indexer, np_1darray_intp), np_1darray_intp)
1630+
check(assert_type(missing, np_1darray_intp), np_1darray_intp)
1631+
1632+
1633+
def test_index_get_indexer_for() -> None:
1634+
idx = pd.Index([1, 3])
1635+
check(
1636+
assert_type(idx.get_indexer_for(pd.Index([3])), np_1darray_intp),
1637+
np_1darray_intp,
1638+
)
1639+
1640+
1641+
def test_index_map() -> None:
1642+
idx = pd.Index([1, 3])
1643+
check(assert_type(idx.map(lambda x: str(x)), pd.Index), pd.Index)
1644+
1645+
1646+
def test_index_slice_indexer() -> None:
1647+
idx = pd.Index([1, 3])
1648+
check(assert_type(idx.slice_indexer(0, 1), slice), slice)
1649+
1650+
1651+
def test_index_get_slice_bound() -> None:
1652+
idx = pd.Index([1, 3])
1653+
check(assert_type(idx.get_slice_bound(1, side="left"), int), int)
1654+
1655+
1656+
def test_index_slice_locs() -> None:
1657+
idx = pd.Index([1, 3])
1658+
start, end = idx.slice_locs(0, 1)
1659+
check(assert_type(start, np.intp | int), np.integer)
1660+
check(assert_type(end, np.intp | int), int)

tests/series/test_series.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@
7373
np_1darray_dt,
7474
np_1darray_float,
7575
np_1darray_object,
76-
np_1darray_str,
7776
np_1darray_td,
7877
np_ndarray_num,
7978
pytest_warns_bounded,
@@ -2004,18 +2003,22 @@ def test_dtype_type() -> None:
20042003

20052004
def test_types_to_numpy() -> None:
20062005
s = pd.Series(["a", "b", "c"], dtype=str)
2007-
check(assert_type(s.to_numpy(), np_1darray_str), np_1darray_str)
2006+
check(assert_type(s.to_numpy(), np_1darray_object), np_1darray_object)
2007+
check( # <U1, not str_
2008+
assert_type(s.to_numpy(dtype="str", copy=True), np_1darray), np_1darray
2009+
)
2010+
check(assert_type(s.to_numpy(na_value=0), np_1darray_object), np_1darray_object)
20082011
check(
2009-
assert_type(s.to_numpy(dtype="str", copy=True), np_1darray_str), np_1darray_str
2012+
assert_type(s.to_numpy(na_value=np.int32(4)), np_1darray_object),
2013+
np_1darray_object,
20102014
)
2011-
check(assert_type(s.to_numpy(na_value=0), np_1darray_str), np_1darray_str)
2012-
check(assert_type(s.to_numpy(na_value=np.int32(4)), np_1darray_str), np_1darray_str)
20132015
check(
2014-
assert_type(s.to_numpy(na_value=np.float16(4)), np_1darray_str), np_1darray_str
2016+
assert_type(s.to_numpy(na_value=np.float16(4)), np_1darray_object),
2017+
np_1darray_object,
20152018
)
20162019
check(
2017-
assert_type(s.to_numpy(na_value=np.complex128(4, 7)), np_1darray_str),
2018-
np_1darray_str,
2020+
assert_type(s.to_numpy(na_value=np.complex128(4, 7)), np_1darray_object),
2021+
np_1darray_object,
20192022
)
20202023

20212024
check(assert_type(pd.Series().to_numpy(), np_1darray), np_1darray)
@@ -2024,7 +2027,7 @@ def test_types_to_numpy() -> None:
20242027
def test_to_numpy() -> None:
20252028
"""Test Series.to_numpy for different types."""
20262029
s_str = pd.Series(["a", "b", "c"], dtype=str)
2027-
check(assert_type(s_str.to_numpy(), np_1darray_str), np_1darray_str)
2030+
check(assert_type(s_str.to_numpy(), np_1darray_object), np_1darray_object)
20282031

20292032
s_bytes = pd.Series(["a", "b", "c"]).astype(bytes)
20302033
check(assert_type(s_bytes.to_numpy(), np_1darray_bytes), np_1darray, np.bytes_)

0 commit comments

Comments
 (0)