Skip to content

Commit

Permalink
CoW: Avoid warning in case of expansion (pandas-dev#56391)
Browse files Browse the repository at this point in the history
  • Loading branch information
phofl authored Dec 8, 2023
1 parent 025ccb5 commit 91e251c
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 10 deletions.
17 changes: 12 additions & 5 deletions pandas/core/internals/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1325,16 +1325,16 @@ def column_setitem(
This is a method on the BlockManager level, to avoid creating an
intermediate Series at the DataFrame level (`s = df[loc]; s[idx] = value`)
"""
needs_to_warn = False
if warn_copy_on_write() and not self._has_no_reference(loc):
if not isinstance(
self.blocks[self.blknos[loc]].values,
(ArrowExtensionArray, ArrowStringArray),
):
warnings.warn(
COW_WARNING_GENERAL_MSG,
FutureWarning,
stacklevel=find_stack_level(),
)
# We might raise if we are in an expansion case, so defer
# warning till we actually updated
needs_to_warn = True

elif using_copy_on_write() and not self._has_no_reference(loc):
blkno = self.blknos[loc]
# Split blocks to only copy the column we want to modify
Expand All @@ -1358,6 +1358,13 @@ def column_setitem(
new_mgr = col_mgr.setitem((idx,), value)
self.iset(loc, new_mgr._block.values, inplace=True)

if needs_to_warn:
warnings.warn(
COW_WARNING_GENERAL_MSG,
FutureWarning,
stacklevel=find_stack_level(),
)

def insert(self, loc: int, item: Hashable, value: ArrayLike, refs=None) -> None:
"""
Insert item at selected position.
Expand Down
3 changes: 1 addition & 2 deletions pandas/tests/copy_view/test_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -1145,13 +1145,12 @@ def test_set_value_copy_only_necessary_column(
view = df[:]

if val == "a" and indexer[0] != slice(None):
# TODO(CoW-warn) assert the FutureWarning for CoW is also raised
with tm.assert_produces_warning(
FutureWarning, match="Setting an item of incompatible dtype is deprecated"
):
indexer_func(df)[indexer] = val
else:
with tm.assert_cow_warning(warn_copy_on_write):
with tm.assert_cow_warning(warn_copy_on_write and val == 100):
indexer_func(df)[indexer] = val

if using_copy_on_write:
Expand Down
4 changes: 1 addition & 3 deletions pandas/tests/frame/indexing/test_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -1397,9 +1397,7 @@ def test_iloc_setitem_enlarge_no_warning(self, warn_copy_on_write):
df = DataFrame(columns=["a", "b"])
expected = df.copy()
view = df[:]
# TODO(CoW-warn) false positive: shouldn't warn in case of enlargement?
with tm.assert_produces_warning(FutureWarning if warn_copy_on_write else None):
df.iloc[:, 0] = np.array([1, 2], dtype=np.float64)
df.iloc[:, 0] = np.array([1, 2], dtype=np.float64)
tm.assert_frame_equal(view, expected)

def test_loc_internals_not_updated_correctly(self):
Expand Down

0 comments on commit 91e251c

Please sign in to comment.