Skip to content

Commit 55b483b

Browse files
avoid warning with inplace operators
1 parent 5f00be7 commit 55b483b

File tree

6 files changed

+32
-6
lines changed

6 files changed

+32
-6
lines changed

pandas/core/generic.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -12375,14 +12375,20 @@ def _inplace_method(self, other, op) -> Self:
1237512375
"""
1237612376
Wrap arithmetic method to operate inplace.
1237712377
"""
12378+
warn = True
12379+
if not PYPY and warn_copy_on_write():
12380+
if sys.getrefcount(self) <= 5:
12381+
# we are probably in an inplace setitem context (e.g. df['a'] += 1)
12382+
warn = False
12383+
1237812384
result = op(self, other)
1237912385

1238012386
if self.ndim == 1 and result._indexed_same(self) and result.dtype == self.dtype:
1238112387
# GH#36498 this inplace op can _actually_ be inplace.
1238212388
# Item "ArrayManager" of "Union[ArrayManager, SingleArrayManager,
1238312389
# BlockManager, SingleBlockManager]" has no attribute "setitem_inplace"
1238412390
self._mgr.setitem_inplace( # type: ignore[union-attr]
12385-
slice(None), result._values
12391+
slice(None), result._values, warn=warn
1238612392
)
1238712393
return self
1238812394

pandas/core/internals/base.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ def array(self) -> ArrayLike:
307307
# error: "SingleDataManager" has no attribute "arrays"; maybe "array"
308308
return self.arrays[0] # type: ignore[attr-defined]
309309

310-
def setitem_inplace(self, indexer, value) -> None:
310+
def setitem_inplace(self, indexer, value, warn: bool = True) -> None:
311311
"""
312312
Set values with indexer.
313313

pandas/core/internals/managers.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1981,7 +1981,7 @@ def get_numeric_data(self, copy: bool = False) -> Self:
19811981
def _can_hold_na(self) -> bool:
19821982
return self._block._can_hold_na
19831983

1984-
def setitem_inplace(self, indexer, value) -> None:
1984+
def setitem_inplace(self, indexer, value, warn: bool = True) -> None:
19851985
"""
19861986
Set values with indexer.
19871987
@@ -1995,7 +1995,7 @@ def setitem_inplace(self, indexer, value) -> None:
19951995
if using_copy_on_write():
19961996
self.blocks = (self._block.copy(),)
19971997
self._cache.clear()
1998-
elif warn_copy_on_write():
1998+
elif warn and warn_copy_on_write():
19991999
warnings.warn(
20002000
"Setting value on view: behaviour will change in pandas 3.0 "
20012001
"with Copy-on-Write ...",

pandas/tests/copy_view/test_setitem.py

+16
Original file line numberDiff line numberDiff line change
@@ -140,3 +140,19 @@ def test_setitem_series_column_midx_broadcasting(using_copy_on_write):
140140
assert not np.shares_memory(get_array(rhs), df._get_column_array(0))
141141
if using_copy_on_write:
142142
assert df._mgr._has_no_reference(0)
143+
144+
145+
def test_set_column_with_inplace_operator(using_copy_on_write, warn_copy_on_write):
146+
df = DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})
147+
148+
# this should not raise any warning
149+
with tm.assert_produces_warning(None):
150+
df["a"] += 1
151+
152+
# when it is not in a chain, then it should produce a warning
153+
warn = FutureWarning if warn_copy_on_write else None
154+
155+
df = DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})
156+
ser = df["a"]
157+
with tm.assert_produces_warning(warn):
158+
ser += 1

pandas/tests/frame/test_arithmetic.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -2029,14 +2029,16 @@ def test_arith_list_of_arraylike_raise(to_add):
20292029
to_add + df
20302030

20312031

2032-
def test_inplace_arithmetic_series_update(using_copy_on_write):
2032+
def test_inplace_arithmetic_series_update(using_copy_on_write, warn_copy_on_write):
20332033
# https://github.com/pandas-dev/pandas/issues/36373
20342034
df = DataFrame({"A": [1, 2, 3]})
20352035
df_orig = df.copy()
20362036
series = df["A"]
20372037
vals = series._values
20382038

2039-
series += 1
2039+
warn = FutureWarning if warn_copy_on_write else None
2040+
with tm.assert_produces_warning(warn):
2041+
series += 1
20402042
if using_copy_on_write:
20412043
assert series._values is not vals
20422044
tm.assert_frame_equal(df, df_orig)

pandas/tests/frame/test_subclass.py

+2
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,8 @@ def test_subclassed_wide_to_long(self):
520520

521521
tm.assert_frame_equal(long_frame, expected)
522522

523+
# TODO(CoW) should not need to warn
524+
@pytest.mark.filterwarnings("ignore:Setting value on view:FutureWarning")
523525
def test_subclassed_apply(self):
524526
# GH 19822
525527

0 commit comments

Comments
 (0)