From 58d0faaa1aef7dc374186279265ffae4f7172891 Mon Sep 17 00:00:00 2001 From: Lakshya Upadhyaya Date: Sat, 1 Nov 2025 09:07:24 +0000 Subject: [PATCH 01/12] DEPR: deprecate passing Series to Index.join - Add Pandas4Warning when Series is passed to Index.join - Add test for deprecation warning - Update whatsnew for v3.0.0 Closes #62897 --- doc/source/whatsnew/v3.0.0.rst | 1 + pandas/core/indexes/base.py | 10 ++++++++++ pandas/tests/indexes/test_common.py | 9 ++++++++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index 12f522301e121..3704afffb7298 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -737,6 +737,7 @@ Other Deprecations - Deprecated allowing ``fill_value`` that cannot be held in the original dtype (excepting NA values for integer and bool dtypes) in :meth:`Series.shift` and :meth:`DataFrame.shift` (:issue:`53802`) - Deprecated backward-compatibility behavior for :meth:`DataFrame.select_dtypes` matching "str" dtype when ``np.object_`` is specified (:issue:`61916`) - Deprecated option "future.no_silent_downcasting", as it is no longer used. In a future version accessing this option will raise (:issue:`59502`) +- Deprecated passing a :class:`Series` to :meth:`Index.join`, pass ``Index.join(other.index)`` instead (:issue:`62897`) - Deprecated silent casting of non-datetime 'other' to datetime in :meth:`Series.combine_first` (:issue:`62931`) - Deprecated slicing on a :class:`Series` or :class:`DataFrame` with a :class:`DatetimeIndex` using a ``datetime.date`` object, explicitly cast to :class:`Timestamp` instead (:issue:`35830`) - Deprecated the 'inplace' keyword from :meth:`Resampler.interpolate`, as passing ``True`` raises ``AttributeError`` (:issue:`58690`) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 72f7a1e086b60..f76d40b682d4d 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -69,6 +69,7 @@ from pandas.errors import ( DuplicateLabelError, InvalidIndexError, + Pandas4Warning ) from pandas.util._decorators import ( Appender, @@ -4426,6 +4427,15 @@ def join( (Index([1, 2, 3, 4, 5, 6], dtype='int64'), array([ 0, 1, 2, -1, -1, -1]), array([-1, -1, -1, 0, 1, 2])) """ + if not isinstance(other, Index): + warnings.warn( + f"Passing a Series to {type(self).__name__}.join is deprecated " + "and will raise in a future version. " + "Pass Index.join(other.index) instead.", + Pandas4Warning, + stacklevel=find_stack_level() + ) + other = ensure_index(other) sort = sort or how == "outer" diff --git a/pandas/tests/indexes/test_common.py b/pandas/tests/indexes/test_common.py index a842d174a4894..707b787401411 100644 --- a/pandas/tests/indexes/test_common.py +++ b/pandas/tests/indexes/test_common.py @@ -28,7 +28,7 @@ RangeIndex, ) import pandas._testing as tm - +from pandas.errors import Pandas4Warning class TestCommon: @pytest.mark.parametrize("name", [None, "new_name"]) @@ -523,3 +523,10 @@ def test_to_frame_name_tuple_multiindex(): result = idx.to_frame(name=(1, 2)) expected = pd.DataFrame([1], columns=MultiIndex.from_arrays([[1], [2]]), index=idx) tm.assert_frame_equal(result, expected) + +def test_join_series_deprecated(): + # GH#62897 + idx = pd.Index([1, 2]) + ser = pd.Series([1, 2, 2]) + with tm.assert_produces_warning(Pandas4Warning, match="Passing a Series"): + idx.join(ser) \ No newline at end of file From a37e394ffc2c9b5c5e5c47001a69981365289742 Mon Sep 17 00:00:00 2001 From: Lakshya Upadhyaya Date: Sat, 1 Nov 2025 13:02:10 +0000 Subject: [PATCH 02/12] STYLE: add newline at end of file --- pandas/tests/indexes/test_common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/indexes/test_common.py b/pandas/tests/indexes/test_common.py index 707b787401411..72832baac049a 100644 --- a/pandas/tests/indexes/test_common.py +++ b/pandas/tests/indexes/test_common.py @@ -529,4 +529,4 @@ def test_join_series_deprecated(): idx = pd.Index([1, 2]) ser = pd.Series([1, 2, 2]) with tm.assert_produces_warning(Pandas4Warning, match="Passing a Series"): - idx.join(ser) \ No newline at end of file + idx.join(ser) From 1040b40d4d19704a30640f69f8624f4f5cb318ba Mon Sep 17 00:00:00 2001 From: Lakshya Upadhyaya Date: Sat, 1 Nov 2025 13:32:50 +0000 Subject: [PATCH 03/12] Remove trailing whitespace --- pandas/core/indexes/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index f76d40b682d4d..6fdd823856bf3 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -4435,7 +4435,7 @@ def join( Pandas4Warning, stacklevel=find_stack_level() ) - + other = ensure_index(other) sort = sort or how == "outer" From 50a04564cdfcbaaa29e521a6b8e6f77051c70bc7 Mon Sep 17 00:00:00 2001 From: Lakshya Upadhyaya Date: Sat, 1 Nov 2025 14:07:08 +0000 Subject: [PATCH 04/12] Fix import ordering --- pandas/tests/indexes/test_common.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pandas/tests/indexes/test_common.py b/pandas/tests/indexes/test_common.py index 72832baac049a..280d206b61f06 100644 --- a/pandas/tests/indexes/test_common.py +++ b/pandas/tests/indexes/test_common.py @@ -14,6 +14,7 @@ import pytest from pandas.compat import IS64 +from pandas.errors import Pandas4Warning from pandas.core.dtypes.common import ( is_integer_dtype, @@ -28,7 +29,7 @@ RangeIndex, ) import pandas._testing as tm -from pandas.errors import Pandas4Warning + class TestCommon: @pytest.mark.parametrize("name", [None, "new_name"]) From 26c9959881d6d7e486f448a7abc78b0741b283a0 Mon Sep 17 00:00:00 2001 From: Lakshya Upadhyaya Date: Sun, 2 Nov 2025 13:18:56 +0000 Subject: [PATCH 05/12] Add trailing comma to import --- pandas/core/indexes/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 6fdd823856bf3..02b707d614930 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -69,7 +69,7 @@ from pandas.errors import ( DuplicateLabelError, InvalidIndexError, - Pandas4Warning + Pandas4Warning, ) from pandas.util._decorators import ( Appender, From 0d254dd87c9a86ee1eaa8ca9aae3a4fba3bcd233 Mon Sep 17 00:00:00 2001 From: Lakshya Upadhyaya Date: Sun, 2 Nov 2025 14:19:42 +0000 Subject: [PATCH 06/12] Apply pre-commit auto-fixes --- pandas/core/indexes/base.py | 2 +- pandas/tests/indexes/test_common.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 02b707d614930..1885d00d57c59 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -4433,7 +4433,7 @@ def join( "and will raise in a future version. " "Pass Index.join(other.index) instead.", Pandas4Warning, - stacklevel=find_stack_level() + stacklevel=find_stack_level(), ) other = ensure_index(other) diff --git a/pandas/tests/indexes/test_common.py b/pandas/tests/indexes/test_common.py index 280d206b61f06..3656fb2af720e 100644 --- a/pandas/tests/indexes/test_common.py +++ b/pandas/tests/indexes/test_common.py @@ -525,6 +525,7 @@ def test_to_frame_name_tuple_multiindex(): expected = pd.DataFrame([1], columns=MultiIndex.from_arrays([[1], [2]]), index=idx) tm.assert_frame_equal(result, expected) + def test_join_series_deprecated(): # GH#62897 idx = pd.Index([1, 2]) From 90358b3626bed5b980beed7c73f9e1f3819b509c Mon Sep 17 00:00:00 2001 From: Lakshya Upadhyaya Date: Mon, 3 Nov 2025 18:36:00 +0000 Subject: [PATCH 07/12] DEPR: generalize join warning for non-Index objects --- pandas/core/indexes/base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 1885d00d57c59..bb3b9b4b740e9 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -4429,9 +4429,9 @@ def join( """ if not isinstance(other, Index): warnings.warn( - f"Passing a Series to {type(self).__name__}.join is deprecated " + f"Passing {type(other).__name__} to {type(self).__name__}.join is deprecated " "and will raise in a future version. " - "Pass Index.join(other.index) instead.", + "Pass an Index instead.", Pandas4Warning, stacklevel=find_stack_level(), ) From c67bf053373f3a79c6ca201384166e52cb30679e Mon Sep 17 00:00:00 2001 From: Lakshya Upadhyaya Date: Tue, 4 Nov 2025 02:55:58 +0000 Subject: [PATCH 08/12] Fix test to match updated warning message --- pandas/tests/indexes/test_common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/indexes/test_common.py b/pandas/tests/indexes/test_common.py index 3656fb2af720e..465ef673f52af 100644 --- a/pandas/tests/indexes/test_common.py +++ b/pandas/tests/indexes/test_common.py @@ -530,5 +530,5 @@ def test_join_series_deprecated(): # GH#62897 idx = pd.Index([1, 2]) ser = pd.Series([1, 2, 2]) - with tm.assert_produces_warning(Pandas4Warning, match="Passing a Series"): + with tm.assert_produces_warning(Pandas4Warning, match="Passing .* to .* is deprecated"): idx.join(ser) From 1702f50bb6c6c241aacd31147b33286714040d38 Mon Sep 17 00:00:00 2001 From: Lakshya Upadhyaya Date: Tue, 4 Nov 2025 06:54:46 +0000 Subject: [PATCH 09/12] STYLE: apply pre-commit formatting --- pandas/tests/indexes/test_common.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pandas/tests/indexes/test_common.py b/pandas/tests/indexes/test_common.py index 465ef673f52af..4802ff37056e6 100644 --- a/pandas/tests/indexes/test_common.py +++ b/pandas/tests/indexes/test_common.py @@ -530,5 +530,7 @@ def test_join_series_deprecated(): # GH#62897 idx = pd.Index([1, 2]) ser = pd.Series([1, 2, 2]) - with tm.assert_produces_warning(Pandas4Warning, match="Passing .* to .* is deprecated"): + with tm.assert_produces_warning( + Pandas4Warning, match="Passing .* to .* is deprecated" + ): idx.join(ser) From 91b3613691125d08d304af71660e21e391409ae7 Mon Sep 17 00:00:00 2001 From: Lakshya Upadhyaya Date: Tue, 4 Nov 2025 10:07:27 +0000 Subject: [PATCH 10/12] Fixed line too long error --- pandas/core/indexes/base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index bb3b9b4b740e9..52d8806b7f1e6 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -4429,8 +4429,8 @@ def join( """ if not isinstance(other, Index): warnings.warn( - f"Passing {type(other).__name__} to {type(self).__name__}.join is deprecated " - "and will raise in a future version. " + f"Passing {type(other).__name__} to {type(self).__name__}.join" + "is deprecated and will raise in a future version. " "Pass an Index instead.", Pandas4Warning, stacklevel=find_stack_level(), From 83205acc77f515767b31feed29e88d9d94de190e Mon Sep 17 00:00:00 2001 From: Lakshya Upadhyaya Date: Tue, 4 Nov 2025 13:38:16 +0000 Subject: [PATCH 11/12] Fixed missing space issue --- pandas/core/indexes/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 52d8806b7f1e6..d7c067299e374 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -4429,7 +4429,7 @@ def join( """ if not isinstance(other, Index): warnings.warn( - f"Passing {type(other).__name__} to {type(self).__name__}.join" + f"Passing {type(other).__name__} to {type(self).__name__}.join " "is deprecated and will raise in a future version. " "Pass an Index instead.", Pandas4Warning, From c717289be4f07c5e5d242890e446f52c1a80a6a9 Mon Sep 17 00:00:00 2001 From: Lakshya Upadhyaya Date: Tue, 4 Nov 2025 17:27:52 +0000 Subject: [PATCH 12/12] Update whatsnew to reflect deprecation of all non-Index types --- doc/source/whatsnew/v3.0.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index 3704afffb7298..e15bb32b38d56 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -737,7 +737,7 @@ Other Deprecations - Deprecated allowing ``fill_value`` that cannot be held in the original dtype (excepting NA values for integer and bool dtypes) in :meth:`Series.shift` and :meth:`DataFrame.shift` (:issue:`53802`) - Deprecated backward-compatibility behavior for :meth:`DataFrame.select_dtypes` matching "str" dtype when ``np.object_`` is specified (:issue:`61916`) - Deprecated option "future.no_silent_downcasting", as it is no longer used. In a future version accessing this option will raise (:issue:`59502`) -- Deprecated passing a :class:`Series` to :meth:`Index.join`, pass ``Index.join(other.index)`` instead (:issue:`62897`) +- Deprecated passing non-Index types to :meth:`Index.join`; explicitly convert to Index first (:issue:`62897`) - Deprecated silent casting of non-datetime 'other' to datetime in :meth:`Series.combine_first` (:issue:`62931`) - Deprecated slicing on a :class:`Series` or :class:`DataFrame` with a :class:`DatetimeIndex` using a ``datetime.date`` object, explicitly cast to :class:`Timestamp` instead (:issue:`35830`) - Deprecated the 'inplace' keyword from :meth:`Resampler.interpolate`, as passing ``True`` raises ``AttributeError`` (:issue:`58690`)