From cf368d522976bee296eb59f224e40e41605bef42 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Sat, 30 Jun 2018 19:43:33 -0700 Subject: [PATCH 1/5] move _add__ and __sub__ to liboffsets, implement _Tick --- pandas/_libs/tslibs/offsets.pyx | 24 ++++++++++++++++++++++++ pandas/_libs/tslibs/period.pyx | 6 +++--- pandas/tseries/offsets.py | 21 +-------------------- 3 files changed, 28 insertions(+), 23 deletions(-) diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index 841db80cf094e..9f7d0f5063e83 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -364,6 +364,24 @@ class _BaseOffset(object): if name not in ['n', 'normalize']} return {name: kwds[name] for name in kwds if kwds[name] is not None} + def __add__(self, other): + if getattr(other, "_typ", None) in ["datetimeindex", + "series", "period"]: + # defer to the other class's implementation + try: + return self.apply(other) + except ApplyTypeError: + return NotImplemented + + def __sub__(self, other): + if isinstance(other, datetime): + raise TypeError('Cannot subtract datetime from offset.') + elif type(other) == type(self): + return self.__class__(self.n - other.n, normalize=self.normalize, + **self.kwds) + else: # pragma: no cover + return NotImplemented + def __call__(self, other): return self.apply(other) @@ -491,6 +509,12 @@ class BaseOffset(_BaseOffset): return -self + other +class _Tick(object): + # dummy class to mix into tseries.Tick so that in tslibs.period we can + # do isinstance checks on _Tick and avoid importing tseries.offsets + pass + + # ---------------------------------------------------------------------- # RelativeDelta Arithmetic diff --git a/pandas/_libs/tslibs/period.pyx b/pandas/_libs/tslibs/period.pyx index 6985d3b8df363..33d05bc8fe2c8 100644 --- a/pandas/_libs/tslibs/period.pyx +++ b/pandas/_libs/tslibs/period.pyx @@ -55,8 +55,8 @@ from parsing import parse_time_string, NAT_SENTINEL from resolution import Resolution from nattype import nat_strings, NaT, iNaT from nattype cimport _nat_scalar_rules, NPY_NAT +from offsets import _Tick -from pandas.tseries import offsets from pandas.tseries import frequencies @@ -1062,9 +1062,9 @@ cdef class _Period(object): int64_t nanos, offset_nanos if (PyDelta_Check(other) or util.is_timedelta64_object(other) or - isinstance(other, offsets.Tick)): + isinstance(other, _Tick)): offset = frequencies.to_offset(self.freq.rule_code) - if isinstance(offset, offsets.Tick): + if isinstance(offset, _Tick): nanos = delta_to_nanoseconds(other) offset_nanos = delta_to_nanoseconds(offset) if nanos % offset_nanos == 0: diff --git a/pandas/tseries/offsets.py b/pandas/tseries/offsets.py index 1cfd3f476f8ab..315e34ecc49c9 100644 --- a/pandas/tseries/offsets.py +++ b/pandas/tseries/offsets.py @@ -311,25 +311,6 @@ def _repr_attrs(self): def name(self): return self.rule_code - def __add__(self, other): - if isinstance(other, (ABCDatetimeIndex, ABCSeries)): - return other + self - elif isinstance(other, ABCPeriod): - return other + self - try: - return self.apply(other) - except ApplyTypeError: - return NotImplemented - - def __sub__(self, other): - if isinstance(other, datetime): - raise TypeError('Cannot subtract datetime from offset.') - elif type(other) == type(self): - return self.__class__(self.n - other.n, normalize=self.normalize, - **self.kwds) - else: # pragma: no cover - return NotImplemented - def rollback(self, dt): """Roll provided date backward to next offset only if not on offset""" dt = as_timestamp(dt) @@ -2129,7 +2110,7 @@ def f(self, other): return f -class Tick(SingleConstructorOffset): +class Tick(liboffsets._Tick, SingleConstructorOffset): _inc = Timedelta(microseconds=1000) _prefix = 'undefined' _attributes = frozenset(['n', 'normalize']) From c63342ce3ef1f4165bf0a162e0c989804efdb40c Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Sat, 30 Jun 2018 19:53:04 -0700 Subject: [PATCH 2/5] typo fixup --- pandas/_libs/tslibs/offsets.pyx | 1 + 1 file changed, 1 insertion(+) diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index 9f7d0f5063e83..d7400d02732cd 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -368,6 +368,7 @@ class _BaseOffset(object): if getattr(other, "_typ", None) in ["datetimeindex", "series", "period"]: # defer to the other class's implementation + return other + self try: return self.apply(other) except ApplyTypeError: From b45147f28e35a3e7a1b249fc15c1260be7b3d47d Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Sat, 30 Jun 2018 21:56:48 -0700 Subject: [PATCH 3/5] fixup remove unused imports --- pandas/tseries/offsets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tseries/offsets.py b/pandas/tseries/offsets.py index 315e34ecc49c9..5bd9e52264b2e 100644 --- a/pandas/tseries/offsets.py +++ b/pandas/tseries/offsets.py @@ -7,7 +7,7 @@ from pandas import compat import numpy as np -from pandas.core.dtypes.generic import ABCSeries, ABCDatetimeIndex, ABCPeriod +from pandas.core.dtypes.generic import ABCPeriod from pandas.core.tools.datetimes import to_datetime import pandas.core.common as com From b23db08a41d2686543555aee37499f5868190f07 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Sun, 1 Jul 2018 10:15:00 -0700 Subject: [PATCH 4/5] change comment to docstring --- pandas/_libs/tslibs/offsets.pyx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index d7400d02732cd..f864f1d110a38 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -511,8 +511,10 @@ class BaseOffset(_BaseOffset): class _Tick(object): - # dummy class to mix into tseries.Tick so that in tslibs.period we can - # do isinstance checks on _Tick and avoid importing tseries.offsets + """ + 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 + """ pass From 1a87b6a5c55a4ec22691c6c6985a4fb94a63573a Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Mon, 2 Jul 2018 16:34:29 -0700 Subject: [PATCH 5/5] change __class__ to type --- pandas/_libs/tslibs/offsets.pyx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index f864f1d110a38..326630cf1f6df 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -378,8 +378,8 @@ class _BaseOffset(object): if isinstance(other, datetime): raise TypeError('Cannot subtract datetime from offset.') elif type(other) == type(self): - return self.__class__(self.n - other.n, normalize=self.normalize, - **self.kwds) + return type(self)(self.n - other.n, normalize=self.normalize, + **self.kwds) else: # pragma: no cover return NotImplemented @@ -387,8 +387,8 @@ class _BaseOffset(object): return self.apply(other) def __mul__(self, other): - return self.__class__(n=other * self.n, normalize=self.normalize, - **self.kwds) + return type(self)(n=other * self.n, normalize=self.normalize, + **self.kwds) def __neg__(self): # Note: we are defering directly to __mul__ instead of __rmul__, as