16
16
17
17
import numpy as np
18
18
19
- from pandas ._config import using_copy_on_write
19
+ from pandas ._config import (
20
+ using_copy_on_write ,
21
+ warn_copy_on_write ,
22
+ )
20
23
21
24
from pandas ._libs import (
22
25
internals as libinternals ,
97
100
from pandas .api .extensions import ExtensionArray
98
101
99
102
103
+ COW_WARNING_SETITEM_MSG = """\
104
+ Setting a value on a view: behaviour will change in pandas 3.0.
105
+ Currently, the mutation will also have effect on the object that shares data
106
+ with this object. For example, when setting a value in a Series that was
107
+ extracted from a column of a DataFrame, that DataFrame will also be updated:
108
+
109
+ ser = df["col"]
110
+ ser[0] = 0 <--- in pandas 2, this also updates `df`
111
+
112
+ In pandas 3.0 (with Copy-on-Write), updating one Series/DataFrame will never
113
+ modify another, and thus in the example above, `df` will not be changed.
114
+ """
115
+
116
+
100
117
class BaseBlockManager (DataManager ):
101
118
"""
102
119
Core internal data structure to implement DataFrame, Series, etc.
@@ -1988,7 +2005,7 @@ def get_numeric_data(self, copy: bool = False) -> Self:
1988
2005
def _can_hold_na (self ) -> bool :
1989
2006
return self ._block ._can_hold_na
1990
2007
1991
- def setitem_inplace (self , indexer , value ) -> None :
2008
+ def setitem_inplace (self , indexer , value , warn : bool = True ) -> None :
1992
2009
"""
1993
2010
Set values with indexer.
1994
2011
@@ -1998,9 +2015,18 @@ def setitem_inplace(self, indexer, value) -> None:
1998
2015
in place, not returning a new Manager (and Block), and thus never changing
1999
2016
the dtype.
2000
2017
"""
2001
- if using_copy_on_write () and not self ._has_no_reference (0 ):
2002
- self .blocks = (self ._block .copy (),)
2003
- self ._cache .clear ()
2018
+ using_cow = using_copy_on_write ()
2019
+ warn_cow = warn_copy_on_write ()
2020
+ if (using_cow or warn_cow ) and not self ._has_no_reference (0 ):
2021
+ if using_cow :
2022
+ self .blocks = (self ._block .copy (),)
2023
+ self ._cache .clear ()
2024
+ elif warn and warn_cow :
2025
+ warnings .warn (
2026
+ COW_WARNING_SETITEM_MSG ,
2027
+ FutureWarning ,
2028
+ stacklevel = find_stack_level (),
2029
+ )
2004
2030
2005
2031
super ().setitem_inplace (indexer , value )
2006
2032
0 commit comments