From f7a09217a2582efda10defd82636d48cd2d19c4c Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Sat, 6 Dec 2025 22:13:20 +0100 Subject: [PATCH 1/2] #1519 #1524 --- pandas-stubs/core/indexes/accessors.pyi | 4 +++- tests/series/test_properties.py | 23 +++++++++++++++++------ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/pandas-stubs/core/indexes/accessors.pyi b/pandas-stubs/core/indexes/accessors.pyi index 477d96d21..77f66e393 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] + ) -> TimestampProperties | TimedeltaProperties | PeriodProperties: ... @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..7993a9642 100644 --- a/tests/series/test_properties.py +++ b/tests/series/test_properties.py @@ -10,7 +10,6 @@ from pandas.core.indexes.accessors import ( DatetimeProperties, PeriodProperties, - Properties, TimedeltaProperties, ) from pandas.core.indexes.interval import interval_range @@ -49,12 +48,24 @@ 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, "TimestampProperties | TimedeltaProperties | PeriodProperties" + ), + DatetimeProperties, + ) + check( + assert_type( # type: ignore[assert-type] + df["td"].dt, "TimestampProperties | TimedeltaProperties | PeriodProperties" + ), + TimedeltaProperties, + ) + 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: From 5e2215f73ca4f5ad145e27c858ab54fa703aa2a2 Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Mon, 8 Dec 2025 10:56:50 +0100 Subject: [PATCH 2/2] https://github.com/pandas-dev/pandas-stubs/pull/1531#discussion_r2595486542 --- pandas-stubs/core/indexes/accessors.pyi | 2 +- tests/series/test_properties.py | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/pandas-stubs/core/indexes/accessors.pyi b/pandas-stubs/core/indexes/accessors.pyi index 77f66e393..61d24d45c 100644 --- a/pandas-stubs/core/indexes/accessors.pyi +++ b/pandas-stubs/core/indexes/accessors.pyi @@ -446,7 +446,7 @@ class DtDescriptor: @overload def __get__( self, instance: Series[Never], owner: type[Series] - ) -> TimestampProperties | TimedeltaProperties | PeriodProperties: ... + ) -> 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 7993a9642..844336ab9 100644 --- a/tests/series/test_properties.py +++ b/tests/series/test_properties.py @@ -8,6 +8,7 @@ from pandas.core.arrays.timedeltas import TimedeltaArray from pandas.core.frame import DataFrame from pandas.core.indexes.accessors import ( + CombinedDatetimelikeProperties, DatetimeProperties, PeriodProperties, TimedeltaProperties, @@ -52,17 +53,30 @@ def test_property_dt() -> None: # python/mypy#19952: mypy gives Any check( assert_type( # type: ignore[assert-type] - df["ts"].dt, "TimestampProperties | TimedeltaProperties | PeriodProperties" + df["ts"].dt, CombinedDatetimelikeProperties ), DatetimeProperties, ) check( assert_type( # type: ignore[assert-type] - df["td"].dt, "TimestampProperties | TimedeltaProperties | PeriodProperties" + 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: _0 = Series([1]).dt # type: ignore[arg-type] # pyright: ignore[reportAttributeAccessIssue] _1 = Series(["2025-01-01"]).dt # type: ignore[arg-type] # pyright: ignore[reportAttributeAccessIssue]