Skip to content

PERF: make _Tick into a cdef class #33979

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions pandas/_libs/tslibs/offsets.pxd
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
cdef to_offset(object obj)
cdef bint is_offset_object(object obj)
cdef bint is_tick_object(object obj)
24 changes: 19 additions & 5 deletions pandas/_libs/tslibs/offsets.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,14 @@ for _d in DAYS:
# ---------------------------------------------------------------------
# Misc Helpers

cdef bint is_offset_object(object obj):
return isinstance(obj, _BaseOffset)


cdef bint is_tick_object(object obj):
return isinstance(obj, _Tick)


cdef to_offset(object obj):
"""
Wrap pandas.tseries.frequencies.to_offset to keep centralize runtime
Expand Down Expand Up @@ -608,7 +616,7 @@ class BaseOffset(_BaseOffset):
return -self + other


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

def __truediv__(self, other):
result = self.delta.__truediv__(other)
if not isinstance(self, _Tick):
# cython semantics mean the args are sometimes swapped
result = other.delta.__rtruediv__(self)
else:
result = self.delta.__truediv__(other)
return _wrap_timedelta_result(result)

def __rtruediv__(self, other):
result = self.delta.__rtruediv__(other)
return _wrap_timedelta_result(result)
def __reduce__(self):
return (type(self), (self.n,))

def __setstate__(self, state):
object.__setattr__(self, "n", state["n"])


class BusinessMixin:
Expand Down
7 changes: 7 additions & 0 deletions pandas/compat/pickle_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

from pandas import Index

from pandas.tseries.offsets import Tick

if TYPE_CHECKING:
from pandas import Series, DataFrame

Expand Down Expand Up @@ -38,6 +40,11 @@ def load_reduce(self):
return
except TypeError:
pass
elif args and issubclass(args[0], Tick):
# TypeError: object.__new__(Day) is not safe, use Day.__new__()
cls = args[0]
stack[-1] = cls.__new__(*args)
return

raise

Expand Down
3 changes: 2 additions & 1 deletion pandas/io/pickle.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,8 @@ def read_pickle(
# 3) try pickle_compat with latin-1 encoding upon a UnicodeDecodeError

try:
excs_to_catch = (AttributeError, ImportError, ModuleNotFoundError)
excs_to_catch = (AttributeError, ImportError, ModuleNotFoundError, TypeError)
# TypeError for Cython complaints about object.__new__ vs Tick.__new__
try:
with warnings.catch_warnings(record=True):
# We want to silence any warnings about, e.g. moved modules.
Expand Down