From 718980095c4d5b7e9c6dafe436228ca9272b2439 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Thu, 3 Aug 2017 09:42:12 -0700 Subject: [PATCH 1/3] Create ABCDateOffset Replace isinstance(x, pd.DateOffset) with isinstance(x, ABCDateOffset) in a few places where doing so lets us avoid run-time imports --- pandas/core/dtypes/generic.py | 2 ++ pandas/core/indexes/base.py | 14 +++++++------- pandas/core/ops.py | 10 +++++++--- pandas/core/tools/datetimes.py | 5 ++--- pandas/tseries/offsets.py | 1 + 5 files changed, 19 insertions(+), 13 deletions(-) diff --git a/pandas/core/dtypes/generic.py b/pandas/core/dtypes/generic.py index 90608c18ae503..618bcf6495155 100644 --- a/pandas/core/dtypes/generic.py +++ b/pandas/core/dtypes/generic.py @@ -52,6 +52,8 @@ def _check(cls, inst): ABCCategorical = create_pandas_abc_type("ABCCategorical", "_typ", ("categorical")) ABCPeriod = create_pandas_abc_type("ABCPeriod", "_typ", ("period", )) +ABCDateOffset = create_pandas_abc_type("ABCDateOffset", "_typ", + ("dateoffset",)) class _ABCGeneric(type): diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 4aecc75d95971..de6221987a59a 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -13,7 +13,11 @@ from pandas import compat -from pandas.core.dtypes.generic import ABCSeries, ABCMultiIndex, ABCPeriodIndex +from pandas.core.dtypes.generic import ( + ABCSeries, + ABCMultiIndex, + ABCPeriodIndex, + ABCDateOffset) from pandas.core.dtypes.missing import isna, array_equivalent from pandas.core.dtypes.common import ( _ensure_int64, @@ -3814,8 +3818,6 @@ def _validate_for_numeric_binop(self, other, op, opstr): internal method called by ops """ - from pandas.tseries.offsets import DateOffset - # if we are an inheritor of numeric, # but not actually numeric (e.g. DatetimeIndex/PeriodInde) if not self._is_numeric_dtype: @@ -3843,7 +3845,7 @@ def _validate_for_numeric_binop(self, other, op, opstr): if other.dtype.kind not in ['f', 'i', 'u']: raise TypeError("cannot evaluate a numeric op " "with a non-numeric dtype") - elif isinstance(other, (DateOffset, np.timedelta64, + elif isinstance(other, (ABCDateOffset, np.timedelta64, Timedelta, datetime.timedelta)): # higher up to handle pass @@ -3862,12 +3864,10 @@ def _add_numeric_methods_binary(cls): def _make_evaluate_binop(op, opstr, reversed=False, constructor=Index): def _evaluate_numeric_binop(self, other): - - from pandas.tseries.offsets import DateOffset other = self._validate_for_numeric_binop(other, op, opstr) # handle time-based others - if isinstance(other, (DateOffset, np.timedelta64, + if isinstance(other, (ABCDateOffset, np.timedelta64, Timedelta, datetime.timedelta)): return self._evaluate_with_timedelta_like(other, op, opstr) elif isinstance(other, (Timestamp, np.datetime64)): diff --git a/pandas/core/ops.py b/pandas/core/ops.py index 4e08e1483d617..82101414e4aa6 100644 --- a/pandas/core/ops.py +++ b/pandas/core/ops.py @@ -35,7 +35,11 @@ is_scalar, _ensure_object) from pandas.core.dtypes.cast import maybe_upcast_putmask, find_common_type -from pandas.core.dtypes.generic import ABCSeries, ABCIndex, ABCPeriodIndex +from pandas.core.dtypes.generic import ( + ABCSeries, + ABCIndex, + ABCPeriodIndex, + ABCDateOffset) # ----------------------------------------------------------------------------- # Functions that add arithmetic methods to objects, given arithmetic factory @@ -605,10 +609,10 @@ def f(x): def _is_offset(self, arr_or_obj): """ check if obj or all elements of list-like is DateOffset """ - if isinstance(arr_or_obj, pd.DateOffset): + if isinstance(arr_or_obj, ABCDateOffset): return True elif is_list_like(arr_or_obj) and len(arr_or_obj): - return all(isinstance(x, pd.DateOffset) for x in arr_or_obj) + return all(isinstance(x, ABCDateOffset) for x in arr_or_obj) return False diff --git a/pandas/core/tools/datetimes.py b/pandas/core/tools/datetimes.py index a1f323aff7c1a..eebf78d7619eb 100644 --- a/pandas/core/tools/datetimes.py +++ b/pandas/core/tools/datetimes.py @@ -17,7 +17,7 @@ is_numeric_dtype) from pandas.core.dtypes.generic import ( ABCIndexClass, ABCSeries, - ABCDataFrame) + ABCDataFrame, ABCDateOffset) from pandas.core.dtypes.missing import notna from pandas.core import algorithms @@ -720,8 +720,7 @@ def parse_time_string(arg, freq=None, dayfirst=None, yearfirst=None): if not isinstance(arg, compat.string_types): return arg - from pandas.tseries.offsets import DateOffset - if isinstance(freq, DateOffset): + if isinstance(freq, ABCDateOffset): freq = freq.rule_code if dayfirst is None: diff --git a/pandas/tseries/offsets.py b/pandas/tseries/offsets.py index 2a120a0696836..56ef703e67ca0 100644 --- a/pandas/tseries/offsets.py +++ b/pandas/tseries/offsets.py @@ -184,6 +184,7 @@ def __add__(date): ) _use_relativedelta = False _adjust_dst = False + _typ = "dateoffset" # default for prior pickles normalize = False From 3f46afeb9c62fb3638fddac2ca34d8bb13455ec2 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Thu, 3 Aug 2017 16:42:13 -0700 Subject: [PATCH 2/3] Add tests for ABCDateOffset --- pandas/tests/dtypes/test_generic.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pandas/tests/dtypes/test_generic.py b/pandas/tests/dtypes/test_generic.py index 653d7d3082c08..c960d3c391e74 100644 --- a/pandas/tests/dtypes/test_generic.py +++ b/pandas/tests/dtypes/test_generic.py @@ -38,3 +38,9 @@ def test_abc_types(self): assert isinstance(self.sparse_array, gt.ABCSparseArray) assert isinstance(self.categorical, gt.ABCCategorical) assert isinstance(pd.Period('2012', freq='A-DEC'), gt.ABCPeriod) + + assert isinstance(pd.DateOffset(), gt.ABCDateOffset) + assert isinstance(pd.Period('2012', freq='A-DEC').freq, + gt.ABCDateOffset) + assert not isinstance(pd.Period('2012', freq='A-DEC'), + gt.ABCDateOffset) From 236a3ee474e4b72b1e89f3f52a8f33879decf67b Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Tue, 8 Aug 2017 18:06:23 -0700 Subject: [PATCH 3/3] Remove whitespace in the hopes that it will simplify git merge --- pandas/tests/dtypes/test_generic.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pandas/tests/dtypes/test_generic.py b/pandas/tests/dtypes/test_generic.py index c960d3c391e74..3dcfeab1db921 100644 --- a/pandas/tests/dtypes/test_generic.py +++ b/pandas/tests/dtypes/test_generic.py @@ -38,7 +38,6 @@ def test_abc_types(self): assert isinstance(self.sparse_array, gt.ABCSparseArray) assert isinstance(self.categorical, gt.ABCCategorical) assert isinstance(pd.Period('2012', freq='A-DEC'), gt.ABCPeriod) - assert isinstance(pd.DateOffset(), gt.ABCDateOffset) assert isinstance(pd.Period('2012', freq='A-DEC').freq, gt.ABCDateOffset)