11import numpy as np
22import pytest
33
4+ from pandas .compat import PY311
45from pandas .errors import (
56 ChainedAssignmentError ,
67 SettingWithCopyWarning ,
@@ -42,7 +43,9 @@ def test_methods_iloc_warn(using_copy_on_write):
4243 ("ffill" , ()),
4344 ],
4445)
45- def test_methods_iloc_getitem_item_cache (func , args , using_copy_on_write ):
46+ def test_methods_iloc_getitem_item_cache (
47+ func , args , using_copy_on_write , warn_copy_on_write
48+ ):
4649 # ensure we don't incorrectly raise chained assignment warning because
4750 # of the item cache / iloc not setting the item cache
4851 df_orig = DataFrame ({"a" : [1 , 2 , 3 ], "b" : 1 })
@@ -66,14 +69,74 @@ def test_methods_iloc_getitem_item_cache(func, args, using_copy_on_write):
6669 ser = df ["a" ]
6770 getattr (ser , func )(* args , inplace = True )
6871
72+ df = df_orig .copy ()
73+ df ["a" ] # populate the item_cache
74+ # TODO(CoW-warn) because of the usage of *args, this doesn't warn on Py3.11+
75+ if using_copy_on_write :
76+ with tm .raises_chained_assignment_error (not PY311 ):
77+ getattr (df ["a" ], func )(* args , inplace = True )
78+ else :
79+ with tm .assert_cow_warning (not PY311 , match = "A value" ):
80+ getattr (df ["a" ], func )(* args , inplace = True )
81+
82+ df = df_orig .copy ()
83+ ser = df ["a" ] # populate the item_cache and keep ref
84+ if using_copy_on_write :
85+ with tm .raises_chained_assignment_error (not PY311 ):
86+ getattr (df ["a" ], func )(* args , inplace = True )
87+ else :
88+ # ideally also warns on the default mode, but the ser' _cacher
89+ # messes up the refcount + even in warning mode this doesn't trigger
90+ # the warning of Py3.1+ (see above)
91+ with tm .assert_cow_warning (warn_copy_on_write and not PY311 , match = "A value" ):
92+ getattr (df ["a" ], func )(* args , inplace = True )
93+
94+
95+ def test_methods_iloc_getitem_item_cache_fillna (
96+ using_copy_on_write , warn_copy_on_write
97+ ):
98+ # ensure we don't incorrectly raise chained assignment warning because
99+ # of the item cache / iloc not setting the item cache
100+ df_orig = DataFrame ({"a" : [1 , 2 , 3 ], "b" : 1 })
101+
102+ df = df_orig .copy ()
103+ ser = df .iloc [:, 0 ]
104+ ser .fillna (1 , inplace = True )
105+
106+ # parent that holds item_cache is dead, so don't increase ref count
107+ df = df_orig .copy ()
108+ ser = df .copy ()["a" ]
109+ ser .fillna (1 , inplace = True )
110+
111+ df = df_orig .copy ()
112+ df ["a" ] # populate the item_cache
113+ ser = df .iloc [:, 0 ] # iloc creates a new object
114+ ser .fillna (1 , inplace = True )
115+
116+ df = df_orig .copy ()
117+ df ["a" ] # populate the item_cache
118+ ser = df ["a" ]
119+ ser .fillna (1 , inplace = True )
120+
69121 df = df_orig .copy ()
70122 df ["a" ] # populate the item_cache
71123 if using_copy_on_write :
72124 with tm .raises_chained_assignment_error ():
73- df ["a" ].fillna (0 , inplace = True )
125+ df ["a" ].fillna (1 , inplace = True )
74126 else :
75127 with tm .assert_cow_warning (match = "A value" ):
76- df ["a" ].fillna (0 , inplace = True )
128+ df ["a" ].fillna (1 , inplace = True )
129+
130+ df = df_orig .copy ()
131+ ser = df ["a" ] # populate the item_cache and keep ref
132+ if using_copy_on_write :
133+ with tm .raises_chained_assignment_error ():
134+ df ["a" ].fillna (1 , inplace = True )
135+ else :
136+ # TODO(CoW-warn) ideally also warns on the default mode, but the ser' _cacher
137+ # messes up the refcount
138+ with tm .assert_cow_warning (warn_copy_on_write , match = "A value" ):
139+ df ["a" ].fillna (1 , inplace = True )
77140
78141
79142# TODO(CoW-warn) expand the cases
0 commit comments