Skip to content

Commit 32b14c7

Browse files
Revert "Move chained assignment detection to cython for Python 3.14 compat (pandas-dev#62070)"
This reverts commit a505423.
1 parent fcffde9 commit 32b14c7

23 files changed

+75
-138
lines changed

pandas/_libs/internals.pyi

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,3 @@ class BlockValuesRefs:
9494
def add_reference(self, blk: Block) -> None: ...
9595
def add_index_reference(self, index: Index) -> None: ...
9696
def has_reference(self) -> bool: ...
97-
98-
class SetitemMixin:
99-
def __setitem__(self, key, value) -> None: ...
100-
def __delitem__(self, key) -> None: ...

pandas/_libs/internals.pyx

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
from collections import defaultdict
2-
import sys
3-
import warnings
42

53
cimport cython
6-
from cpython cimport PY_VERSION_HEX
74
from cpython.object cimport PyObject
85
from cpython.pyport cimport PY_SSIZE_T_MAX
96
from cpython.slice cimport PySlice_GetIndicesEx
@@ -23,9 +20,6 @@ from numpy cimport (
2320
cnp.import_array()
2421

2522
from pandas._libs.algos import ensure_int64
26-
from pandas.compat import CHAINED_WARNING_DISABLED
27-
from pandas.errors import ChainedAssignmentError
28-
from pandas.errors.cow import _chained_assignment_msg
2923

3024
from pandas._libs.util cimport (
3125
is_array,
@@ -1002,47 +996,3 @@ cdef class BlockValuesRefs:
1002996
return self._has_reference_maybe_locked()
1003997
ELSE:
1004998
return self._has_reference_maybe_locked()
1005-
1006-
1007-
cdef extern from "Python.h":
1008-
"""
1009-
// python version < 3.14
1010-
#if PY_VERSION_HEX < 0x030E0000
1011-
// This function is unused and is declared to avoid a build warning
1012-
int __Pyx_PyUnstable_Object_IsUniqueReferencedTemporary(PyObject *ref) {
1013-
return Py_REFCNT(ref) == 1;
1014-
}
1015-
#else
1016-
#define __Pyx_PyUnstable_Object_IsUniqueReferencedTemporary \
1017-
PyUnstable_Object_IsUniqueReferencedTemporary
1018-
#endif
1019-
"""
1020-
int PyUnstable_Object_IsUniqueReferencedTemporary\
1021-
"__Pyx_PyUnstable_Object_IsUniqueReferencedTemporary"(object o) except -1
1022-
1023-
1024-
# Python version compatibility for PyUnstable_Object_IsUniqueReferencedTemporary
1025-
cdef inline bint _is_unique_referenced_temporary(object obj) except -1:
1026-
if PY_VERSION_HEX >= 0x030E0000:
1027-
# Python 3.14+ has PyUnstable_Object_IsUniqueReferencedTemporary
1028-
return PyUnstable_Object_IsUniqueReferencedTemporary(obj)
1029-
else:
1030-
# Fallback for older Python versions using sys.getrefcount
1031-
return sys.getrefcount(obj) <= 1
1032-
1033-
1034-
cdef class SetitemMixin:
1035-
# class used in DataFrame and Series for checking for chained assignment
1036-
1037-
def __setitem__(self, key, value) -> None:
1038-
cdef bint is_unique = 0
1039-
if not CHAINED_WARNING_DISABLED:
1040-
is_unique = _is_unique_referenced_temporary(self)
1041-
if is_unique:
1042-
warnings.warn(
1043-
_chained_assignment_msg, ChainedAssignmentError, stacklevel=1
1044-
)
1045-
self._setitem(key, value)
1046-
1047-
def __delitem__(self, key) -> None:
1048-
self._delitem(key)

pandas/_testing/contexts.py

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
import uuid
1414

1515
from pandas.compat import (
16-
CHAINED_WARNING_DISABLED,
17-
CHAINED_WARNING_DISABLED_INPLACE_METHOD,
16+
PYPY,
17+
WARNING_CHECK_DISABLED,
1818
)
1919
from pandas.errors import ChainedAssignmentError
2020

@@ -163,18 +163,10 @@ def with_csv_dialect(name: str, **kwargs) -> Generator[None]:
163163
csv.unregister_dialect(name)
164164

165165

166-
def raises_chained_assignment_error(
167-
extra_warnings=(), extra_match=(), inplace_method=False
168-
):
166+
def raises_chained_assignment_error(extra_warnings=(), extra_match=()):
169167
from pandas._testing import assert_produces_warning
170168

171-
WARNING_DISABLED = (
172-
CHAINED_WARNING_DISABLED_INPLACE_METHOD
173-
if inplace_method
174-
else CHAINED_WARNING_DISABLED
175-
)
176-
177-
if WARNING_DISABLED:
169+
if PYPY or WARNING_CHECK_DISABLED:
178170
if not extra_warnings:
179171
from contextlib import nullcontext
180172

pandas/compat/__init__.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,12 @@
1616
from typing import TYPE_CHECKING
1717

1818
from pandas.compat._constants import (
19-
CHAINED_WARNING_DISABLED,
20-
CHAINED_WARNING_DISABLED_INPLACE_METHOD,
2119
IS64,
2220
ISMUSL,
2321
PY312,
2422
PY314,
2523
PYPY,
24+
WARNING_CHECK_DISABLED,
2625
WASM,
2726
)
2827
from pandas.compat.numpy import is_numpy_dev
@@ -153,15 +152,14 @@ def is_ci_environment() -> bool:
153152

154153

155154
__all__ = [
156-
"CHAINED_WARNING_DISABLED",
157-
"CHAINED_WARNING_DISABLED_INPLACE_METHOD",
158155
"HAS_PYARROW",
159156
"IS64",
160157
"ISMUSL",
161158
"PY312",
162159
"PY314",
163160
"PYARROW_MIN_VERSION",
164161
"PYPY",
162+
"WARNING_CHECK_DISABLED",
165163
"WASM",
166164
"is_numpy_dev",
167165
"pa_version_under14p0",

pandas/compat/_constants.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@
1919
WASM = (sys.platform == "emscripten") or (platform.machine() in ["wasm32", "wasm64"])
2020
ISMUSL = "musl" in (sysconfig.get_config_var("HOST_GNU_TYPE") or "")
2121
REF_COUNT = 2
22-
CHAINED_WARNING_DISABLED = PYPY or (PY314 and not sys._is_gil_enabled()) # type: ignore[attr-defined]
23-
CHAINED_WARNING_DISABLED_INPLACE_METHOD = PYPY or PY314
22+
WARNING_CHECK_DISABLED = PY314
2423

2524

2625
__all__ = [

pandas/compat/pickle_compat.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
PeriodArray,
2323
TimedeltaArray,
2424
)
25-
from pandas.core.generic import NDFrame
2625
from pandas.core.internals import BlockManager
2726

2827
if TYPE_CHECKING:
@@ -91,10 +90,6 @@ def load_reduce(self) -> None:
9190
cls = args[0]
9291
stack[-1] = NDArrayBacked.__new__(*args)
9392
return
94-
elif args and issubclass(args[0], NDFrame):
95-
cls = args[0]
96-
stack[-1] = cls.__new__(cls)
97-
return
9893
raise
9994

10095
dispatch[pickle.REDUCE[0]] = load_reduce # type: ignore[assignment]

pandas/core/frame.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,11 @@
4848
properties,
4949
)
5050
from pandas._libs.hashtable import duplicated
51-
from pandas._libs.internals import SetitemMixin
5251
from pandas._libs.lib import is_range_indexer
52+
from pandas.compat import PYPY
5353
from pandas.compat._constants import (
54-
CHAINED_WARNING_DISABLED_INPLACE_METHOD,
5554
REF_COUNT,
55+
WARNING_CHECK_DISABLED,
5656
)
5757
from pandas.compat._optional import import_optional_dependency
5858
from pandas.compat.numpy import function as nv
@@ -63,6 +63,7 @@
6363
)
6464
from pandas.errors.cow import (
6565
_chained_assignment_method_msg,
66+
_chained_assignment_msg,
6667
)
6768
from pandas.util._decorators import (
6869
Appender,
@@ -520,7 +521,7 @@
520521

521522

522523
@set_module("pandas")
523-
class DataFrame(SetitemMixin, NDFrame, OpsMixin):
524+
class DataFrame(NDFrame, OpsMixin):
524525
"""
525526
Two-dimensional, size-mutable, potentially heterogeneous tabular data.
526527
@@ -667,11 +668,6 @@ class DataFrame(SetitemMixin, NDFrame, OpsMixin):
667668
# and ExtensionArray. Should NOT be overridden by subclasses.
668669
__pandas_priority__ = 4000
669670

670-
# override those to avoid inheriting from SetitemMixin (cython generates
671-
# them by default)
672-
__reduce__ = object.__reduce__
673-
__setstate__ = NDFrame.__setstate__
674-
675671
@property
676672
def _constructor(self) -> type[DataFrame]:
677673
return DataFrame
@@ -4325,8 +4321,7 @@ def isetitem(self, loc, value) -> None:
43254321
arraylike, refs = self._sanitize_column(value)
43264322
self._iset_item_mgr(loc, arraylike, inplace=False, refs=refs)
43274323

4328-
# def __setitem__() is implemented in SetitemMixin and dispatches to this method
4329-
def _setitem(self, key, value) -> None:
4324+
def __setitem__(self, key, value) -> None:
43304325
"""
43314326
Set item(s) in DataFrame by key.
43324327
@@ -4410,6 +4405,12 @@ def _setitem(self, key, value) -> None:
44104405
z 3 50
44114406
# Values for 'a' and 'b' are completely ignored!
44124407
"""
4408+
if not PYPY and not WARNING_CHECK_DISABLED:
4409+
if sys.getrefcount(self) <= REF_COUNT + 1:
4410+
warnings.warn(
4411+
_chained_assignment_msg, ChainedAssignmentError, stacklevel=2
4412+
)
4413+
44134414
key = com.apply_if_callable(key, self)
44144415

44154416
# see if we can slice the rows
@@ -9362,7 +9363,7 @@ def update(
93629363
1 2 500.0
93639364
2 3 6.0
93649365
"""
9365-
if not CHAINED_WARNING_DISABLED_INPLACE_METHOD:
9366+
if not PYPY and not WARNING_CHECK_DISABLED:
93669367
if sys.getrefcount(self) <= REF_COUNT:
93679368
warnings.warn(
93689369
_chained_assignment_method_msg,

pandas/core/generic.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,10 @@
8282
WriteExcelBuffer,
8383
npt,
8484
)
85+
from pandas.compat import PYPY
8586
from pandas.compat._constants import (
86-
CHAINED_WARNING_DISABLED_INPLACE_METHOD,
8787
REF_COUNT,
88+
WARNING_CHECK_DISABLED,
8889
)
8990
from pandas.compat._optional import import_optional_dependency
9091
from pandas.compat.numpy import function as nv
@@ -2074,6 +2075,7 @@ def __getstate__(self) -> dict[str, Any]:
20742075
**meta,
20752076
}
20762077

2078+
@final
20772079
def __setstate__(self, state) -> None:
20782080
if isinstance(state, BlockManager):
20792081
self._mgr = state
@@ -4264,9 +4266,8 @@ def _slice(self, slobj: slice, axis: AxisInt = 0) -> Self:
42644266
result = result.__finalize__(self)
42654267
return result
42664268

4267-
# def __delitem__() is implemented in SetitemMixin and dispatches to this method
42684269
@final
4269-
def _delitem(self, key) -> None:
4270+
def __delitem__(self, key) -> None:
42704271
"""
42714272
Delete item
42724273
"""
@@ -7081,7 +7082,7 @@ def fillna(
70817082
"""
70827083
inplace = validate_bool_kwarg(inplace, "inplace")
70837084
if inplace:
7084-
if not CHAINED_WARNING_DISABLED_INPLACE_METHOD:
7085+
if not PYPY and not WARNING_CHECK_DISABLED:
70857086
if sys.getrefcount(self) <= REF_COUNT:
70867087
warnings.warn(
70877088
_chained_assignment_method_msg,
@@ -7328,7 +7329,7 @@ def ffill(
73287329
"""
73297330
inplace = validate_bool_kwarg(inplace, "inplace")
73307331
if inplace:
7331-
if not CHAINED_WARNING_DISABLED_INPLACE_METHOD:
7332+
if not PYPY and not WARNING_CHECK_DISABLED:
73327333
if sys.getrefcount(self) <= REF_COUNT:
73337334
warnings.warn(
73347335
_chained_assignment_method_msg,
@@ -7468,7 +7469,7 @@ def bfill(
74687469
"""
74697470
inplace = validate_bool_kwarg(inplace, "inplace")
74707471
if inplace:
7471-
if not CHAINED_WARNING_DISABLED_INPLACE_METHOD:
7472+
if not PYPY and not WARNING_CHECK_DISABLED:
74727473
if sys.getrefcount(self) <= REF_COUNT:
74737474
warnings.warn(
74747475
_chained_assignment_method_msg,
@@ -7553,7 +7554,7 @@ def replace(
75537554

75547555
inplace = validate_bool_kwarg(inplace, "inplace")
75557556
if inplace:
7556-
if not CHAINED_WARNING_DISABLED_INPLACE_METHOD:
7557+
if not PYPY and not WARNING_CHECK_DISABLED:
75577558
if sys.getrefcount(self) <= REF_COUNT:
75587559
warnings.warn(
75597560
_chained_assignment_method_msg,
@@ -7916,7 +7917,7 @@ def interpolate(
79167917
inplace = validate_bool_kwarg(inplace, "inplace")
79177918

79187919
if inplace:
7919-
if not CHAINED_WARNING_DISABLED_INPLACE_METHOD:
7920+
if not PYPY and not WARNING_CHECK_DISABLED:
79207921
if sys.getrefcount(self) <= REF_COUNT:
79217922
warnings.warn(
79227923
_chained_assignment_method_msg,
@@ -8571,7 +8572,7 @@ def clip(
85718572
inplace = validate_bool_kwarg(inplace, "inplace")
85728573

85738574
if inplace:
8574-
if not CHAINED_WARNING_DISABLED_INPLACE_METHOD:
8575+
if not PYPY and not WARNING_CHECK_DISABLED:
85758576
if sys.getrefcount(self) <= REF_COUNT:
85768577
warnings.warn(
85778578
_chained_assignment_method_msg,
@@ -10206,7 +10207,7 @@ def where(
1020610207
"""
1020710208
inplace = validate_bool_kwarg(inplace, "inplace")
1020810209
if inplace:
10209-
if not CHAINED_WARNING_DISABLED_INPLACE_METHOD:
10210+
if not PYPY and not WARNING_CHECK_DISABLED:
1021010211
if sys.getrefcount(self) <= REF_COUNT:
1021110212
warnings.warn(
1021210213
_chained_assignment_method_msg,
@@ -10270,7 +10271,7 @@ def mask(
1027010271
) -> Self | None:
1027110272
inplace = validate_bool_kwarg(inplace, "inplace")
1027210273
if inplace:
10273-
if not CHAINED_WARNING_DISABLED_INPLACE_METHOD:
10274+
if not PYPY and not WARNING_CHECK_DISABLED:
1027410275
if sys.getrefcount(self) <= REF_COUNT:
1027510276
warnings.warn(
1027610277
_chained_assignment_method_msg,

pandas/core/indexing.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@
1515

1616
from pandas._libs.indexing import NDFrameIndexerBase
1717
from pandas._libs.lib import item_from_zerodim
18+
from pandas.compat import PYPY
1819
from pandas.compat._constants import (
19-
CHAINED_WARNING_DISABLED,
2020
REF_COUNT,
21+
WARNING_CHECK_DISABLED,
2122
)
2223
from pandas.errors import (
2324
AbstractMethodError,
@@ -919,7 +920,7 @@ def _ensure_listlike_indexer(self, key, axis=None, value=None) -> None:
919920

920921
@final
921922
def __setitem__(self, key, value) -> None:
922-
if not CHAINED_WARNING_DISABLED:
923+
if not PYPY and not WARNING_CHECK_DISABLED:
923924
if sys.getrefcount(self.obj) <= REF_COUNT:
924925
warnings.warn(
925926
_chained_assignment_msg, ChainedAssignmentError, stacklevel=2
@@ -2587,7 +2588,7 @@ def __getitem__(self, key):
25872588
return super().__getitem__(key)
25882589

25892590
def __setitem__(self, key, value) -> None:
2590-
if not CHAINED_WARNING_DISABLED:
2591+
if not PYPY and not WARNING_CHECK_DISABLED:
25912592
if sys.getrefcount(self.obj) <= REF_COUNT:
25922593
warnings.warn(
25932594
_chained_assignment_msg, ChainedAssignmentError, stacklevel=2
@@ -2618,7 +2619,7 @@ def _convert_key(self, key):
26182619
return key
26192620

26202621
def __setitem__(self, key, value) -> None:
2621-
if not CHAINED_WARNING_DISABLED:
2622+
if not PYPY and not WARNING_CHECK_DISABLED:
26222623
if sys.getrefcount(self.obj) <= REF_COUNT:
26232624
warnings.warn(
26242625
_chained_assignment_msg, ChainedAssignmentError, stacklevel=2

0 commit comments

Comments
 (0)