diff --git a/pandas-stubs/core/indexes/accessors.pyi b/pandas-stubs/core/indexes/accessors.pyi index 477d96d21..61d24d45c 100644 --- a/pandas-stubs/core/indexes/accessors.pyi +++ b/pandas-stubs/core/indexes/accessors.pyi @@ -444,7 +444,9 @@ class TimedeltaIndexProperties( @type_check_only class DtDescriptor: @overload - def __get__(self, instance: Series[Never], owner: type[Series]) -> Properties: ... + def __get__( + self, instance: Series[Never], owner: type[Series] + ) -> CombinedDatetimelikeProperties: ... @overload def __get__( self, instance: Series[Timestamp], owner: type[Series] diff --git a/tests/series/test_properties.py b/tests/series/test_properties.py index 21ce75931..844336ab9 100644 --- a/tests/series/test_properties.py +++ b/tests/series/test_properties.py @@ -8,9 +8,9 @@ from pandas.core.arrays.timedeltas import TimedeltaArray from pandas.core.frame import DataFrame from pandas.core.indexes.accessors import ( + CombinedDatetimelikeProperties, DatetimeProperties, PeriodProperties, - Properties, TimedeltaProperties, ) from pandas.core.indexes.interval import interval_range @@ -49,12 +49,37 @@ def test_property_dt() -> None: PeriodProperties, ) + df = DataFrame({"ts": [Timestamp(2025, 12, 6)], "td": [Timedelta(1, "s")]}) + # python/mypy#19952: mypy gives Any + check( + assert_type( # type: ignore[assert-type] + df["ts"].dt, CombinedDatetimelikeProperties + ), + DatetimeProperties, + ) + check( + assert_type( # type: ignore[assert-type] + df["td"].dt, CombinedDatetimelikeProperties + ), + TimedeltaProperties, + ) + + check( + assert_type(df["ts"].dt.year, "Series[int]"), # type: ignore[assert-type] + Series, + np.integer, + ) + check( + assert_type( # type: ignore[assert-type] + df["td"].dt.total_seconds(), "Series[float]" + ), + Series, + np.floating, + ) + if TYPE_CHECKING_INVALID_USAGE: - s = DataFrame({"a": [1]})["a"] - # python/mypy#19952: mypy believes Properties and its subclasses have a - # conflict and gives Any for s.dt - assert_type(s.dt, Properties) # type: ignore[assert-type] - _1 = Series([1]).dt # type: ignore[arg-type] # pyright: ignore[reportAttributeAccessIssue] + _0 = Series([1]).dt # type: ignore[arg-type] # pyright: ignore[reportAttributeAccessIssue] + _1 = Series(["2025-01-01"]).dt # type: ignore[arg-type] # pyright: ignore[reportAttributeAccessIssue] def test_property_array() -> None: