Skip to content

Commit 3cd66a2

Browse files
committed
Revert changes to cython code base
1 parent abe7603 commit 3cd66a2

File tree

3 files changed

+45
-65
lines changed

3 files changed

+45
-65
lines changed

pandas/_libs/properties.pyx

+2-19
Original file line numberDiff line numberDiff line change
@@ -23,29 +23,12 @@ cdef class CachedProperty:
2323
return self
2424

2525
# Get the cache or set a default one if needed
26-
cache = instance_cache = getattr(obj, '_cache', None)
27-
26+
cache = getattr(obj, '_cache', None)
2827
if cache is None:
2928
try:
3029
cache = obj._cache = {}
3130
except (AttributeError):
32-
raise TypeError(
33-
f"Cython extension type {type(obj)} must declare attribute "
34-
"`_cache` to use @cache_readonly."
35-
)
36-
37-
if instance_cache is not None:
38-
# When accessing cython extension types, the attribute is already
39-
# registered and known to the class, unlike for python object. To
40-
# ensure we're not accidentally using a global scope / class level
41-
# cache we'll need to check whether the instance and class
42-
# attribute is identical
43-
cache_class = getattr(typ, "_cache", None)
44-
if cache_class is not None and cache_class is instance_cache:
45-
raise TypeError(
46-
f"Class {typ} defines a `_cache` attribute on class level "
47-
"which is forbidden in combination with @cache_readonly."
48-
)
31+
return self
4932

5033
if PyDict_Contains(cache, self.name):
5134
# not necessary to Py_INCREF

pandas/_libs/tslibs/offsets.pyx

+43
Original file line numberDiff line numberDiff line change
@@ -895,6 +895,13 @@ cdef class Tick(SingleConstructorOffset):
895895

896896
raise ApplyTypeError(f"Unhandled type: {type(other).__name__}")
897897

898+
# --------------------------------------------------------------------
899+
# Pickle Methods
900+
901+
def __setstate__(self, state):
902+
self.n = state["n"]
903+
self.normalize = False
904+
898905

899906
cdef class Day(Tick):
900907
_nanos_inc = 24 * 3600 * 1_000_000_000
@@ -1998,6 +2005,11 @@ cdef class QuarterOffset(SingleConstructorOffset):
19982005
startingMonth = self._default_starting_month
19992006
self.startingMonth = startingMonth
20002007

2008+
cpdef __setstate__(self, state):
2009+
self.startingMonth = state.pop("startingMonth")
2010+
self.n = state.pop("n")
2011+
self.normalize = state.pop("normalize")
2012+
20012013
@classmethod
20022014
def _from_name(cls, suffix=None):
20032015
kwargs = {}
@@ -2253,6 +2265,11 @@ cdef class SemiMonthOffset(SingleConstructorOffset):
22532265
f"got {self.day_of_month}"
22542266
)
22552267

2268+
cpdef __setstate__(self, state):
2269+
self.n = state.pop("n")
2270+
self.normalize = state.pop("normalize")
2271+
self.day_of_month = state.pop("day_of_month")
2272+
22562273
@classmethod
22572274
def _from_name(cls, suffix=None):
22582275
return cls(day_of_month=suffix)
@@ -2570,6 +2587,12 @@ cdef class WeekOfMonth(WeekOfMonthMixin):
25702587
if self.week < 0 or self.week > 3:
25712588
raise ValueError(f"Week must be 0<=week<=3, got {self.week}")
25722589

2590+
cpdef __setstate__(self, state):
2591+
self.n = state.pop("n")
2592+
self.normalize = state.pop("normalize")
2593+
self.weekday = state.pop("weekday")
2594+
self.week = state.pop("week")
2595+
25732596
def _get_offset_day(self, other: datetime) -> int:
25742597
"""
25752598
Find the day in the same month as other that has the same
@@ -2629,6 +2652,12 @@ cdef class LastWeekOfMonth(WeekOfMonthMixin):
26292652
if self.n == 0:
26302653
raise ValueError("N cannot be 0")
26312654

2655+
cpdef __setstate__(self, state):
2656+
self.n = state.pop("n")
2657+
self.normalize = state.pop("normalize")
2658+
self.weekday = state.pop("weekday")
2659+
self.week = -1
2660+
26322661
def _get_offset_day(self, other: datetime) -> int:
26332662
"""
26342663
Find the day in the same month as other that has the same
@@ -2680,6 +2709,12 @@ cdef class FY5253Mixin(SingleConstructorOffset):
26802709
if self.variation not in ["nearest", "last"]:
26812710
raise ValueError(f"{self.variation} is not a valid variation")
26822711

2712+
cpdef __setstate__(self, state):
2713+
self.n = state.pop("n")
2714+
self.normalize = state.pop("normalize")
2715+
self.weekday = state.pop("weekday")
2716+
self.variation = state.pop("variation")
2717+
26832718
def is_anchored(self) -> bool:
26842719
return (
26852720
self.n == 1 and self.startingMonth is not None and self.weekday is not None
@@ -2960,6 +2995,10 @@ cdef class FY5253Quarter(FY5253Mixin):
29602995
)
29612996
self.qtr_with_extra_week = qtr_with_extra_week
29622997

2998+
cpdef __setstate__(self, state):
2999+
FY5253Mixin.__setstate__(self, state)
3000+
self.qtr_with_extra_week = state.pop("qtr_with_extra_week")
3001+
29633002
@cache_readonly
29643003
def _offset(self):
29653004
return FY5253(
@@ -3102,6 +3141,10 @@ cdef class Easter(SingleConstructorOffset):
31023141
Right now uses the revised method which is valid in years 1583-4099.
31033142
"""
31043143

3144+
cpdef __setstate__(self, state):
3145+
self.n = state.pop("n")
3146+
self.normalize = state.pop("normalize")
3147+
31053148
@apply_wraps
31063149
def apply(self, other: datetime) -> datetime:
31073150
current_easter = easter(other.year)

pandas/tests/libs/test_lib.py

-46
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
from pandas._libs import (
55
Timestamp,
66
lib,
7-
properties,
87
writers as libwriters,
98
)
109

@@ -213,48 +212,3 @@ def test_no_default_pickle():
213212
# GH#40397
214213
obj = tm.round_trip_pickle(lib.no_default)
215214
assert obj is lib.no_default
216-
217-
218-
def test_cache_readonly_no_global_cache():
219-
"""
220-
Ensure that the definition of a global attribute `_cache` does
221-
not interfere with the property cache
222-
"""
223-
224-
from typing import Dict
225-
226-
class MyDtypeGlobalAttr:
227-
_cache: Dict = {}
228-
229-
def __init__(self, value):
230-
self._value = value
231-
232-
@properties.cache_readonly
233-
def cached_attr(self):
234-
return self._value
235-
236-
a = MyDtypeGlobalAttr("A")
237-
with pytest.raises(TypeError, match=r"defines a `_cache` attribute"):
238-
a.cached_attr
239-
240-
class MyDtypeInstanceAttr:
241-
def __init__(self, value):
242-
self._value = value
243-
self._cache = {}
244-
245-
@properties.cache_readonly
246-
def cached_attr(self):
247-
return self._value
248-
249-
a = MyDtypeInstanceAttr("A")
250-
b = MyDtypeInstanceAttr("B")
251-
b._cache = {}
252-
253-
# Assert our assumption that the property cache
254-
# actually uses an attribute called _cache
255-
assert len(a._cache) == 0
256-
257-
assert a.cached_attr == "A"
258-
assert b.cached_attr == "B"
259-
260-
assert len(a._cache) == 1

0 commit comments

Comments
 (0)