26
26
27
27
import numpy as np
28
28
29
- from pandas ._config import using_copy_on_write
29
+ from pandas ._config import (
30
+ using_copy_on_write ,
31
+ warn_copy_on_write ,
32
+ )
30
33
from pandas ._config .config import _get_option
31
34
32
35
from pandas ._libs import (
45
48
_chained_assignment_method_msg ,
46
49
_chained_assignment_msg ,
47
50
_chained_assignment_warning_method_msg ,
51
+ _chained_assignment_warning_msg ,
48
52
_check_cacher ,
49
53
)
50
54
from pandas .util ._decorators import (
@@ -1221,11 +1225,29 @@ def _get_value(self, label, takeable: bool = False):
1221
1225
return self .iloc [loc ]
1222
1226
1223
1227
def __setitem__ (self , key , value ) -> None :
1228
+ warn = True
1224
1229
if not PYPY and using_copy_on_write ():
1225
1230
if sys .getrefcount (self ) <= 3 :
1226
1231
warnings .warn (
1227
1232
_chained_assignment_msg , ChainedAssignmentError , stacklevel = 2
1228
1233
)
1234
+ elif not PYPY and not using_copy_on_write ():
1235
+ ctr = sys .getrefcount (self )
1236
+ ref_count = 3
1237
+ if not warn_copy_on_write () and _check_cacher (self ):
1238
+ # see https://github.com/pandas-dev/pandas/pull/56060#discussion_r1399245221
1239
+ ref_count += 1
1240
+ if ctr <= ref_count and (
1241
+ warn_copy_on_write ()
1242
+ or (
1243
+ not warn_copy_on_write ()
1244
+ and self ._mgr .blocks [0 ].refs .has_reference () # type: ignore[union-attr]
1245
+ )
1246
+ ):
1247
+ warn = False
1248
+ warnings .warn (
1249
+ _chained_assignment_warning_msg , FutureWarning , stacklevel = 2
1250
+ )
1229
1251
1230
1252
check_dict_or_set_indexers (key )
1231
1253
key = com .apply_if_callable (key , self )
@@ -1236,10 +1258,10 @@ def __setitem__(self, key, value) -> None:
1236
1258
1237
1259
if isinstance (key , slice ):
1238
1260
indexer = self .index ._convert_slice_indexer (key , kind = "getitem" )
1239
- return self ._set_values (indexer , value )
1261
+ return self ._set_values (indexer , value , warn = warn )
1240
1262
1241
1263
try :
1242
- self ._set_with_engine (key , value )
1264
+ self ._set_with_engine (key , value , warn = warn )
1243
1265
except KeyError :
1244
1266
# We have a scalar (or for MultiIndex or object-dtype, scalar-like)
1245
1267
# key that is not present in self.index.
@@ -1305,18 +1327,18 @@ def __setitem__(self, key, value) -> None:
1305
1327
return
1306
1328
1307
1329
else :
1308
- self ._set_with (key , value )
1330
+ self ._set_with (key , value , warn = warn )
1309
1331
1310
1332
if cacher_needs_updating :
1311
1333
self ._maybe_update_cacher (inplace = True )
1312
1334
1313
- def _set_with_engine (self , key , value ) -> None :
1335
+ def _set_with_engine (self , key , value , warn : bool = True ) -> None :
1314
1336
loc = self .index .get_loc (key )
1315
1337
1316
1338
# this is equivalent to self._values[key] = value
1317
- self ._mgr .setitem_inplace (loc , value )
1339
+ self ._mgr .setitem_inplace (loc , value , warn = warn )
1318
1340
1319
- def _set_with (self , key , value ) -> None :
1341
+ def _set_with (self , key , value , warn : bool = True ) -> None :
1320
1342
# We got here via exception-handling off of InvalidIndexError, so
1321
1343
# key should always be listlike at this point.
1322
1344
assert not isinstance (key , tuple )
@@ -1327,7 +1349,7 @@ def _set_with(self, key, value) -> None:
1327
1349
1328
1350
if not self .index ._should_fallback_to_positional :
1329
1351
# Regardless of the key type, we're treating it as labels
1330
- self ._set_labels (key , value )
1352
+ self ._set_labels (key , value , warn = warn )
1331
1353
1332
1354
else :
1333
1355
# Note: key_type == "boolean" should not occur because that
@@ -1344,23 +1366,23 @@ def _set_with(self, key, value) -> None:
1344
1366
FutureWarning ,
1345
1367
stacklevel = find_stack_level (),
1346
1368
)
1347
- self ._set_values (key , value )
1369
+ self ._set_values (key , value , warn = warn )
1348
1370
else :
1349
- self ._set_labels (key , value )
1371
+ self ._set_labels (key , value , warn = warn )
1350
1372
1351
- def _set_labels (self , key , value ) -> None :
1373
+ def _set_labels (self , key , value , warn : bool = True ) -> None :
1352
1374
key = com .asarray_tuplesafe (key )
1353
1375
indexer : np .ndarray = self .index .get_indexer (key )
1354
1376
mask = indexer == - 1
1355
1377
if mask .any ():
1356
1378
raise KeyError (f"{ key [mask ]} not in index" )
1357
- self ._set_values (indexer , value )
1379
+ self ._set_values (indexer , value , warn = warn )
1358
1380
1359
- def _set_values (self , key , value ) -> None :
1381
+ def _set_values (self , key , value , warn : bool = True ) -> None :
1360
1382
if isinstance (key , (Index , Series )):
1361
1383
key = key ._values
1362
1384
1363
- self ._mgr = self ._mgr .setitem (indexer = key , value = value )
1385
+ self ._mgr = self ._mgr .setitem (indexer = key , value = value , warn = warn )
1364
1386
self ._maybe_update_cacher ()
1365
1387
1366
1388
def _set_value (self , label , value , takeable : bool = False ) -> None :
0 commit comments