Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions pandas-stubs/_libs/tslibs/period.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@ from pandas import (
from typing_extensions import TypeAlias

from pandas._libs.tslibs import NaTType
from pandas._libs.tslibs.offsets import BaseOffset
from pandas._libs.tslibs.offsets import (
BaseOffset,
)
from pandas._libs.tslibs.timestamps import Timestamp
from pandas._typing import (
PeriodFrequency,
ShapeT,
np_1darray,
np_ndarray,
Expand Down Expand Up @@ -62,7 +65,7 @@ class Period(PeriodMixin):
value: (
Period | str | datetime.datetime | datetime.date | Timestamp | None
) = ...,
freq: str | BaseOffset | None = ...,
freq: PeriodFrequency | None = None,
ordinal: int | None = ...,
year: int | None = ...,
month: int | None = ...,
Expand Down Expand Up @@ -226,12 +229,12 @@ class Period(PeriodMixin):
def day_of_year(self) -> int: ...
@property
def day_of_week(self) -> int: ...
def asfreq(self, freq: str | BaseOffset, how: _PeriodFreqHow = "end") -> Period: ...
def asfreq(self, freq: PeriodFrequency, how: _PeriodFreqHow = "end") -> Period: ...
@classmethod
def now(cls, freq: str | BaseOffset = ...) -> Period: ...
def now(cls, freq: PeriodFrequency | None = None) -> Period: ...
def strftime(self, fmt: str) -> str: ...
def to_timestamp(
self,
freq: str | BaseOffset | None = ...,
freq: PeriodFrequency | None = None,
how: _PeriodToTimestampHow = "S",
) -> Timestamp: ...
8 changes: 4 additions & 4 deletions pandas-stubs/_libs/tslibs/timedeltas.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ from typing_extensions import (
)

from pandas._libs.tslibs import (
BaseOffset,
NaTType,
)
from pandas._libs.tslibs.period import Period
from pandas._libs.tslibs.timestamps import Timestamp
from pandas._typing import (
Frequency,
ShapeT,
TimeUnit,
np_1darray,
Expand Down Expand Up @@ -130,9 +130,9 @@ class Timedelta(timedelta):
@property
def asm8(self) -> np.timedelta64: ...
# TODO: round/floor/ceil could return NaT?
def round(self, freq: str | BaseOffset) -> Self: ...
def floor(self, freq: str | BaseOffset) -> Self: ...
def ceil(self, freq: str | BaseOffset) -> Self: ...
def round(self, freq: Frequency) -> Self: ...
def floor(self, freq: Frequency) -> Self: ...
def ceil(self, freq: Frequency) -> Self: ...
Comment on lines -131 to +135
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

docs say str but offset objects are also accepted, so I think it's ok to keep the current annotation

In [11]: pd.Timedelta(minutes=37).round(pd.tseries.offsets.Hour())
Out[11]: Timedelta('0 days 01:00:00')

@property
def resolution_string(self) -> str: ...
# Override due to more types supported than dt.timedelta
Expand Down
4 changes: 2 additions & 2 deletions pandas-stubs/_libs/tslibs/timestamps.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ from typing_extensions import (
)

from pandas._libs.tslibs import (
BaseOffset,
Period,
Tick,
Timedelta,
)
from pandas._typing import (
PeriodFrequency,
ShapeT,
TimestampNonexistent,
TimeUnit,
Expand Down Expand Up @@ -282,7 +282,7 @@ class Timestamp(datetime, SupportsIndex):
def is_year_end(self) -> bool: ...
def to_pydatetime(self, warn: bool = ...) -> datetime: ...
def to_datetime64(self) -> np.datetime64: ...
def to_period(self, freq: BaseOffset | str | None = ...) -> Period: ...
def to_period(self, freq: PeriodFrequency | None = ...) -> Period: ...
def to_julian_date(self) -> np.float64: ...
@property
def asm8(self) -> np.datetime64: ...
Expand Down
27 changes: 27 additions & 0 deletions pandas-stubs/_typing.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,19 @@ from pandas.core.dtypes.dtypes import (
)

from pandas.io.formats.format import EngFormatter
from pandas.tseries.offsets import (
Day,
Hour,
Micro,
Milli,
Minute,
MonthEnd,
Nano,
QuarterEnd,
Second,
Week,
YearEnd,
)

P = ParamSpec("P")

Expand Down Expand Up @@ -162,6 +175,20 @@ Suffixes: TypeAlias = tuple[str | None, str | None] | list[str | None]
Ordered: TypeAlias = bool | None
JSONSerializable: TypeAlias = PythonScalar | list | dict
Frequency: TypeAlias = str | BaseOffset
PeriodFrequency: TypeAlias = (
str
| Day
| Hour
| Minute
| Second
| Milli
| Micro
| Nano
| YearEnd
| QuarterEnd
| MonthEnd
| Week
)
Axes: TypeAlias = ListLike

RandomState: TypeAlias = (
Expand Down
5 changes: 4 additions & 1 deletion pandas-stubs/core/arrays/period.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ from pandas.core.arrays.datetimelike import (

from pandas._libs.tslibs import Timestamp
from pandas._libs.tslibs.period import Period
from pandas._typing import PeriodFrequency

class PeriodArray(DatetimeLikeArrayMixin, DatelikeOps):
__array_priority__: int = ...
Expand Down Expand Up @@ -37,6 +38,8 @@ class PeriodArray(DatetimeLikeArrayMixin, DatelikeOps):
def start_time(self) -> Timestamp: ...
@property
def end_time(self) -> Timestamp: ...
def to_timestamp(self, freq: str | None = ..., how: str = ...) -> Timestamp: ...
def to_timestamp(
self, freq: PeriodFrequency | None = None, how: str = ...
) -> Timestamp: ...
def asfreq(self, freq: str | None = ..., how: str = "E") -> Period: ...
def astype(self, dtype, copy: bool = True): ...
13 changes: 7 additions & 6 deletions pandas-stubs/core/frame.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ from pandas._libs.lib import _NoDefaultDoNotUse
from pandas._libs.missing import NAType
from pandas._libs.tslibs import BaseOffset
from pandas._libs.tslibs.nattype import NaTType
from pandas._libs.tslibs.offsets import DateOffset
from pandas._typing import (
S2,
AggFuncTypeBase,
Expand All @@ -106,6 +105,7 @@ from pandas._typing import (
FillnaOptions,
FloatFormatType,
FormattersType,
Frequency,
GroupByObjectNonScalar,
HashableT,
HashableT1,
Expand Down Expand Up @@ -135,6 +135,7 @@ from pandas._typing import (
NDFrameT,
NsmallestNlargestKeep,
ParquetEngine,
PeriodFrequency,
QuantileInterpolation,
RandomState,
ReadBuffer,
Expand Down Expand Up @@ -1683,14 +1684,14 @@ class DataFrame(NDFrame, OpsMixin, _GetItemHack):
) -> Self: ...
def to_timestamp(
self,
freq=...,
freq: PeriodFrequency | None = None,
Comment on lines 1684 to +1687
Copy link
Member Author

@MarcoGorelli MarcoGorelli Oct 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i've always found bizarre that to_timestamp only accepts period frequencies

In [4]: pd.Period('2020').to_timestamp('MS')
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[4], line 1
----> 1 pd.Period('2020').to_timestamp('MS')

File ~/scratch/.39venv/lib/python3.9/site-packages/pandas/_libs/tslibs/period.pyx:1868, in pandas._libs.tslibs.period._Period.to_timestamp()

AttributeError: 'pandas._libs.tslibs.offsets.MonthBegin' object has no attribute '_period_dtype_code'

(and, on newer versions of pandas):

In [2]: pd.Period('2020').to_timestamp('MS')
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
File pandas/_libs/tslibs/offsets.pyx:5363, in pandas._libs.tslibs.offsets.to_offset()

File pandas/_libs/tslibs/offsets.pyx:5246, in pandas._libs.tslibs.offsets._validate_to_offset_alias()

ValueError: for Period, please use 'M' instead of 'MS'

The above exception was the direct cause of the following exception:

ValueError                                Traceback (most recent call last)
Cell In[2], line 1
----> 1 pd.Period('2020').to_timestamp('MS')

File pandas/_libs/tslibs/period.pyx:2041, in pandas._libs.tslibs.period._Period.to_timestamp()

File pandas/_libs/tslibs/period.pyx:1771, in pandas._libs.tslibs.period._Period._maybe_convert_freq()

File pandas/_libs/tslibs/offsets.pyx:5402, in pandas._libs.tslibs.offsets.to_offset()

ValueError: Invalid frequency: MS, failed to parse with error message: ValueError("for Period, please use 'M' instead of 'MS'")

but whatever, if that's how it is then it should at least be typed to respect that 🤷

how: ToTimestampHow = ...,
axis: Axis = 0,
copy: _bool = True,
) -> Self: ...
def to_period(
self,
freq: _str | None = None,
freq: PeriodFrequency | None = None,
axis: Axis = 0,
copy: _bool = True,
) -> Self: ...
Expand Down Expand Up @@ -2224,7 +2225,7 @@ class DataFrame(NDFrame, OpsMixin, _GetItemHack):
self,
periods: int = 1,
fill_method: None = None,
freq: DateOffset | dt.timedelta | _str | None = ...,
freq: Frequency | dt.timedelta | None = ...,
Comment on lines -2227 to +2228
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the typing here was too tight to begin with

In [6]: s = pd.Series([1,2,3], index=pd.date_range('2020', freq='MS', periods=3))

In [7]: s.pct_change(freq='MS')
Out[7]:
2020-01-01    NaN
2020-02-01    1.0
2020-03-01    0.5
Freq: MS, dtype: float64

fill_value: Scalar | NAType | None = ...,
) -> Self: ...
def pop(self, item: _str) -> Series: ...
Expand Down Expand Up @@ -2341,7 +2342,7 @@ class DataFrame(NDFrame, OpsMixin, _GetItemHack):
@overload
def rolling(
self,
window: int | str | dt.timedelta | BaseOffset | BaseIndexer,
window: int | Frequency | dt.timedelta | BaseIndexer,
min_periods: int | None = ...,
center: _bool = ...,
on: Hashable | None = ...,
Expand All @@ -2355,7 +2356,7 @@ class DataFrame(NDFrame, OpsMixin, _GetItemHack):
@overload
def rolling(
self,
window: int | str | dt.timedelta | BaseOffset | BaseIndexer,
window: int | Frequency | dt.timedelta | BaseIndexer,
min_periods: int | None = ...,
center: _bool = ...,
on: Hashable | None = ...,
Expand Down
2 changes: 1 addition & 1 deletion pandas-stubs/core/groupby/groupby.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ class GroupBy(BaseGroupBy[NDFrameT]):
periods: int = ...,
fill_method: Literal["bfill", "ffill"] | None | _NoDefaultDoNotUse = ...,
limit: int | None | _NoDefaultDoNotUse = ...,
freq=...,
freq: Frequency | None = None,
axis: Axis | _NoDefaultDoNotUse = ...,
) -> NDFrameT: ...
@final
Expand Down
15 changes: 8 additions & 7 deletions pandas-stubs/core/indexes/accessors.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,12 @@ from typing_extensions import Never

from pandas._libs.interval import Interval
from pandas._libs.tslibs import BaseOffset
from pandas._libs.tslibs.offsets import DateOffset
from pandas._libs.tslibs.period import Period
from pandas._libs.tslibs.timedeltas import Timedelta
from pandas._libs.tslibs.timestamps import Timestamp
from pandas._typing import (
Frequency,
PeriodFrequency,
TimeAmbiguous,
TimeNonexistent,
TimestampConvention,
Expand Down Expand Up @@ -178,7 +179,7 @@ _DTTimestampTimedeltaReturnType = TypeVar(
class _DatetimeRoundingMethods(Generic[_DTTimestampTimedeltaReturnType]):
def round(
self,
freq: str | BaseOffset | None,
freq: Frequency | None,
ambiguous: Literal["raise", "infer", "NaT"] | bool | np_ndarray_bool = ...,
nonexistent: (
Literal["shift_forward", "shift_backward", "NaT", "raise"]
Expand All @@ -188,7 +189,7 @@ class _DatetimeRoundingMethods(Generic[_DTTimestampTimedeltaReturnType]):
) -> _DTTimestampTimedeltaReturnType: ...
def floor(
self,
freq: str | BaseOffset | None,
freq: Frequency | None,
ambiguous: Literal["raise", "infer", "NaT"] | bool | np_ndarray_bool = ...,
nonexistent: (
Literal["shift_forward", "shift_backward", "NaT", "raise"]
Expand All @@ -198,7 +199,7 @@ class _DatetimeRoundingMethods(Generic[_DTTimestampTimedeltaReturnType]):
) -> _DTTimestampTimedeltaReturnType: ...
def ceil(
self,
freq: str | BaseOffset | None,
freq: Frequency | None,
ambiguous: Literal["raise", "infer", "NaT"] | bool | np_ndarray_bool = ...,
nonexistent: (
Literal["shift_forward", "shift_backward", "NaT", "raise"]
Expand All @@ -225,7 +226,7 @@ class _DatetimeLikeNoTZMethods(
],
):
def to_period(
self, freq: str | BaseOffset | None = ...
self, freq: PeriodFrequency | None = None
) -> _DTToPeriodReturnType: ...
def tz_localize(
self,
Expand Down Expand Up @@ -357,12 +358,12 @@ class _PeriodProperties(
def strftime(self, date_format: str) -> _PeriodStrReturnTypes: ...
def to_timestamp(
self,
freq: str | DateOffset | None = ...,
freq: PeriodFrequency | None = None,
how: TimestampConvention = ...,
) -> _PeriodDTAReturnTypes: ...
def asfreq(
self,
freq: str | DateOffset | None = ...,
freq: PeriodFrequency | None = None,
how: Literal["E", "END", "FINISH", "S", "START", "BEGIN"] = ...,
) -> _PeriodPAReturnTypes: ...

Expand Down
14 changes: 6 additions & 8 deletions pandas-stubs/core/indexes/datetimes.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import numpy as np
from pandas import (
DataFrame,
Index,
Timedelta,
TimedeltaIndex,
Timestamp,
)
Expand All @@ -25,7 +24,6 @@ from pandas.core.indexes.datetimelike import DatetimeTimedeltaMixin
from pandas.core.series import Series
from typing_extensions import Self

from pandas._libs.tslibs.offsets import DateOffset
from pandas._typing import (
AxesData,
DateAndDatetimeLike,
Expand Down Expand Up @@ -99,14 +97,14 @@ class DatetimeIndex(
@property
def dtype(self) -> np.dtype | DatetimeTZDtype: ...
def shift(
self, periods: int = 1, freq: DateOffset | Timedelta | str | None = None
self, periods: int = 1, freq: Frequency | timedelta | None = None
) -> Self: ...

@overload
def date_range(
start: str | DateAndDatetimeLike,
end: str | DateAndDatetimeLike,
freq: str | timedelta | Timedelta | BaseOffset | None = None,
freq: Frequency | timedelta | None = None,
tz: TimeZones = None,
normalize: bool = False,
name: Hashable | None = None,
Expand All @@ -129,7 +127,7 @@ def date_range(
start: str | DateAndDatetimeLike,
*,
periods: int,
freq: str | timedelta | Timedelta | BaseOffset | None = None,
freq: Frequency | timedelta | None = None,
tz: TimeZones = None,
normalize: bool = False,
name: Hashable | None = None,
Expand All @@ -141,7 +139,7 @@ def date_range(
*,
end: str | DateAndDatetimeLike,
periods: int,
freq: str | timedelta | Timedelta | BaseOffset | None = None,
freq: Frequency | timedelta | None = None,
tz: TimeZones = None,
normalize: bool = False,
name: Hashable | None = None,
Expand All @@ -153,7 +151,7 @@ def bdate_range(
start: str | DateAndDatetimeLike | None = ...,
end: str | DateAndDatetimeLike | None = ...,
periods: int | None = ...,
freq: str | timedelta | Timedelta | BaseOffset = ...,
freq: Frequency | timedelta = ...,
tz: TimeZones = ...,
normalize: bool = ...,
name: Hashable | None = ...,
Expand All @@ -167,7 +165,7 @@ def bdate_range(
end: str | DateAndDatetimeLike | None = ...,
periods: int | None = ...,
*,
freq: str | timedelta | Timedelta | BaseOffset,
freq: Frequency | timedelta,
tz: TimeZones = ...,
normalize: bool = ...,
name: Hashable | None = ...,
Expand Down
Loading