Skip to content

REF: make SingleConstructorOffset a cdef class #34323

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 22, 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
42 changes: 21 additions & 21 deletions pandas/_libs/tslibs/offsets.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ cimport numpy as cnp
from numpy cimport int64_t
cnp.import_array()

# TODO: formalize having _libs.properties "above" tslibs in the dependency structure
from pandas._libs.properties import cache_readonly

from pandas._libs.tslibs cimport util
from pandas._libs.tslibs.util cimport is_integer_object, is_datetime64_object
Expand Down Expand Up @@ -447,7 +449,7 @@ cdef class BaseOffset:
def __hash__(self):
return hash(self._params)

@property
@cache_readonly
def _params(self):
"""
Returns a tuple containing all of the attributes needed to evaluate
Expand Down Expand Up @@ -583,7 +585,7 @@ cdef class BaseOffset:
def rule_code(self) -> str:
return self._prefix

@property
@cache_readonly
def freqstr(self) -> str:
try:
code = self.rule_code
Expand Down Expand Up @@ -778,7 +780,19 @@ cdef class BaseOffset:
return self.n == 1


cdef class Tick(BaseOffset):
cdef class SingleConstructorOffset(BaseOffset):
@classmethod
def _from_name(cls, suffix=None):
# default _from_name calls cls with no args
if suffix:
raise ValueError(f"Bad freq suffix {suffix}")
return cls()


# ---------------------------------------------------------------------
# Tick Offsets

cdef class Tick(SingleConstructorOffset):
# ensure that reversed-ops with numpy scalars return NotImplemented
__array_priority__ = 1000
_adjust_dst = False
Expand All @@ -796,13 +810,6 @@ cdef class Tick(BaseOffset):
"Tick offset with `normalize=True` are not allowed."
)

@classmethod
def _from_name(cls, suffix=None):
# default _from_name calls cls with no args
if suffix:
raise ValueError(f"Bad freq suffix {suffix}")
return cls()

def _repr_attrs(self) -> str:
# Since cdef classes have no __dict__, we need to override
return ""
Expand Down Expand Up @@ -981,7 +988,7 @@ def delta_to_tick(delta: timedelta) -> Tick:
# --------------------------------------------------------------------


class BusinessMixin(BaseOffset):
class BusinessMixin(SingleConstructorOffset):
"""
Mixin to business types to provide related functions.
"""
Expand Down Expand Up @@ -1060,13 +1067,6 @@ class BusinessHourMixin(BusinessMixin):
object.__setattr__(self, "start", start)
object.__setattr__(self, "end", end)

@classmethod
def _from_name(cls, suffix=None):
# default _from_name calls cls with no args
if suffix:
raise ValueError(f"Bad freq suffix {suffix}")
return cls()

def _repr_attrs(self) -> str:
out = super()._repr_attrs()
hours = ",".join(
Expand Down Expand Up @@ -1128,7 +1128,7 @@ class CustomMixin:
object.__setattr__(self, "calendar", calendar)


class WeekOfMonthMixin(BaseOffset):
class WeekOfMonthMixin(SingleConstructorOffset):
"""
Mixin for methods common to WeekOfMonth and LastWeekOfMonth.
"""
Expand Down Expand Up @@ -1169,7 +1169,7 @@ class WeekOfMonthMixin(BaseOffset):

# ----------------------------------------------------------------------

cdef class YearOffset(BaseOffset):
cdef class YearOffset(SingleConstructorOffset):
"""
DateOffset that just needs a month.
"""
Expand Down Expand Up @@ -1230,7 +1230,7 @@ cdef class YearOffset(BaseOffset):
return type(dtindex)._simple_new(shifted, dtype=dtindex.dtype)


cdef class QuarterOffset(BaseOffset):
cdef class QuarterOffset(SingleConstructorOffset):
_attributes = frozenset(["n", "normalize", "startingMonth"])
# TODO: Consider combining QuarterOffset and YearOffset __init__ at some
# point. Also apply_index, is_on_offset, rule_code if
Expand Down
46 changes: 8 additions & 38 deletions pandas/tseries/offsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
Minute,
Nano,
Second,
SingleConstructorOffset,
Tick,
apply_index_wraps,
apply_wraps,
Expand Down Expand Up @@ -298,37 +299,6 @@ def is_on_offset(self, dt):
# TODO, see #1395
return True

@cache_readonly
def _params(self):
# TODO: see if we can just write cache_readonly(BaseOffset._params.__get__)
return BaseOffset._params.__get__(self)

@cache_readonly
def freqstr(self):
# TODO: see if we can just write cache_readonly(BaseOffset.freqstr.__get__)
return BaseOffset.freqstr.__get__(self)


class SingleConstructorMixin:
@cache_readonly
def _params(self):
# TODO: see if we can just write cache_readonly(BaseOffset._params.__get__)
return BaseOffset._params.__get__(self)

@cache_readonly
def freqstr(self):
# TODO: see if we can just write cache_readonly(BaseOffset.freqstr.__get__)
return BaseOffset.freqstr.__get__(self)


class SingleConstructorOffset(SingleConstructorMixin, BaseOffset):
@classmethod
def _from_name(cls, suffix=None):
# default _from_name calls cls with no args
if suffix:
raise ValueError(f"Bad freq suffix {suffix}")
return cls()


class BusinessDay(BusinessMixin, SingleConstructorOffset):
"""
Expand Down Expand Up @@ -441,7 +411,7 @@ def is_on_offset(self, dt: datetime) -> bool:
return dt.weekday() < 5


class BusinessHour(SingleConstructorMixin, liboffsets.BusinessHourMixin):
class BusinessHour(liboffsets.BusinessHourMixin):
"""
DateOffset subclass representing possibly n business hours.
"""
Expand Down Expand Up @@ -1320,7 +1290,7 @@ def _from_name(cls, suffix=None):
return cls(weekday=weekday)


class WeekOfMonth(SingleConstructorMixin, liboffsets.WeekOfMonthMixin):
class WeekOfMonth(liboffsets.WeekOfMonthMixin):
"""
Describes monthly dates like "the Tuesday of the 2nd week of each month".

Expand Down Expand Up @@ -1381,7 +1351,7 @@ def _from_name(cls, suffix=None):
return cls(week=week, weekday=weekday)


class LastWeekOfMonth(SingleConstructorMixin, liboffsets.WeekOfMonthMixin):
class LastWeekOfMonth(liboffsets.WeekOfMonthMixin):
"""
Describes monthly dates in last week of month like "the last Tuesday of
each month".
Expand Down Expand Up @@ -1443,7 +1413,7 @@ def _from_name(cls, suffix=None):
# Quarter-Based Offset Classes


class QuarterOffset(SingleConstructorMixin, liboffsets.QuarterOffset):
class QuarterOffset(liboffsets.QuarterOffset):
"""
Quarter representation.
"""
Expand Down Expand Up @@ -1552,7 +1522,7 @@ class YearBegin(liboffsets.YearOffset):
# Special Offset Classes


class FY5253Mixin(BaseOffset):
class FY5253Mixin(SingleConstructorOffset):
def __init__(
self, n=1, normalize=False, weekday=0, startingMonth=1, variation="nearest"
):
Expand Down Expand Up @@ -1595,7 +1565,7 @@ def get_rule_code_suffix(self) -> str:
return f"{prefix}-{month}-{weekday}"


class FY5253(SingleConstructorMixin, FY5253Mixin):
class FY5253(FY5253Mixin):
"""
Describes 52-53 week fiscal year. This is also known as a 4-4-5 calendar.

Expand Down Expand Up @@ -1763,7 +1733,7 @@ def _from_name(cls, *args):
return cls(**cls._parse_suffix(*args))


class FY5253Quarter(SingleConstructorMixin, FY5253Mixin):
class FY5253Quarter(FY5253Mixin):
"""
DateOffset increments between business quarter dates
for 52-53 week fiscal year (also known as a 4-4-5 calendar).
Expand Down