diff --git a/pandas/core/indexes/datetimelike.py b/pandas/core/indexes/datetimelike.py index c98f8ceea0ffa..f37f6d545f343 100644 --- a/pandas/core/indexes/datetimelike.py +++ b/pandas/core/indexes/datetimelike.py @@ -627,9 +627,9 @@ def _convert_scalar_indexer(self, key, kind=None): ._convert_scalar_indexer(key, kind=kind)) def _add_datelike(self, other): - raise TypeError("cannot add {0} and {1}" - .format(type(self).__name__, - type(other).__name__)) + raise TypeError("cannot add {cls} and {typ}" + .format(cls=type(self).__name__, + typ=type(other).__name__)) def _sub_datelike(self, other): raise com.AbstractMethodError(self) @@ -670,8 +670,9 @@ def __add__(self, other): elif isinstance(self, TimedeltaIndex) and isinstance(other, Index): if hasattr(other, '_add_delta'): return other._add_delta(self) - raise TypeError("cannot add TimedeltaIndex and {typ}" - .format(typ=type(other))) + raise TypeError("cannot add {cls} and {typ}" + .format(cls=type(self).__name__, + typ=type(other).__name__)) elif is_integer(other): return self.shift(other) elif isinstance(other, (datetime, np.datetime64)): @@ -705,8 +706,9 @@ def __sub__(self, other): return self._sub_offset_array(other) elif isinstance(self, TimedeltaIndex) and isinstance(other, Index): if not isinstance(other, TimedeltaIndex): - raise TypeError("cannot subtract TimedeltaIndex and {typ}" - .format(typ=type(other).__name__)) + raise TypeError("cannot subtract {cls} and {typ}" + .format(cls=type(self).__name__, + typ=type(other).__name__)) return self._add_delta(-other) elif isinstance(other, DatetimeIndex): return self._sub_datelike(other) @@ -794,7 +796,7 @@ def isin(self, values): def shift(self, n, freq=None): """ - Specialized shift which produces a DatetimeIndex + Specialized shift which produces a %(klass)s Parameters ---------- @@ -804,7 +806,7 @@ def shift(self, n, freq=None): Returns ------- - shifted : DatetimeIndex + shifted : %(klass)s """ if freq is not None and freq != self.freq: if isinstance(freq, compat.string_types): diff --git a/pandas/core/indexes/datetimes.py b/pandas/core/indexes/datetimes.py index cc9ce1f3fd5eb..a422d5b4c3851 100644 --- a/pandas/core/indexes/datetimes.py +++ b/pandas/core/indexes/datetimes.py @@ -106,7 +106,7 @@ def _dt_index_cmp(opname, cls, nat_result=False): """ def wrapper(self, other): - func = getattr(super(DatetimeIndex, self), opname) + binop = getattr(Index, opname) if isinstance(other, (datetime, compat.string_types)): if isinstance(other, datetime): @@ -114,7 +114,7 @@ def wrapper(self, other): self._assert_tzawareness_compat(other) other = _to_m8(other, tz=self.tz) - result = func(other) + result = binop(self, other) if isna(other): result.fill(nat_result) else: @@ -134,7 +134,7 @@ def wrapper(self, other): if is_datetimelike(other): self._assert_tzawareness_compat(other) - result = func(np.asarray(other)) + result = binop(self, np.asarray(other)) result = com._values_from_object(result) if isinstance(other, Index): @@ -856,9 +856,9 @@ def _add_datelike(self, other): # adding a timedeltaindex to a datetimelike if other is libts.NaT: return self._nat_new(box=True) - raise TypeError("cannot add {0} and {1}" - .format(type(self).__name__, - type(other).__name__)) + raise TypeError("cannot add {cls} and {typ}" + .format(cls=type(self).__name__, + typ=type(other).__name__)) def _sub_datelike(self, other): # subtract a datetime from myself, yielding a TimedeltaIndex @@ -866,8 +866,9 @@ def _sub_datelike(self, other): if isinstance(other, DatetimeIndex): # require tz compat if not self._has_same_tz(other): - raise TypeError("DatetimeIndex subtraction must have the same " - "timezones or no timezones") + raise TypeError("{cls} subtraction must have the same " + "timezones or no timezones" + .format(cls=type(self).__name__)) result = self._sub_datelike_dti(other) elif isinstance(other, (datetime, np.datetime64)): other = Timestamp(other) @@ -884,8 +885,9 @@ def _sub_datelike(self, other): result = self._maybe_mask_results(result, fill_value=libts.iNaT) else: - raise TypeError("cannot subtract DatetimeIndex and {typ}" - .format(typ=type(other).__name__)) + raise TypeError("cannot subtract {cls} and {typ}" + .format(cls=type(self).__name__, + typ=type(other).__name__)) return TimedeltaIndex(result, name=self.name, copy=False) def _sub_datelike_dti(self, other): @@ -901,6 +903,11 @@ def _sub_datelike_dti(self, other): new_values[mask] = libts.iNaT return new_values.view('i8') + @Substitution(klass='DatetimeIndex') + @Appender(DatetimeIndexOpsMixin.shift.__doc__) + def shift(self, n, freq=None): + return super(DatetimeIndex, self).shift(n, freq) + def _maybe_update_attributes(self, attrs): """ Update Index attributes (e.g. freq) depending on op """ freq = attrs.get('freq', None) @@ -948,8 +955,8 @@ def _add_offset(self, offset): return result except NotImplementedError: - warnings.warn("Non-vectorized DateOffset being applied to Series " - "or DatetimeIndex", PerformanceWarning) + warnings.warn("Non-vectorized DateOffset being applied to {cls}" + .format(cls=type(self).__name__), PerformanceWarning) return self.astype('O') + offset def _add_offset_array(self, other): @@ -960,8 +967,8 @@ def _add_offset_array(self, other): return self + other[0] else: warnings.warn("Adding/subtracting array of DateOffsets to " - "{} not vectorized".format(type(self)), - PerformanceWarning) + "{cls} not vectorized" + .format(cls=type(self).__name__), PerformanceWarning) return self.astype('O') + np.array(other) # TODO: This works for __add__ but loses dtype in __sub__ @@ -973,8 +980,8 @@ def _sub_offset_array(self, other): return self - other[0] else: warnings.warn("Adding/subtracting array of DateOffsets to " - "{} not vectorized".format(type(self)), - PerformanceWarning) + "{cls} not vectorized" + .format(cls=type(self).__name__), PerformanceWarning) res_values = self.astype('O').values - np.array(other) return self.__class__(res_values, freq='infer') diff --git a/pandas/core/indexes/timedeltas.py b/pandas/core/indexes/timedeltas.py index 4b543262fc485..cd9f08a3e7f16 100644 --- a/pandas/core/indexes/timedeltas.py +++ b/pandas/core/indexes/timedeltas.py @@ -59,23 +59,25 @@ def _td_index_cmp(opname, cls, nat_result=False): """ def wrapper(self, other): - msg = "cannot compare a TimedeltaIndex with type {0}" - func = getattr(super(TimedeltaIndex, self), opname) + msg = "cannot compare a {cls} with type {typ}" + binop = getattr(Index, opname) if _is_convertible_to_td(other) or other is NaT: try: other = _to_m8(other) except ValueError: # failed to parse as timedelta - raise TypeError(msg.format(type(other))) - result = func(other) + raise TypeError(msg.format(cls=type(self).__name__, + typ=type(other).__name__)) + result = binop(self, other) if isna(other): result.fill(nat_result) else: if not is_list_like(other): - raise TypeError(msg.format(type(other))) + raise TypeError(msg.format(cls=type(self).__name__, + typ=type(other).__name__)) other = TimedeltaIndex(other).values - result = func(other) + result = binop(self, other) result = com._values_from_object(result) if isinstance(other, Index): @@ -364,8 +366,9 @@ def _add_delta(self, delta): # update name when delta is index name = com._maybe_match_name(self, delta) else: - raise TypeError("cannot add the type {0} to a TimedeltaIndex" - .format(type(delta))) + raise TypeError("cannot add the type {typ} to a {cls}" + .format(typ=type(delta).__name__, + cls=type(self).__name__)) result = TimedeltaIndex(new_values, freq='infer', name=name) return result @@ -409,7 +412,7 @@ def _add_datelike(self, other): result = checked_add_with_arr(i8, other.value, arr_mask=self._isnan) result = self._maybe_mask_results(result, fill_value=iNaT) - return DatetimeIndex(result, name=self.name, copy=False) + return DatetimeIndex(result, name=self.name, copy=False) def _sub_datelike(self, other): # GH#19124 Timedelta - datetime is not in general well-defined. @@ -418,7 +421,8 @@ def _sub_datelike(self, other): if other is NaT: return self._nat_new() else: - raise TypeError("cannot subtract a datelike from a TimedeltaIndex") + raise TypeError("cannot subtract a datelike from a {cls}" + .format(cls=type(self).__name__)) def _add_offset_array(self, other): # Array/Index of DateOffset objects @@ -433,12 +437,14 @@ def _add_offset_array(self, other): else: from pandas.errors import PerformanceWarning warnings.warn("Adding/subtracting array of DateOffsets to " - "{} not vectorized".format(type(self)), + "{cls} not vectorized" + .format(cls=type(self).__name__), PerformanceWarning) return self.astype('O') + np.array(other) # TODO: This works for __add__ but loses dtype in __sub__ except AttributeError: - raise TypeError("Cannot add non-tick DateOffset to TimedeltaIndex") + raise TypeError("Cannot add non-tick DateOffset to {cls}" + .format(cls=type(self).__name__)) def _sub_offset_array(self, other): # Array/Index of DateOffset objects @@ -453,13 +459,19 @@ def _sub_offset_array(self, other): else: from pandas.errors import PerformanceWarning warnings.warn("Adding/subtracting array of DateOffsets to " - "{} not vectorized".format(type(self)), + "{cls} not vectorized" + .format(cls=type(self).__name__), PerformanceWarning) res_values = self.astype('O').values - np.array(other) return self.__class__(res_values, freq='infer') except AttributeError: - raise TypeError("Cannot subtrack non-tick DateOffset from" - " TimedeltaIndex") + raise TypeError("Cannot subtrack non-tick DateOffset " + "from {cls}".format(cls=type(self).__name__)) + + @Substitution(klass='TimedeltaIndex') + @Appender(DatetimeIndexOpsMixin.shift.__doc__) + def shift(self, n, freq=None): + return super(TimedeltaIndex, self).shift(n, freq) def _format_native_types(self, na_rep=u('NaT'), date_format=None, **kwargs): @@ -928,7 +940,7 @@ def insert(self, loc, item): def delete(self, loc): """ - Make a new DatetimeIndex with passed location(s) deleted. + Make a new TimedeltaIndex with passed location(s) deleted. Parameters ----------