From 20ee6193da863eed9ea7a3c3727a61adb1887de4 Mon Sep 17 00:00:00 2001 From: Brock Date: Wed, 3 Jun 2020 11:45:47 -0700 Subject: [PATCH] REF: avoid runtime imports in offsets --- pandas/_libs/tslibs/offsets.pyx | 34 +++++----------------------- pandas/_libs/tslibs/tzconversion.pyx | 2 +- 2 files changed, 7 insertions(+), 29 deletions(-) diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index 33b478c4d8da4..d2e8806319f78 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -31,8 +31,6 @@ from pandas._libs.tslibs.util cimport ( is_float_object, ) -from pandas._libs.tslibs.base cimport ABCTimestamp - from pandas._libs.tslibs.ccalendar import ( MONTH_ALIASES, MONTH_TO_CAL_NUM, weekday_to_int, int_to_weekday, ) @@ -48,7 +46,9 @@ from pandas._libs.tslibs.timezones cimport utc_pytz as UTC from pandas._libs.tslibs.tzconversion cimport tz_convert_single from .timedeltas cimport delta_to_nanoseconds - +from .timedeltas import Timedelta +from .timestamps cimport _Timestamp +from .timestamps import Timestamp # --------------------------------------------------------------------- # Misc Helpers @@ -62,7 +62,7 @@ cdef bint is_tick_object(object obj): cdef datetime _as_datetime(datetime obj): - if isinstance(obj, ABCTimestamp): + if isinstance(obj, _Timestamp): return obj.to_pydatetime() return obj @@ -71,7 +71,7 @@ cdef bint _is_normalized(datetime dt): if dt.hour != 0 or dt.minute != 0 or dt.second != 0 or dt.microsecond != 0: # Regardless of whether dt is datetime vs Timestamp return False - if isinstance(dt, ABCTimestamp): + if isinstance(dt, _Timestamp): return dt.nanosecond == 0 return True @@ -113,7 +113,6 @@ def apply_wraps(func): # not play nicely with cython class methods def wrapper(self, other): - from pandas import Timestamp if other is NaT: return NaT @@ -590,7 +589,6 @@ cdef class BaseOffset: TimeStamp Rolled timestamp if not on offset, otherwise unchanged timestamp. """ - from pandas import Timestamp dt = Timestamp(dt) if not self.is_on_offset(dt): dt = dt - type(self)(1, normalize=self.normalize, **self.kwds) @@ -605,7 +603,6 @@ cdef class BaseOffset: TimeStamp Rolled timestamp if not on offset, otherwise unchanged timestamp. """ - from pandas import Timestamp dt = Timestamp(dt) if not self.is_on_offset(dt): dt = dt + type(self)(1, normalize=self.normalize, **self.kwds) @@ -772,7 +769,6 @@ cdef class Tick(SingleConstructorOffset): @property def delta(self): - from .timedeltas import Timedelta return self.n * Timedelta(self._nanos_inc) @property @@ -859,7 +855,7 @@ cdef class Tick(SingleConstructorOffset): def apply(self, other): # Timestamp can handle tz and nano sec, thus no need to use apply_wraps - if isinstance(other, ABCTimestamp): + if isinstance(other, _Timestamp): # GH#15126 # in order to avoid a recursive @@ -874,7 +870,6 @@ cdef class Tick(SingleConstructorOffset): return NaT elif is_datetime64_object(other) or PyDate_Check(other): # PyDate_Check includes date, datetime - from pandas import Timestamp return Timestamp(other) + self if PyDelta_Check(other): @@ -1026,7 +1021,6 @@ cdef class RelativeDeltaOffset(BaseOffset): # bring tz back from UTC calculation other = localize_pydatetime(other, tzinfo) - from .timestamps import Timestamp return Timestamp(other) else: return other + timedelta(self.n) @@ -1079,7 +1073,6 @@ cdef class RelativeDeltaOffset(BaseOffset): if k in ["days", "hours", "minutes", "seconds", "microseconds"] } if timedelta_kwds: - from .timedeltas import Timedelta delta = Timedelta(**timedelta_kwds) index = index + (self.n * delta) return index @@ -2273,7 +2266,6 @@ cdef class SemiMonthOffset(SingleConstructorOffset): @apply_index_wraps def apply_index(self, dtindex): # determine how many days away from the 1st of the month we are - from pandas import Timedelta dti = dtindex days_from_start = dtindex.to_perioddelta("M").asi8 @@ -2375,8 +2367,6 @@ cdef class SemiMonthEnd(SemiMonthOffset): ------- result : DatetimeIndex """ - from pandas import Timedelta - nanos = (roll % 2) * Timedelta(days=self.day_of_month).value dtindex += nanos.astype("timedelta64[ns]") return dtindex + Timedelta(days=-1) @@ -2434,7 +2424,6 @@ cdef class SemiMonthBegin(SemiMonthOffset): ------- result : DatetimeIndex """ - from pandas import Timedelta nanos = (roll % 2) * Timedelta(days=self.day_of_month - 1).value return dtindex + nanos.astype("timedelta64[ns]") @@ -2526,7 +2515,6 @@ cdef class Week(SingleConstructorOffset): ------- result : DatetimeIndex """ - from pandas import Timedelta from .frequencies import get_freq_code # TODO: avoid circular import off = dtindex.to_perioddelta("D") @@ -2827,8 +2815,6 @@ cdef class FY5253(FY5253Mixin): @apply_wraps def apply(self, other): - from pandas import Timestamp - norm = Timestamp(other).normalize() n = self.n @@ -3049,8 +3035,6 @@ cdef class FY5253Quarter(FY5253Mixin): num_qtrs : int tdelta : Timedelta """ - from pandas import Timestamp, Timedelta - num_qtrs = 0 norm = Timestamp(other).tz_localize(None) @@ -3081,7 +3065,6 @@ cdef class FY5253Quarter(FY5253Mixin): @apply_wraps def apply(self, other): # Note: self.n == 0 is not allowed. - from pandas import Timedelta n = self.n @@ -3121,8 +3104,6 @@ cdef class FY5253Quarter(FY5253Mixin): def year_has_extra_week(self, dt: datetime) -> bool: # Avoid round-down errors --> normalize to get # e.g. '370D' instead of '360D23H' - from pandas import Timestamp - norm = Timestamp(dt).normalize().tz_localize(None) next_year_end = self._offset.rollforward(norm) @@ -3601,9 +3582,6 @@ cpdef to_offset(freq): >>> to_offset(Hour()) """ - # TODO: avoid runtime imports - from pandas._libs.tslibs.timedeltas import Timedelta - if freq is None: return None diff --git a/pandas/_libs/tslibs/tzconversion.pyx b/pandas/_libs/tslibs/tzconversion.pyx index a90d06fa53997..02fe203637d62 100644 --- a/pandas/_libs/tslibs/tzconversion.pyx +++ b/pandas/_libs/tslibs/tzconversion.pyx @@ -20,7 +20,6 @@ from pandas._libs.tslibs.ccalendar cimport DAY_NANOS, HOUR_NANOS from pandas._libs.tslibs.nattype cimport NPY_NAT from pandas._libs.tslibs.np_datetime cimport ( npy_datetimestruct, dt64_to_dtstruct) -from pandas._libs.tslibs.timedeltas cimport delta_to_nanoseconds from pandas._libs.tslibs.timezones cimport ( get_dst_info, is_tzlocal, is_utc, get_timezone, get_utcoffset) @@ -123,6 +122,7 @@ timedelta-like} elif nonexistent == 'shift_backward': shift_backward = True elif PyDelta_Check(nonexistent): + from .timedeltas import delta_to_nanoseconds shift_delta = delta_to_nanoseconds(nonexistent) elif nonexistent not in ('raise', None): msg = ("nonexistent must be one of {'NaT', 'raise', 'shift_forward', "