From 82587f311b528d29d434ce73cb1850dfe6b07bdc Mon Sep 17 00:00:00 2001 From: Marco Gorelli <33491632+MarcoGorelli@users.noreply.github.com> Date: Tue, 19 Aug 2025 14:42:58 +0100 Subject: [PATCH 1/8] type ``PeriodIndex.__new__`` --- pandas-stubs/core/indexes/period.pyi | 42 ++++++++-------------------- tests/test_indexes.py | 13 +++++++++ 2 files changed, 25 insertions(+), 30 deletions(-) diff --git a/pandas-stubs/core/indexes/period.pyi b/pandas-stubs/core/indexes/period.pyi index da025b8a..5a7e5766 100644 --- a/pandas-stubs/core/indexes/period.pyi +++ b/pandas-stubs/core/indexes/period.pyi @@ -1,7 +1,6 @@ from collections.abc import Hashable import datetime from typing import ( - final, overload, ) @@ -14,27 +13,27 @@ from pandas.core.indexes.timedeltas import TimedeltaIndex from typing_extensions import Self from pandas._libs.tslibs import ( - BaseOffset, NaTType, Period, ) from pandas._libs.tslibs.period import _PeriodAddSub +from pandas._typing import ( + AxesData, + Dtype, + Frequency, +) class PeriodIndex(DatetimeIndexOpsMixin[pd.Period, np.object_], PeriodIndexFieldOps): def __new__( cls, - data=..., - ordinal=..., - freq=..., - tz=..., - dtype=..., - copy: bool = ..., - name: Hashable = ..., - **fields, + data: AxesData | None = None, + freq: Frequency | None = None, + dtype: Dtype | None = None, + copy: bool = False, + name: Hashable | None = None, ): ... @property - def values(self): ... - def __contains__(self, key) -> bool: ... + def values(self) -> np.ndarray[tuple[int], np.dtype[np.object_]]: ... @overload def __sub__(self, other: Period) -> Index: ... @overload @@ -53,28 +52,11 @@ class PeriodIndex(DatetimeIndexOpsMixin[pd.Period, np.object_], PeriodIndexField def __rsub__( # pyright: ignore[reportIncompatibleMethodOverride] self, other: NaTType ) -> NaTType: ... - @final - def __array_wrap__(self, result, context=...): ... def asof_locs(self, where, mask): ... - def searchsorted(self, value, side: str = ..., sorter=...): ... @property def is_full(self) -> bool: ... @property def inferred_type(self) -> str: ... - @final - def get_indexer(self, target, method=..., limit=..., tolerance=...): ... - def get_indexer_non_unique(self, target): ... - def insert(self, loc, item): ... - @final - def join( - self, - other, - *, - how: str = ..., - level=..., - return_indexers: bool = ..., - sort: bool = ..., - ): ... @property def freqstr(self) -> str: ... def shift(self, periods: int = 1, freq=...) -> Self: ... @@ -87,6 +69,6 @@ def period_range( str | datetime.datetime | datetime.date | pd.Timestamp | pd.Period | None ) = None, periods: int | None = None, - freq: str | BaseOffset | None = None, + freq: Frequency | None = None, name: Hashable | None = None, ) -> PeriodIndex: ... diff --git a/tests/test_indexes.py b/tests/test_indexes.py index 819e5b24..b23b7605 100644 --- a/tests/test_indexes.py +++ b/tests/test_indexes.py @@ -1489,3 +1489,16 @@ def test_index_naming() -> None: check(assert_type(df.index.names, list[Hashable | None]), list) df.index.names = (None,) check(assert_type(df.index.names, list[Hashable | None]), list) + + +def test_period_index_constructor() -> None: + check( + assert_type(pd.PeriodIndex(["2000"], dtype="period[D]"), pd.PeriodIndex), + pd.PeriodIndex, + ) + check( + assert_type( + pd.PeriodIndex(["2000"], freq="D", name="foo", copy=True), pd.PeriodIndex + ), + pd.PeriodIndex, + ) From 5193bd6d0b3742fee31cfd4d6be8eb358fe63722 Mon Sep 17 00:00:00 2001 From: Marco Gorelli <33491632+MarcoGorelli@users.noreply.github.com> Date: Tue, 19 Aug 2025 15:35:36 +0100 Subject: [PATCH 2/8] shift and asof_locs too --- pandas-stubs/core/indexes/period.pyi | 8 ++++++-- tests/test_indexes.py | 10 ++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/pandas-stubs/core/indexes/period.pyi b/pandas-stubs/core/indexes/period.pyi index 5a7e5766..90c96430 100644 --- a/pandas-stubs/core/indexes/period.pyi +++ b/pandas-stubs/core/indexes/period.pyi @@ -52,14 +52,18 @@ class PeriodIndex(DatetimeIndexOpsMixin[pd.Period, np.object_], PeriodIndexField def __rsub__( # pyright: ignore[reportIncompatibleMethodOverride] self, other: NaTType ) -> NaTType: ... - def asof_locs(self, where, mask): ... + def asof_locs( + self, + where: pd.DatetimeIndex | PeriodIndex, + mask: np.ndarray[tuple[int], np.dtype[np.bool_]], + ) -> Self: ... @property def is_full(self) -> bool: ... @property def inferred_type(self) -> str: ... @property def freqstr(self) -> str: ... - def shift(self, periods: int = 1, freq=...) -> Self: ... + def shift(self, periods: int = 1, freq: Frequency | None = None) -> Self: ... def period_range( start: ( diff --git a/tests/test_indexes.py b/tests/test_indexes.py index b23b7605..3d5fe9e2 100644 --- a/tests/test_indexes.py +++ b/tests/test_indexes.py @@ -1502,3 +1502,13 @@ def test_period_index_constructor() -> None: ), pd.PeriodIndex, ) + + +def test_period_index_asof_locs() -> None: + idx = pd.PeriodIndex(["2000", "2001"], freq="D") + where = pd.DatetimeIndex(["2023-05-30 00:12:00", "2023-06-01 00:00:00"]) + mask = np.ones(2, dtype=bool) + check( + assert_type(idx.asof_locs(where, mask), pd.PeriodIndex), + pd.PeriodIndex, + ) From 6d1be80632d0ad46a692fa13926a349173860227 Mon Sep 17 00:00:00 2001 From: Marco Gorelli <33491632+MarcoGorelli@users.noreply.github.com> Date: Tue, 19 Aug 2025 15:43:06 +0100 Subject: [PATCH 3/8] fixup return type --- pandas-stubs/core/indexes/period.pyi | 2 +- tests/test_indexes.py | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pandas-stubs/core/indexes/period.pyi b/pandas-stubs/core/indexes/period.pyi index 90c96430..9ed23088 100644 --- a/pandas-stubs/core/indexes/period.pyi +++ b/pandas-stubs/core/indexes/period.pyi @@ -56,7 +56,7 @@ class PeriodIndex(DatetimeIndexOpsMixin[pd.Period, np.object_], PeriodIndexField self, where: pd.DatetimeIndex | PeriodIndex, mask: np.ndarray[tuple[int], np.dtype[np.bool_]], - ) -> Self: ... + ) -> np.ndarray[tuple[int], np.dtype[np.integer]]: ... @property def is_full(self) -> bool: ... @property diff --git a/tests/test_indexes.py b/tests/test_indexes.py index 3d5fe9e2..240834a4 100644 --- a/tests/test_indexes.py +++ b/tests/test_indexes.py @@ -1509,6 +1509,8 @@ def test_period_index_asof_locs() -> None: where = pd.DatetimeIndex(["2023-05-30 00:12:00", "2023-06-01 00:00:00"]) mask = np.ones(2, dtype=bool) check( - assert_type(idx.asof_locs(where, mask), pd.PeriodIndex), - pd.PeriodIndex, + assert_type( + idx.asof_locs(where, mask), np.ndarray[tuple[int], np.dtype[np.integer]] + ), + np.ndarray, ) From 9167976702d0e5325ee121a94dd594b8f296722e Mon Sep 17 00:00:00 2001 From: Marco Gorelli <33491632+MarcoGorelli@users.noreply.github.com> Date: Tue, 19 Aug 2025 15:45:30 +0100 Subject: [PATCH 4/8] np.integer -> np.intp --- pandas-stubs/core/indexes/period.pyi | 2 +- tests/test_indexes.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas-stubs/core/indexes/period.pyi b/pandas-stubs/core/indexes/period.pyi index 9ed23088..427b9fec 100644 --- a/pandas-stubs/core/indexes/period.pyi +++ b/pandas-stubs/core/indexes/period.pyi @@ -56,7 +56,7 @@ class PeriodIndex(DatetimeIndexOpsMixin[pd.Period, np.object_], PeriodIndexField self, where: pd.DatetimeIndex | PeriodIndex, mask: np.ndarray[tuple[int], np.dtype[np.bool_]], - ) -> np.ndarray[tuple[int], np.dtype[np.integer]]: ... + ) -> np.ndarray[tuple[int], np.dtype[np.intp]]: ... @property def is_full(self) -> bool: ... @property diff --git a/tests/test_indexes.py b/tests/test_indexes.py index 240834a4..1f97a54f 100644 --- a/tests/test_indexes.py +++ b/tests/test_indexes.py @@ -1510,7 +1510,7 @@ def test_period_index_asof_locs() -> None: mask = np.ones(2, dtype=bool) check( assert_type( - idx.asof_locs(where, mask), np.ndarray[tuple[int], np.dtype[np.integer]] + idx.asof_locs(where, mask), np.ndarray[tuple[int], np.dtype[np.intp]] ), np.ndarray, ) From e4e54d9f2f3c31d8217c5ea735e987193c16d3be Mon Sep 17 00:00:00 2001 From: Marco Gorelli <33491632+MarcoGorelli@users.noreply.github.com> Date: Tue, 19 Aug 2025 16:14:15 +0100 Subject: [PATCH 5/8] fixup generics --- pandas-stubs/_typing.pyi | 2 +- pandas-stubs/core/indexes/period.pyi | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pandas-stubs/_typing.pyi b/pandas-stubs/_typing.pyi index 1dc22c5d..2f0732e7 100644 --- a/pandas-stubs/_typing.pyi +++ b/pandas-stubs/_typing.pyi @@ -889,7 +889,7 @@ IndexingInt: TypeAlias = ( ) # AxesData is used for data for Index -AxesData: TypeAlias = Mapping[S3, Any] | Axes | KeysView +AxesData: TypeAlias = Mapping[S3, Any] | Axes | KeysView[S3] # Any plain Python or numpy function Function: TypeAlias = np.ufunc | Callable[..., Any] diff --git a/pandas-stubs/core/indexes/period.pyi b/pandas-stubs/core/indexes/period.pyi index 427b9fec..01ddabbb 100644 --- a/pandas-stubs/core/indexes/period.pyi +++ b/pandas-stubs/core/indexes/period.pyi @@ -1,6 +1,7 @@ from collections.abc import Hashable import datetime from typing import ( + Any, overload, ) @@ -26,7 +27,7 @@ from pandas._typing import ( class PeriodIndex(DatetimeIndexOpsMixin[pd.Period, np.object_], PeriodIndexFieldOps): def __new__( cls, - data: AxesData | None = None, + data: AxesData[Any] | None = None, freq: Frequency | None = None, dtype: Dtype | None = None, copy: bool = False, From df651aa874cf5de6f8eb15e12c8cbdb473a72bb0 Mon Sep 17 00:00:00 2001 From: Marco Gorelli <33491632+MarcoGorelli@users.noreply.github.com> Date: Tue, 19 Aug 2025 16:21:42 +0100 Subject: [PATCH 6/8] __new__ return type too --- pandas-stubs/core/indexes/period.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas-stubs/core/indexes/period.pyi b/pandas-stubs/core/indexes/period.pyi index 01ddabbb..408d8d28 100644 --- a/pandas-stubs/core/indexes/period.pyi +++ b/pandas-stubs/core/indexes/period.pyi @@ -32,7 +32,7 @@ class PeriodIndex(DatetimeIndexOpsMixin[pd.Period, np.object_], PeriodIndexField dtype: Dtype | None = None, copy: bool = False, name: Hashable | None = None, - ): ... + ) -> Self: ... @property def values(self) -> np.ndarray[tuple[int], np.dtype[np.object_]]: ... @overload From 3f573c75edf75efd1130d4774359a03aaa6d81d3 Mon Sep 17 00:00:00 2001 From: Marco Gorelli <33491632+MarcoGorelli@users.noreply.github.com> Date: Fri, 22 Aug 2025 08:58:42 +0100 Subject: [PATCH 7/8] use np_1darray alias --- pandas-stubs/core/indexes/period.pyi | 5 +++-- tests/test_indexes.py | 6 ++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/pandas-stubs/core/indexes/period.pyi b/pandas-stubs/core/indexes/period.pyi index 408d8d28..1077dae6 100644 --- a/pandas-stubs/core/indexes/period.pyi +++ b/pandas-stubs/core/indexes/period.pyi @@ -22,6 +22,7 @@ from pandas._typing import ( AxesData, Dtype, Frequency, + np_1darray, ) class PeriodIndex(DatetimeIndexOpsMixin[pd.Period, np.object_], PeriodIndexFieldOps): @@ -34,7 +35,7 @@ class PeriodIndex(DatetimeIndexOpsMixin[pd.Period, np.object_], PeriodIndexField name: Hashable | None = None, ) -> Self: ... @property - def values(self) -> np.ndarray[tuple[int], np.dtype[np.object_]]: ... + def values(self) -> np_1darray[np.object_]: ... @overload def __sub__(self, other: Period) -> Index: ... @overload @@ -57,7 +58,7 @@ class PeriodIndex(DatetimeIndexOpsMixin[pd.Period, np.object_], PeriodIndexField self, where: pd.DatetimeIndex | PeriodIndex, mask: np.ndarray[tuple[int], np.dtype[np.bool_]], - ) -> np.ndarray[tuple[int], np.dtype[np.intp]]: ... + ) -> np_1darray[np.intp]: ... @property def is_full(self) -> bool: ... @property diff --git a/tests/test_indexes.py b/tests/test_indexes.py index 1f97a54f..280b5726 100644 --- a/tests/test_indexes.py +++ b/tests/test_indexes.py @@ -1509,8 +1509,6 @@ def test_period_index_asof_locs() -> None: where = pd.DatetimeIndex(["2023-05-30 00:12:00", "2023-06-01 00:00:00"]) mask = np.ones(2, dtype=bool) check( - assert_type( - idx.asof_locs(where, mask), np.ndarray[tuple[int], np.dtype[np.intp]] - ), - np.ndarray, + assert_type(idx.asof_locs(where, mask), np_1darray[np.intp]), + np_1darray[np.intp], ) From 6fc6a315db62cd1b12e5815a4625d4ecdc1728b6 Mon Sep 17 00:00:00 2001 From: Marco Gorelli <33491632+MarcoGorelli@users.noreply.github.com> Date: Fri, 22 Aug 2025 08:59:33 +0100 Subject: [PATCH 8/8] one more --- pandas-stubs/core/indexes/period.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas-stubs/core/indexes/period.pyi b/pandas-stubs/core/indexes/period.pyi index 1077dae6..87ee0af1 100644 --- a/pandas-stubs/core/indexes/period.pyi +++ b/pandas-stubs/core/indexes/period.pyi @@ -57,7 +57,7 @@ class PeriodIndex(DatetimeIndexOpsMixin[pd.Period, np.object_], PeriodIndexField def asof_locs( self, where: pd.DatetimeIndex | PeriodIndex, - mask: np.ndarray[tuple[int], np.dtype[np.bool_]], + mask: np_1darray[np.bool_], ) -> np_1darray[np.intp]: ... @property def is_full(self) -> bool: ...