@@ -101,7 +101,7 @@ def test_subset_column_selection_modify_parent(backend, using_copy_on_write):
101
101
tm .assert_frame_equal (subset , expected )
102
102
103
103
104
- def test_subset_row_slice (backend , using_copy_on_write ):
104
+ def test_subset_row_slice (backend , using_copy_on_write , warn_copy_on_write ):
105
105
# Case: taking a subset of the rows of a DataFrame using a slice
106
106
# + afterwards modifying the subset
107
107
_ , DataFrame , _ = backend
@@ -121,7 +121,8 @@ def test_subset_row_slice(backend, using_copy_on_write):
121
121
# INFO this no longer raise warning since pandas 1.4
122
122
# with pd.option_context("chained_assignment", "warn"):
123
123
# with tm.assert_produces_warning(SettingWithCopyWarning):
124
- subset .iloc [0 , 0 ] = 0
124
+ with tm .assert_cow_warning (warn_copy_on_write ):
125
+ subset .iloc [0 , 0 ] = 0
125
126
126
127
subset ._mgr ._verify_integrity ()
127
128
@@ -334,8 +335,11 @@ def test_subset_set_with_row_indexer(
334
335
pytest .skip ("setitem with labels selects on columns" )
335
336
336
337
# TODO(CoW-warn) should warn
337
- if using_copy_on_write or warn_copy_on_write :
338
+ if using_copy_on_write :
338
339
indexer_si (subset )[indexer ] = 0
340
+ elif warn_copy_on_write :
341
+ with tm .assert_cow_warning ():
342
+ indexer_si (subset )[indexer ] = 0
339
343
else :
340
344
# INFO iloc no longer raises warning since pandas 1.4
341
345
warn = SettingWithCopyWarning if indexer_si is tm .setitem else None
@@ -419,7 +423,7 @@ def test_subset_set_column(backend, using_copy_on_write, warn_copy_on_write):
419
423
"dtype" , ["int64" , "float64" ], ids = ["single-block" , "mixed-block" ]
420
424
)
421
425
def test_subset_set_column_with_loc (
422
- backend , using_copy_on_write , using_array_manager , dtype
426
+ backend , using_copy_on_write , warn_copy_on_write , using_array_manager , dtype
423
427
):
424
428
# Case: setting a single column with loc on a viewing subset
425
429
# -> subset.loc[:, col] = value
@@ -432,6 +436,9 @@ def test_subset_set_column_with_loc(
432
436
433
437
if using_copy_on_write :
434
438
subset .loc [:, "a" ] = np .array ([10 , 11 ], dtype = "int64" )
439
+ elif warn_copy_on_write :
440
+ with tm .assert_cow_warning ():
441
+ subset .loc [:, "a" ] = np .array ([10 , 11 ], dtype = "int64" )
435
442
else :
436
443
with pd .option_context ("chained_assignment" , "warn" ):
437
444
with tm .assert_produces_warning (
@@ -455,7 +462,9 @@ def test_subset_set_column_with_loc(
455
462
tm .assert_frame_equal (df , df_orig )
456
463
457
464
458
- def test_subset_set_column_with_loc2 (backend , using_copy_on_write , using_array_manager ):
465
+ def test_subset_set_column_with_loc2 (
466
+ backend , using_copy_on_write , warn_copy_on_write , using_array_manager
467
+ ):
459
468
# Case: setting a single column with loc on a viewing subset
460
469
# -> subset.loc[:, col] = value
461
470
# separate test for case of DataFrame of a single column -> takes a separate
@@ -467,6 +476,9 @@ def test_subset_set_column_with_loc2(backend, using_copy_on_write, using_array_m
467
476
468
477
if using_copy_on_write :
469
478
subset .loc [:, "a" ] = 0
479
+ elif warn_copy_on_write :
480
+ with tm .assert_cow_warning ():
481
+ subset .loc [:, "a" ] = 0
470
482
else :
471
483
with pd .option_context ("chained_assignment" , "warn" ):
472
484
with tm .assert_produces_warning (
@@ -528,7 +540,9 @@ def test_subset_set_columns(backend, using_copy_on_write, warn_copy_on_write, dt
528
540
[slice ("a" , "b" ), np .array ([True , True , False ]), ["a" , "b" ]],
529
541
ids = ["slice" , "mask" , "array" ],
530
542
)
531
- def test_subset_set_with_column_indexer (backend , indexer , using_copy_on_write ):
543
+ def test_subset_set_with_column_indexer (
544
+ backend , indexer , using_copy_on_write , warn_copy_on_write
545
+ ):
532
546
# Case: setting multiple columns with a column indexer on a viewing subset
533
547
# -> subset.loc[:, [col1, col2]] = value
534
548
_ , DataFrame , _ = backend
@@ -538,6 +552,9 @@ def test_subset_set_with_column_indexer(backend, indexer, using_copy_on_write):
538
552
539
553
if using_copy_on_write :
540
554
subset .loc [:, indexer ] = 0
555
+ elif warn_copy_on_write :
556
+ with tm .assert_cow_warning ():
557
+ subset .loc [:, indexer ] = 0
541
558
else :
542
559
with pd .option_context ("chained_assignment" , "warn" ):
543
560
# As of 2.0, this setitem attempts (successfully) to set values
@@ -659,10 +676,7 @@ def test_subset_chained_getitem_column(
659
676
# modify parent -> don't modify subset
660
677
subset = df [:]["a" ][0 :2 ]
661
678
df ._clear_item_cache ()
662
- # TODO(CoW-warn) should also warn for mixed block and nullable dtypes
663
- with tm .assert_cow_warning (
664
- warn_copy_on_write and dtype == "int64" and dtype_backend == "numpy"
665
- ):
679
+ with tm .assert_cow_warning (warn_copy_on_write ):
666
680
df .iloc [0 , 0 ] = 0
667
681
expected = Series ([1 , 2 ], name = "a" )
668
682
if using_copy_on_write :
@@ -765,8 +779,7 @@ def test_null_slice(backend, method, using_copy_on_write, warn_copy_on_write):
765
779
assert df2 is not df
766
780
767
781
# and those trigger CoW when mutated
768
- # TODO(CoW-warn) should also warn for nullable dtypes
769
- with tm .assert_cow_warning (warn_copy_on_write and dtype_backend == "numpy" ):
782
+ with tm .assert_cow_warning (warn_copy_on_write ):
770
783
df2 .iloc [0 , 0 ] = 0
771
784
if using_copy_on_write :
772
785
tm .assert_frame_equal (df , df_orig )
@@ -884,10 +897,10 @@ def test_series_subset_set_with_indexer(
884
897
# del operator
885
898
886
899
887
- def test_del_frame (backend , using_copy_on_write ):
900
+ def test_del_frame (backend , using_copy_on_write , warn_copy_on_write ):
888
901
# Case: deleting a column with `del` on a viewing child dataframe should
889
902
# not modify parent + update the references
890
- _ , DataFrame , _ = backend
903
+ dtype_backend , DataFrame , _ = backend
891
904
df = DataFrame ({"a" : [1 , 2 , 3 ], "b" : [4 , 5 , 6 ], "c" : [0.1 , 0.2 , 0.3 ]})
892
905
df_orig = df .copy ()
893
906
df2 = df [:]
@@ -901,11 +914,14 @@ def test_del_frame(backend, using_copy_on_write):
901
914
tm .assert_frame_equal (df2 , df_orig [["a" , "c" ]])
902
915
df2 ._mgr ._verify_integrity ()
903
916
904
- df .loc [0 , "b" ] = 200
917
+ # TODO(CoW-warn) false positive, this should not warn?
918
+ with tm .assert_cow_warning (warn_copy_on_write and dtype_backend == "numpy" ):
919
+ df .loc [0 , "b" ] = 200
905
920
assert np .shares_memory (get_array (df , "a" ), get_array (df2 , "a" ))
906
921
df_orig = df .copy ()
907
922
908
- df2 .loc [0 , "a" ] = 100
923
+ with tm .assert_cow_warning (warn_copy_on_write ):
924
+ df2 .loc [0 , "a" ] = 100
909
925
if using_copy_on_write :
910
926
# modifying child after deleting a column still doesn't update parent
911
927
tm .assert_frame_equal (df , df_orig )
@@ -1109,7 +1125,6 @@ def test_set_value_copy_only_necessary_column(
1109
1125
):
1110
1126
# When setting inplace, only copy column that is modified instead of the whole
1111
1127
# block (by splitting the block)
1112
- single_block = isinstance (col [0 ], int )
1113
1128
df = DataFrame ({"a" : [1 , 2 , 3 ], "b" : [4 , 5 , 6 ], "c" : col })
1114
1129
df_orig = df .copy ()
1115
1130
view = df [:]
@@ -1120,11 +1135,7 @@ def test_set_value_copy_only_necessary_column(
1120
1135
):
1121
1136
indexer_func (df )[indexer ] = val
1122
1137
else :
1123
- # TODO(CoW-warn) should also warn in the other cases
1124
- with tm .assert_cow_warning (
1125
- warn_copy_on_write
1126
- and not (indexer [0 ] == slice (None ) or (not single_block and val == 100 ))
1127
- ):
1138
+ with tm .assert_cow_warning (warn_copy_on_write ):
1128
1139
indexer_func (df )[indexer ] = val
1129
1140
1130
1141
if using_copy_on_write :
0 commit comments