Skip to content

Commit c557ab5

Browse files
authored
PERF: make _Tick into a cdef class (pandas-dev#33979)
1 parent e1ee2b0 commit c557ab5

File tree

4 files changed

+30
-6
lines changed

4 files changed

+30
-6
lines changed

pandas/_libs/tslibs/offsets.pxd

+2
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
cdef to_offset(object obj)
2+
cdef bint is_offset_object(object obj)
3+
cdef bint is_tick_object(object obj)

pandas/_libs/tslibs/offsets.pyx

+19-5
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,14 @@ for _d in DAYS:
8686
# ---------------------------------------------------------------------
8787
# Misc Helpers
8888

89+
cdef bint is_offset_object(object obj):
90+
return isinstance(obj, _BaseOffset)
91+
92+
93+
cdef bint is_tick_object(object obj):
94+
return isinstance(obj, _Tick)
95+
96+
8997
cdef to_offset(object obj):
9098
"""
9199
Wrap pandas.tseries.frequencies.to_offset to keep centralize runtime
@@ -608,7 +616,7 @@ class BaseOffset(_BaseOffset):
608616
return -self + other
609617

610618

611-
class _Tick:
619+
cdef class _Tick:
612620
"""
613621
dummy class to mix into tseries.offsets.Tick so that in tslibs.period we
614622
can do isinstance checks on _Tick and avoid importing tseries.offsets
@@ -618,12 +626,18 @@ class _Tick:
618626
__array_priority__ = 1000
619627

620628
def __truediv__(self, other):
621-
result = self.delta.__truediv__(other)
629+
if not isinstance(self, _Tick):
630+
# cython semantics mean the args are sometimes swapped
631+
result = other.delta.__rtruediv__(self)
632+
else:
633+
result = self.delta.__truediv__(other)
622634
return _wrap_timedelta_result(result)
623635

624-
def __rtruediv__(self, other):
625-
result = self.delta.__rtruediv__(other)
626-
return _wrap_timedelta_result(result)
636+
def __reduce__(self):
637+
return (type(self), (self.n,))
638+
639+
def __setstate__(self, state):
640+
object.__setattr__(self, "n", state["n"])
627641

628642

629643
class BusinessMixin:

pandas/compat/pickle_compat.py

+7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
from pandas import Index
1111

12+
from pandas.tseries.offsets import Tick
13+
1214
if TYPE_CHECKING:
1315
from pandas import Series, DataFrame
1416

@@ -38,6 +40,11 @@ def load_reduce(self):
3840
return
3941
except TypeError:
4042
pass
43+
elif args and issubclass(args[0], Tick):
44+
# TypeError: object.__new__(Day) is not safe, use Day.__new__()
45+
cls = args[0]
46+
stack[-1] = cls.__new__(*args)
47+
return
4148

4249
raise
4350

pandas/io/pickle.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,8 @@ def read_pickle(
173173
# 3) try pickle_compat with latin-1 encoding upon a UnicodeDecodeError
174174

175175
try:
176-
excs_to_catch = (AttributeError, ImportError, ModuleNotFoundError)
176+
excs_to_catch = (AttributeError, ImportError, ModuleNotFoundError, TypeError)
177+
# TypeError for Cython complaints about object.__new__ vs Tick.__new__
177178
try:
178179
with warnings.catch_warnings(record=True):
179180
# We want to silence any warnings about, e.g. moved modules.

0 commit comments

Comments
 (0)