From 7294a3d3b3af48f368797a2dc16001fa5ea6fc49 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Mon, 12 Aug 2019 18:31:50 -0700 Subject: [PATCH 1/2] CLN: remove _maybe_update_attributes --- pandas/core/indexes/base.py | 8 -------- pandas/core/indexes/datetimelike.py | 15 +++++++++++++++ pandas/core/indexes/datetimes.py | 8 -------- pandas/core/indexes/range.py | 3 +-- pandas/core/indexes/timedeltas.py | 17 ++++++----------- 5 files changed, 22 insertions(+), 29 deletions(-) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 598c4dca9ce88..649143a4ba872 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -722,7 +722,6 @@ def __array_wrap__(self, result, context=None): return result attrs = self._get_attributes_dict() - attrs = self._maybe_update_attributes(attrs) return Index(result, **attrs) @cache_readonly @@ -5368,12 +5367,6 @@ def _add_numeric_methods_disabled(cls): cls.__abs__ = make_invalid_op("__abs__") cls.__inv__ = make_invalid_op("__inv__") - def _maybe_update_attributes(self, attrs): - """ - Update Index attributes (e.g. freq) depending on op. - """ - return attrs - def _validate_for_numeric_unaryop(self, op, opstr): """ Validate if we can perform a numeric unary operation. @@ -5463,7 +5456,6 @@ def _evaluate_numeric_unary(self): self._validate_for_numeric_unaryop(op, opstr) attrs = self._get_attributes_dict() - attrs = self._maybe_update_attributes(attrs) return Index(op(self.values), **attrs) _evaluate_numeric_unary.__name__ = opstr diff --git a/pandas/core/indexes/datetimelike.py b/pandas/core/indexes/datetimelike.py index af99c7a2754e5..c7664d9777c71 100644 --- a/pandas/core/indexes/datetimelike.py +++ b/pandas/core/indexes/datetimelike.py @@ -15,6 +15,7 @@ from pandas.core.dtypes.common import ( ensure_int64, + is_bool_dtype, is_dtype_equal, is_float, is_integer, @@ -163,6 +164,20 @@ def values(self): def asi8(self): return self._data.asi8 + def __array_wrap__(self, result, context=None): + """ + Gets called after a ufunc. + """ + result = lib.item_from_zerodim(result) + if is_bool_dtype(result) or lib.is_scalar(result): + return result + + attrs = self._get_attributes_dict() + if not is_period_dtype(self) and attrs["freq"]: + # no need to infer if freq is None + attrs["freq"] = "infer" + return Index(result, **attrs) + # ------------------------------------------------------------------------ def equals(self, other): diff --git a/pandas/core/indexes/datetimes.py b/pandas/core/indexes/datetimes.py index 9f2b31f23d2fa..caae9a0b5f751 100644 --- a/pandas/core/indexes/datetimes.py +++ b/pandas/core/indexes/datetimes.py @@ -465,14 +465,6 @@ def _convert_for_op(self, value): return _to_M8(value) raise ValueError("Passed item and index have different timezone") - def _maybe_update_attributes(self, attrs): - """ Update Index attributes (e.g. freq) depending on op """ - freq = attrs.get("freq", None) - if freq is not None: - # no need to infer if freq is None - attrs["freq"] = "infer" - return attrs - # -------------------------------------------------------------------- # Rendering Methods diff --git a/pandas/core/indexes/range.py b/pandas/core/indexes/range.py index d2bea5f68b92d..babf881d780ba 100644 --- a/pandas/core/indexes/range.py +++ b/pandas/core/indexes/range.py @@ -74,7 +74,7 @@ class RangeIndex(Int64Index): _engine_type = libindex.Int64Engine _range = None # type: range - # check whether self._data has benn called + # check whether self._data has been called _cached_data = None # type: np.ndarray # -------------------------------------------------------------------- # Constructors @@ -784,7 +784,6 @@ def _evaluate_numeric_binop(self, other): other = self._validate_for_numeric_binop(other, op) attrs = self._get_attributes_dict() - attrs = self._maybe_update_attributes(attrs) left, right = self, other diff --git a/pandas/core/indexes/timedeltas.py b/pandas/core/indexes/timedeltas.py index f2ce562536b95..b51b20ea1ebb4 100644 --- a/pandas/core/indexes/timedeltas.py +++ b/pandas/core/indexes/timedeltas.py @@ -44,7 +44,11 @@ class TimedeltaDelegateMixin(DatetimelikeDelegateMixin): # which we we dont' want to expose in the .dt accessor. _delegate_class = TimedeltaArray _delegated_properties = TimedeltaArray._datetimelike_ops + ["components"] - _delegated_methods = TimedeltaArray._datetimelike_methods + ["_box_values"] + _delegated_methods = TimedeltaArray._datetimelike_methods + [ + "_box_values", + "__neg__", + "__abs__", + ] _raw_properties = {"components"} _raw_methods = {"to_pytimedelta"} @@ -56,7 +60,7 @@ class TimedeltaDelegateMixin(DatetimelikeDelegateMixin): TimedeltaArray, TimedeltaDelegateMixin._delegated_methods, typ="method", - overwrite=False, + overwrite=True, ) class TimedeltaIndex( DatetimeIndexOpsMixin, dtl.TimelikeOps, Int64Index, TimedeltaDelegateMixin @@ -279,14 +283,6 @@ def __setstate__(self, state): _unpickle_compat = __setstate__ - def _maybe_update_attributes(self, attrs): - """ Update Index attributes (e.g. freq) depending on op """ - freq = attrs.get("freq", None) - if freq is not None: - # no need to infer if freq is None - attrs["freq"] = "infer" - return attrs - # ------------------------------------------------------------------- # Rendering Methods @@ -689,7 +685,6 @@ def delete(self, loc): TimedeltaIndex._add_comparison_ops() -TimedeltaIndex._add_numeric_methods_unary() TimedeltaIndex._add_logical_methods_disabled() TimedeltaIndex._add_datetimelike_methods() From a7f7d8126ed8f55c9233b465c1b99ffcb32617ba Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Mon, 12 Aug 2019 19:24:34 -0700 Subject: [PATCH 2/2] implement __pos__ --- pandas/core/arrays/timedeltas.py | 4 +++- pandas/core/indexes/timedeltas.py | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/pandas/core/arrays/timedeltas.py b/pandas/core/arrays/timedeltas.py index 6899e47045c1c..3609c68a26c0f 100644 --- a/pandas/core/arrays/timedeltas.py +++ b/pandas/core/arrays/timedeltas.py @@ -776,12 +776,14 @@ def __rdivmod__(self, other): res2 = other - res1 * self return res1, res2 - # Note: TimedeltaIndex overrides this in call to cls._add_numeric_methods def __neg__(self): if self.freq is not None: return type(self)(-self._data, freq=-self.freq) return type(self)(-self._data) + def __pos__(self): + return type(self)(self._data, freq=self.freq) + def __abs__(self): # Note: freq is not preserved return type(self)(np.abs(self._data)) diff --git a/pandas/core/indexes/timedeltas.py b/pandas/core/indexes/timedeltas.py index b51b20ea1ebb4..d06afa3daa792 100644 --- a/pandas/core/indexes/timedeltas.py +++ b/pandas/core/indexes/timedeltas.py @@ -47,6 +47,7 @@ class TimedeltaDelegateMixin(DatetimelikeDelegateMixin): _delegated_methods = TimedeltaArray._datetimelike_methods + [ "_box_values", "__neg__", + "__pos__", "__abs__", ] _raw_properties = {"components"}