Skip to content

Commit

Permalink
CoW: Add warning for update (pandas-dev#56068)
Browse files Browse the repository at this point in the history
  • Loading branch information
phofl authored Nov 22, 2023
1 parent f331b83 commit 219bc5e
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 5 deletions.
8 changes: 8 additions & 0 deletions pandas/core/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
InvalidIndexError,
_chained_assignment_method_msg,
_chained_assignment_msg,
_chained_assignment_warning_method_msg,
)
from pandas.util._decorators import (
Appender,
Expand Down Expand Up @@ -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

Expand Down
13 changes: 13 additions & 0 deletions pandas/core/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
InvalidIndexError,
_chained_assignment_method_msg,
_chained_assignment_msg,
_chained_assignment_warning_method_msg,
)
from pandas.util._decorators import (
Appender,
Expand Down Expand Up @@ -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)
Expand Down
18 changes: 15 additions & 3 deletions pandas/tests/copy_view/test_methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
Series,
Timestamp,
date_range,
option_context,
period_range,
)
import pandas._testing as tm
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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):
Expand Down
3 changes: 2 additions & 1 deletion pandas/tests/series/indexing/test_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]}
)
Expand Down
3 changes: 2 additions & 1 deletion pandas/tests/series/methods/test_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
)
Expand Down

0 comments on commit 219bc5e

Please sign in to comment.