From a56a50caa219d953c12d69225528f8a04c65f593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Diridollou?= Date: Wed, 10 Dec 2025 16:54:38 -0500 Subject: [PATCH 1/6] GH1541 Revert Series[Any].__add__(str) --- pandas-stubs/core/series.pyi | 2 +- tests/series/test_series.py | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index 469d44ea0..6188024ef 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -1789,7 +1789,7 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): # just failed to generate these so I couldn't match # them up. @overload - def __add__(self: Series[Never], other: complex | ListLike) -> Series: ... + def __add__(self: Series[Never], other: _str | complex | ListLike) -> Series: ... @overload def __add__(self, other: Index[Never] | Series[Never]) -> Series: ... @overload diff --git a/tests/series/test_series.py b/tests/series/test_series.py index 33eee7915..f2ae4dc43 100644 --- a/tests/series/test_series.py +++ b/tests/series/test_series.py @@ -4080,3 +4080,11 @@ def test_series_index_setter() -> None: check(assert_type(sr.index, pd.Index), pd.Index) sr.index = [2, 3] check(assert_type(sr.index, pd.Index), pd.Index) + + +def test_series_add_str() -> None: + """Test Series.__add__ with Series[Any].""" + df = pd.DataFrame({0: ["a", "b"]}) + sr = df[0] + + check(assert_type(sr.__add__("c1"), pd.Series), pd.Series, str) From 4aa6173c6492b558ad994bf4a8cd9f32d149c3ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Diridollou?= Date: Wed, 10 Dec 2025 17:03:25 -0500 Subject: [PATCH 2/6] GH1541 Revert Series[Any].__add__(str) --- tests/series/test_series.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/series/test_series.py b/tests/series/test_series.py index f2ae4dc43..b6f82ed10 100644 --- a/tests/series/test_series.py +++ b/tests/series/test_series.py @@ -4087,4 +4087,4 @@ def test_series_add_str() -> None: df = pd.DataFrame({0: ["a", "b"]}) sr = df[0] - check(assert_type(sr.__add__("c1"), pd.Series), pd.Series, str) + check(assert_type(sr + "c1", pd.Series), pd.Series, str) From 3bbe2c130719290e20e4b811642b8b480816afa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Diridollou?= Date: Fri, 12 Dec 2025 13:41:03 -0500 Subject: [PATCH 3/6] GH1541 PR Feedback --- pandas-stubs/core/indexes/base.pyi | 4 ++-- pandas-stubs/core/series.pyi | 6 +++++- tests/series/arithmetic/str/test_add.py | 9 +++++++++ tests/series/test_series.py | 8 -------- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/pandas-stubs/core/indexes/base.pyi b/pandas-stubs/core/indexes/base.pyi index 3f3332940..35a610cf4 100644 --- a/pandas-stubs/core/indexes/base.pyi +++ b/pandas-stubs/core/indexes/base.pyi @@ -626,7 +626,7 @@ class Index(IndexOpsMixin[S1], ElementOpsMixin[S1]): def __lt__(self, other: Self | S1) -> np_1darray_bool: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] def __gt__(self, other: Self | S1) -> np_1darray_bool: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] @overload - def __add__(self: Index[Never], other: _str) -> Never: ... + def __add__(self: Index[Never], other: _str) -> Index[_str]: ... @overload def __add__( self: Index[Never], other: complex | ArrayLike | SequenceNotStr[S1] | Index @@ -680,7 +680,7 @@ class Index(IndexOpsMixin[S1], ElementOpsMixin[S1]): self: Index[_str], other: np_ndarray_str | Index[_str] ) -> Index[_str]: ... @overload - def __radd__(self: Index[Never], other: _str) -> Never: ... + def __radd__(self: Index[Never], other: _str) -> Index[_str]: ... @overload def __radd__( self: Index[Never], other: complex | ArrayLike | SequenceNotStr[S1] | Index diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index 6188024ef..b8326903c 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -1789,7 +1789,9 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): # just failed to generate these so I couldn't match # them up. @overload - def __add__(self: Series[Never], other: _str | complex | ListLike) -> Series: ... + def __add__(self: Series[Never], other: _str) -> Series[_str]: ... + @overload + def __add__(self: Series[Never], other: complex | ListLike) -> Series: ... @overload def __add__(self, other: Index[Never] | Series[Never]) -> Series: ... @overload @@ -2008,6 +2010,8 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): axis: int = 0, ) -> Series[_str]: ... @overload + def __radd__(self: Series[Never], other: _str) -> Series[_str]: ... + @overload def __radd__(self: Series[Never], other: complex | ListLike) -> Series: ... @overload def __radd__(self, other: Index[Never] | Series[Never]) -> Series: ... diff --git a/tests/series/arithmetic/str/test_add.py b/tests/series/arithmetic/str/test_add.py index 6aa5ce0ff..355d277b3 100644 --- a/tests/series/arithmetic/str/test_add.py +++ b/tests/series/arithmetic/str/test_add.py @@ -145,3 +145,12 @@ def test_add_pd_series() -> None: if TYPE_CHECKING_INVALID_USAGE: left.radd(i) # type: ignore[arg-type] # pyright: ignore[reportArgumentType, reportCallIssue] check(assert_type(left.radd(r0), "pd.Series[str]"), pd.Series, str) + + +def test_series_add_str() -> None: + """Test Series.__add__ with Series[Any].""" + df = pd.DataFrame({0: ["a", "b"]}) + sr = df[0] + + check(assert_type(sr + "c1", "pd.Series[str]"), pd.Series, str) + check(assert_type("c1" + sr, "pd.Series[str]"), pd.Series, str) diff --git a/tests/series/test_series.py b/tests/series/test_series.py index b6f82ed10..33eee7915 100644 --- a/tests/series/test_series.py +++ b/tests/series/test_series.py @@ -4080,11 +4080,3 @@ def test_series_index_setter() -> None: check(assert_type(sr.index, pd.Index), pd.Index) sr.index = [2, 3] check(assert_type(sr.index, pd.Index), pd.Index) - - -def test_series_add_str() -> None: - """Test Series.__add__ with Series[Any].""" - df = pd.DataFrame({0: ["a", "b"]}) - sr = df[0] - - check(assert_type(sr + "c1", pd.Series), pd.Series, str) From e63fe8caa85d5b5fbe06dd2bdd93ae591037a80f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Diridollou?= Date: Fri, 12 Dec 2025 14:18:31 -0500 Subject: [PATCH 4/6] GH1541 PR Feedback --- pandas-stubs/core/reshape/pivot.pyi | 20 +++++++++++++------- tests/indexes/arithmetic/test_add.py | 7 ++----- tests/test_timefuncs.py | 4 +++- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/pandas-stubs/core/reshape/pivot.pyi b/pandas-stubs/core/reshape/pivot.pyi index eb7d9d479..2aefd5d95 100644 --- a/pandas-stubs/core/reshape/pivot.pyi +++ b/pandas-stubs/core/reshape/pivot.pyi @@ -67,11 +67,13 @@ _Values: TypeAlias = SequenceNotStr[Any] | _ExtendedAnyArrayLike @overload def pivot_table( data: DataFrame, - values: _PivotTableValuesTypes[ + values: _PivotTableValuesTypes[ # ty: ignore[non-subscriptable] Hashable # ty: ignore[invalid-type-arguments] ] = None, - index: _PivotTableIndexTypes[Hashable] = None, # ty: ignore[invalid-type-arguments] - columns: _PivotTableColumnsTypes[ + index: _PivotTableIndexTypes[ # ty: ignore[non-subscriptable] + Hashable + ] = None, # ty: ignore[invalid-type-arguments] + columns: _PivotTableColumnsTypes[ # ty: ignore[non-subscriptable] Hashable # ty: ignore[invalid-type-arguments] ] = None, aggfunc: ( @@ -91,13 +93,15 @@ def pivot_table( @overload def pivot_table( data: DataFrame, - values: _PivotTableValuesTypes[ + values: _PivotTableValuesTypes[ # ty: ignore[non-subscriptable] Hashable # ty: ignore[invalid-type-arguments] ] = None, *, index: Grouper, columns: ( - _PivotTableColumnsTypes[Hashable] # ty: ignore[invalid-type-arguments] + _PivotTableColumnsTypes[ # ty: ignore[non-subscriptable] + Hashable + ] # ty: ignore[invalid-type-arguments] | np_ndarray | Index[Any] ) = None, @@ -116,11 +120,13 @@ def pivot_table( @overload def pivot_table( data: DataFrame, - values: _PivotTableValuesTypes[ + values: _PivotTableValuesTypes[ # ty: ignore[non-subscriptable] Hashable # ty: ignore[invalid-type-arguments] ] = None, index: ( - _PivotTableIndexTypes[Hashable] # ty: ignore[invalid-type-arguments] + _PivotTableIndexTypes[ # ty: ignore[invalid-type-arguments,non-subscriptable] + Hashable + ] | np_ndarray | Index[Any] ) = None, diff --git a/tests/indexes/arithmetic/test_add.py b/tests/indexes/arithmetic/test_add.py index c7c415b46..41b4acaf1 100644 --- a/tests/indexes/arithmetic/test_add.py +++ b/tests/indexes/arithmetic/test_add.py @@ -3,12 +3,10 @@ import numpy as np import pandas as pd from typing_extensions import ( - Never, assert_type, ) from tests import ( - TYPE_CHECKING_INVALID_USAGE, check, ) @@ -106,6 +104,5 @@ def test_add_i_py_str() -> None: """Test pd.Index[Any] (int) + Python str""" s = "abc" - if TYPE_CHECKING_INVALID_USAGE: - assert_type(left_i + s, Never) - assert_type(s + left_i, Never) + check(assert_type(left_i + s, "pd.Index[str]"), pd.Index, str) + check(assert_type(s + left_i, "pd.Index[str]"), pd.Index, str) diff --git a/tests/test_timefuncs.py b/tests/test_timefuncs.py index 0b210feb2..678317728 100644 --- a/tests/test_timefuncs.py +++ b/tests/test_timefuncs.py @@ -1,7 +1,9 @@ from __future__ import annotations import datetime as dt -from typing import TypeAlias +from typing import ( + TypeAlias, +) from dateutil.relativedelta import ( FR, From 17670b78be783e6a357486517ba98b1082d2d191 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Diridollou?= Date: Fri, 12 Dec 2025 14:23:59 -0500 Subject: [PATCH 5/6] GH1541 PR Feedback --- pandas-stubs/core/reshape/pivot.pyi | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pandas-stubs/core/reshape/pivot.pyi b/pandas-stubs/core/reshape/pivot.pyi index 2aefd5d95..2af85c5f8 100644 --- a/pandas-stubs/core/reshape/pivot.pyi +++ b/pandas-stubs/core/reshape/pivot.pyi @@ -71,8 +71,8 @@ def pivot_table( Hashable # ty: ignore[invalid-type-arguments] ] = None, index: _PivotTableIndexTypes[ # ty: ignore[non-subscriptable] - Hashable - ] = None, # ty: ignore[invalid-type-arguments] + Hashable # ty: ignore[invalid-type-arguments] + ] = None, columns: _PivotTableColumnsTypes[ # ty: ignore[non-subscriptable] Hashable # ty: ignore[invalid-type-arguments] ] = None, @@ -100,8 +100,8 @@ def pivot_table( index: Grouper, columns: ( _PivotTableColumnsTypes[ # ty: ignore[non-subscriptable] - Hashable - ] # ty: ignore[invalid-type-arguments] + Hashable # ty: ignore[invalid-type-arguments] + ] | np_ndarray | Index[Any] ) = None, @@ -124,8 +124,8 @@ def pivot_table( Hashable # ty: ignore[invalid-type-arguments] ] = None, index: ( - _PivotTableIndexTypes[ # ty: ignore[invalid-type-arguments,non-subscriptable] - Hashable + _PivotTableIndexTypes[ # ty: ignore[non-subscriptable] + Hashable # ty: ignore[invalid-type-arguments] ] | np_ndarray | Index[Any] From 4db2db1d7efa0dfdaa1461c14fa79310a68b1d52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Diridollou?= Date: Fri, 12 Dec 2025 14:30:27 -0500 Subject: [PATCH 6/6] GH1541 PR Feedback --- tests/indexes/arithmetic/test_add.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/indexes/arithmetic/test_add.py b/tests/indexes/arithmetic/test_add.py index 41b4acaf1..1316e8830 100644 --- a/tests/indexes/arithmetic/test_add.py +++ b/tests/indexes/arithmetic/test_add.py @@ -7,6 +7,7 @@ ) from tests import ( + TYPE_CHECKING_INVALID_USAGE, check, ) @@ -104,5 +105,7 @@ def test_add_i_py_str() -> None: """Test pd.Index[Any] (int) + Python str""" s = "abc" - check(assert_type(left_i + s, "pd.Index[str]"), pd.Index, str) - check(assert_type(s + left_i, "pd.Index[str]"), pd.Index, str) + if TYPE_CHECKING_INVALID_USAGE: + # relaxing typing, won't work at runtime though + assert_type(left_i + s, "pd.Index[str]") + assert_type(s + left_i, "pd.Index[str]")