Skip to content

Commit 261eabb

Browse files
authored
Add accessors for PeriodIndex (#505)
1 parent c9a8a73 commit 261eabb

File tree

4 files changed

+72
-11
lines changed

4 files changed

+72
-11
lines changed

pandas-stubs/core/indexes/accessors.pyi

+35-9
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,15 @@ class Properties(PandasDelegate, PandasObject, NoNewAttributesMixin):
4545

4646
_DTFieldOpsReturnType = TypeVar("_DTFieldOpsReturnType", Series[int], IntegerIndex)
4747

48-
class _DatetimeFieldOps(Generic[_DTFieldOpsReturnType]):
48+
class _DatetimeFieldOps(
49+
_DayLikeFieldOps[_DTFieldOpsReturnType], _MiniSeconds[_DTFieldOpsReturnType]
50+
): ...
51+
class PeriodIndexFieldOps(
52+
_DayLikeFieldOps[IntegerIndex],
53+
_PeriodProperties[DatetimeIndex, IntegerIndex, Index, DatetimeIndex, PeriodIndex],
54+
): ...
55+
56+
class _DayLikeFieldOps(Generic[_DTFieldOpsReturnType]):
4957
@property
5058
def year(self) -> _DTFieldOpsReturnType: ...
5159
@property
@@ -74,6 +82,8 @@ class _DatetimeFieldOps(Generic[_DTFieldOpsReturnType]):
7482
def days_in_month(self) -> _DTFieldOpsReturnType: ...
7583
@property
7684
def daysinmonth(self) -> _DTFieldOpsReturnType: ...
85+
86+
class _MiniSeconds(Generic[_DTFieldOpsReturnType]):
7787
@property
7888
def microsecond(self) -> _DTFieldOpsReturnType: ...
7989
@property
@@ -295,28 +305,44 @@ class TimedeltaProperties(
295305
_DatetimeRoundingMethods[TimedeltaSeries],
296306
): ...
297307

298-
class _PeriodProperties:
308+
_PeriodDTReturnTypes = TypeVar("_PeriodDTReturnTypes", TimestampSeries, DatetimeIndex)
309+
_PeriodIntReturnTypes = TypeVar("_PeriodIntReturnTypes", Series[int], IntegerIndex)
310+
_PeriodStrReturnTypes = TypeVar("_PeriodStrReturnTypes", Series[str], Index)
311+
_PeriodDTAReturnTypes = TypeVar("_PeriodDTAReturnTypes", DatetimeArray, DatetimeIndex)
312+
_PeriodPAReturnTypes = TypeVar("_PeriodPAReturnTypes", PeriodArray, PeriodIndex)
313+
314+
class _PeriodProperties(
315+
Generic[
316+
_PeriodDTReturnTypes,
317+
_PeriodIntReturnTypes,
318+
_PeriodStrReturnTypes,
319+
_PeriodDTAReturnTypes,
320+
_PeriodPAReturnTypes,
321+
]
322+
):
299323
@property
300-
def start_time(self) -> TimestampSeries: ...
324+
def start_time(self) -> _PeriodDTReturnTypes: ...
301325
@property
302-
def end_time(self) -> TimestampSeries: ...
326+
def end_time(self) -> _PeriodDTReturnTypes: ...
303327
@property
304-
def qyear(self) -> Series[int]: ...
305-
def strftime(self, date_format: str) -> Series[str]: ...
328+
def qyear(self) -> _PeriodIntReturnTypes: ...
329+
def strftime(self, date_format: str) -> _PeriodStrReturnTypes: ...
306330
def to_timestamp(
307331
self,
308332
freq: str | DateOffset | None = ...,
309333
how: TimestampConvention = ...,
310-
) -> DatetimeArray: ...
334+
) -> _PeriodDTAReturnTypes: ...
311335
def asfreq(
312336
self,
313337
freq: str | DateOffset | None = ...,
314338
how: Literal["E", "END", "FINISH", "S", "START", "BEGIN"] = ...,
315-
) -> PeriodArray: ...
339+
) -> _PeriodPAReturnTypes: ...
316340

317341
class PeriodProperties(
318342
Properties,
319-
_PeriodProperties,
343+
_PeriodProperties[
344+
TimestampSeries, Series[int], Series[str], DatetimeArray, PeriodArray
345+
],
320346
_DatetimeFieldOps[Series[int]],
321347
_IsLeapYearProperty,
322348
_FreqProperty[BaseOffset],

pandas-stubs/core/indexes/datetimelike.pyi

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ from pandas._libs.tslibs import BaseOffset
66
class DatetimeIndexOpsMixin(ExtensionIndex):
77
@property
88
def freq(self) -> BaseOffset | None: ...
9-
freqstr: str | None
9+
@property
10+
def freqstr(self) -> str | None: ...
1011
@property
1112
def is_all_dates(self) -> bool: ...
1213
@property

pandas-stubs/core/indexes/period.pyi

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ from typing import overload
44
import numpy as np
55
import pandas as pd
66
from pandas import Index
7+
from pandas.core.indexes.accessors import PeriodIndexFieldOps
78
from pandas.core.indexes.datetimelike import (
89
DatetimeIndexOpsMixin as DatetimeIndexOpsMixin,
910
)
@@ -15,7 +16,7 @@ from pandas._libs.tslibs import (
1516
Period,
1617
)
1718

18-
class PeriodIndex(DatetimeIndexOpsMixin, Int64Index):
19+
class PeriodIndex(DatetimeIndexOpsMixin, Int64Index, PeriodIndexFieldOps):
1920
def __new__(
2021
cls,
2122
data=...,
@@ -61,6 +62,8 @@ class PeriodIndex(DatetimeIndexOpsMixin, Int64Index):
6162
def intersection(self, other, sort: bool = ...): ...
6263
def difference(self, other, sort=...): ...
6364
def memory_usage(self, deep: bool = ...): ...
65+
@property
66+
def freqstr(self) -> str: ...
6467

6568
def period_range(
6669
start: str | pd.Period | None = ...,

tests/test_timefuncs.py

+31
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,37 @@ def test_timedeltaindex_accessors() -> None:
528528
check(assert_type(i0.ceil("D"), pd.TimedeltaIndex), pd.TimedeltaIndex, pd.Timedelta)
529529

530530

531+
def test_periodindex_accessors() -> None:
532+
# GH 395
533+
534+
i0 = pd.period_range(start="2022-06-01", periods=10)
535+
check(assert_type(i0, pd.PeriodIndex), pd.PeriodIndex, pd.Period)
536+
537+
check(assert_type(i0.year, IntegerIndex), IntegerIndex, int)
538+
check(assert_type(i0.month, IntegerIndex), IntegerIndex, int)
539+
check(assert_type(i0.day, IntegerIndex), IntegerIndex, int)
540+
check(assert_type(i0.hour, IntegerIndex), IntegerIndex, int)
541+
check(assert_type(i0.minute, IntegerIndex), IntegerIndex, int)
542+
check(assert_type(i0.second, IntegerIndex), IntegerIndex, int)
543+
check(assert_type(i0.dayofweek, IntegerIndex), IntegerIndex, int)
544+
check(assert_type(i0.day_of_week, IntegerIndex), IntegerIndex, int)
545+
check(assert_type(i0.weekday, IntegerIndex), IntegerIndex, int)
546+
check(assert_type(i0.dayofyear, IntegerIndex), IntegerIndex, int)
547+
check(assert_type(i0.day_of_year, IntegerIndex), IntegerIndex, int)
548+
check(assert_type(i0.quarter, IntegerIndex), IntegerIndex, int)
549+
check(assert_type(i0.daysinmonth, IntegerIndex), IntegerIndex, int)
550+
check(assert_type(i0.days_in_month, IntegerIndex), IntegerIndex, int)
551+
check(assert_type(i0.freq, Optional[BaseOffset]), BaseOffset)
552+
check(assert_type(i0.strftime("%Y"), pd.Index), pd.Index, str)
553+
check(assert_type(i0.asfreq("D"), pd.PeriodIndex), pd.PeriodIndex, pd.Period)
554+
check(assert_type(i0.end_time, pd.DatetimeIndex), pd.DatetimeIndex, pd.Timestamp)
555+
check(assert_type(i0.start_time, pd.DatetimeIndex), pd.DatetimeIndex, pd.Timestamp)
556+
check(
557+
assert_type(i0.to_timestamp(), pd.DatetimeIndex), pd.DatetimeIndex, pd.Timestamp
558+
)
559+
check(assert_type(i0.freqstr, str), str)
560+
561+
531562
def test_some_offsets() -> None:
532563
# GH 222
533564
check(

0 commit comments

Comments
 (0)