diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 58d2b56e764f6..9f16340d98e22 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -62,6 +62,7 @@ InvalidIndexError, _chained_assignment_method_msg, _chained_assignment_msg, + _chained_assignment_warning_method_msg, ) from pandas.util._decorators import ( Appender, @@ -8849,6 +8850,13 @@ def update( ChainedAssignmentError, stacklevel=2, ) + elif not PYPY and not using_copy_on_write(): + if sys.getrefcount(self) <= REF_COUNT: + warnings.warn( + _chained_assignment_warning_method_msg, + FutureWarning, + stacklevel=2, + ) from pandas.core.computation import expressions diff --git a/pandas/core/series.py b/pandas/core/series.py index 1bbd10429ea22..a9679f22f9933 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -44,6 +44,7 @@ InvalidIndexError, _chained_assignment_method_msg, _chained_assignment_msg, + _chained_assignment_warning_method_msg, ) from pandas.util._decorators import ( Appender, @@ -3560,6 +3561,18 @@ def update(self, other: Series | Sequence | Mapping) -> None: ChainedAssignmentError, stacklevel=2, ) + elif not PYPY and not using_copy_on_write(): + ctr = sys.getrefcount(self) + ref_count = REF_COUNT + if hasattr(self, "_cacher"): + # see https://github.com/pandas-dev/pandas/pull/56060#discussion_r1399245221 + ref_count += 1 + if ctr <= ref_count: + warnings.warn( + _chained_assignment_warning_method_msg, + FutureWarning, + stacklevel=2, + ) if not isinstance(other, Series): other = Series(other) diff --git a/pandas/tests/copy_view/test_methods.py b/pandas/tests/copy_view/test_methods.py index 61569a49863cb..6416dd50daddc 100644 --- a/pandas/tests/copy_view/test_methods.py +++ b/pandas/tests/copy_view/test_methods.py @@ -12,6 +12,7 @@ Series, Timestamp, date_range, + option_context, period_range, ) import pandas._testing as tm @@ -1684,7 +1685,7 @@ def test_get(using_copy_on_write, warn_copy_on_write, key): warn = FutureWarning if isinstance(key, str) else None else: warn = SettingWithCopyWarning if isinstance(key, list) else None - with pd.option_context("chained_assignment", "warn"): + with option_context("chained_assignment", "warn"): with tm.assert_produces_warning(warn): result.iloc[0] = 0 @@ -1721,7 +1722,7 @@ def test_xs( with tm.assert_cow_warning(single_block or axis == 1): result.iloc[0] = 0 else: - with pd.option_context("chained_assignment", "warn"): + with option_context("chained_assignment", "warn"): with tm.assert_produces_warning(SettingWithCopyWarning): result.iloc[0] = 0 @@ -1756,7 +1757,7 @@ def test_xs_multiindex( warn = SettingWithCopyWarning else: warn = None - with pd.option_context("chained_assignment", "warn"): + with option_context("chained_assignment", "warn"): with tm.assert_produces_warning(warn): result.iloc[0, 0] = 0 @@ -1813,6 +1814,17 @@ def test_update_chained_assignment(using_copy_on_write): with tm.raises_chained_assignment_error(): df[["a"]].update(ser2.to_frame()) tm.assert_frame_equal(df, df_orig) + else: + with tm.assert_produces_warning(FutureWarning, match="inplace method"): + df["a"].update(ser2) + + with tm.assert_produces_warning(FutureWarning, match="inplace method"): + with option_context("mode.chained_assignment", None): + df[["a"]].update(ser2.to_frame()) + + with tm.assert_produces_warning(FutureWarning, match="inplace method"): + with option_context("mode.chained_assignment", None): + df[df["a"] > 1].update(ser2.to_frame()) def test_inplace_arithmetic_series(using_copy_on_write): diff --git a/pandas/tests/series/indexing/test_indexing.py b/pandas/tests/series/indexing/test_indexing.py index 0e850c2d20e72..b108ec24732ac 100644 --- a/pandas/tests/series/indexing/test_indexing.py +++ b/pandas/tests/series/indexing/test_indexing.py @@ -295,7 +295,8 @@ def test_underlying_data_conversion(using_copy_on_write): df["val"].update(s) expected = df_original else: - df["val"].update(s) + with tm.assert_produces_warning(FutureWarning, match="inplace method"): + df["val"].update(s) expected = DataFrame( {"a": [1, 2, 3], "b": [1, 2, 3], "c": [1, 2, 3], "val": [0, 1, 0]} ) diff --git a/pandas/tests/series/methods/test_update.py b/pandas/tests/series/methods/test_update.py index 3745c045078b7..3f18ae6c13880 100644 --- a/pandas/tests/series/methods/test_update.py +++ b/pandas/tests/series/methods/test_update.py @@ -34,7 +34,8 @@ def test_update(self, using_copy_on_write): df["c"].update(Series(["foo"], index=[0])) expected = df_orig else: - df["c"].update(Series(["foo"], index=[0])) + with tm.assert_produces_warning(FutureWarning, match="inplace method"): + df["c"].update(Series(["foo"], index=[0])) expected = DataFrame( [[1, np.nan, "foo"], [3, 2.0, np.nan]], columns=["a", "b", "c"] )