From c0cbbbefc729e9295c008b206df6dd58c81e8733 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Mon, 15 Oct 2018 16:38:38 -0700 Subject: [PATCH 01/11] small fixups --- pandas/core/arrays/datetimelike.py | 4 ++-- pandas/core/indexes/period.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pandas/core/arrays/datetimelike.py b/pandas/core/arrays/datetimelike.py index a98b0b3bf35f9..62b9f685c009a 100644 --- a/pandas/core/arrays/datetimelike.py +++ b/pandas/core/arrays/datetimelike.py @@ -380,7 +380,7 @@ def _add_delta_tdi(self, other): Add a delta of a TimedeltaIndex return the i8 result view """ - if not len(self) == len(other): + if len(self) != len(other): raise ValueError("cannot add indices of unequal length") if isinstance(other, np.ndarray): @@ -441,7 +441,7 @@ def _sub_period_array(self, other): .format(dtype=other.dtype, cls=type(self).__name__)) - if not len(self) == len(other): + if len(self) != len(other): raise ValueError("cannot subtract arrays/indices of " "unequal length") if self.freq != other.freq: diff --git a/pandas/core/indexes/period.py b/pandas/core/indexes/period.py index f452a57e82725..64a70b52b02a6 100644 --- a/pandas/core/indexes/period.py +++ b/pandas/core/indexes/period.py @@ -289,9 +289,9 @@ def __array_wrap__(self, result, context=None): """ if isinstance(context, tuple) and len(context) > 0: func = context[0] - if (func is np.add): + if func is np.add: pass - elif (func is np.subtract): + elif func is np.subtract: name = self.name left = context[1][0] right = context[1][1] @@ -312,7 +312,7 @@ def __array_wrap__(self, result, context=None): return result # the result is object dtype array of Period # cannot pass _simple_new as it is - return self._shallow_copy(result, freq=self.freq, name=self.name) + return type(self)(result, freq=self.freq, name=self.name) @property def size(self): From 8622871ea32d065654cebc950f9314f98dca7cd4 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Mon, 15 Oct 2018 16:39:37 -0700 Subject: [PATCH 02/11] import abstractmethoderror at top --- pandas/core/arrays/datetimelike.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/pandas/core/arrays/datetimelike.py b/pandas/core/arrays/datetimelike.py index 62b9f685c009a..7fbda6b4c1a1f 100644 --- a/pandas/core/arrays/datetimelike.py +++ b/pandas/core/arrays/datetimelike.py @@ -11,7 +11,8 @@ from pandas._libs.tslibs.period import ( Period, DIFFERENT_FREQ_INDEX, IncompatibleFrequency) -from pandas.errors import NullFrequencyError, PerformanceWarning +from pandas.errors import ( + NullFrequencyError, PerformanceWarning, AbstractMethodError) from pandas import compat from pandas.tseries import frequencies @@ -77,12 +78,10 @@ class AttributesMixin(object): @property def _attributes(self): # Inheriting subclass should implement _attributes as a list of strings - from pandas.errors import AbstractMethodError raise AbstractMethodError(self) @classmethod def _simple_new(cls, values, **kwargs): - from pandas.errors import AbstractMethodError raise AbstractMethodError(cls) def _get_attributes_dict(self): @@ -119,7 +118,7 @@ def _box_func(self): """ box function to get object from internal representation """ - raise com.AbstractMethodError(self) + raise AbstractMethodError(self) def _box_values(self, values): """ @@ -352,13 +351,13 @@ def _add_datelike(self, other): typ=type(other).__name__)) def _sub_datelike(self, other): - raise com.AbstractMethodError(self) + raise AbstractMethodError(self) def _sub_period(self, other): return NotImplemented def _add_offset(self, offset): - raise com.AbstractMethodError(self) + raise AbstractMethodError(self) def _add_delta(self, other): return NotImplemented From 42d3bdb1a88ad70d6a6262d99cd368a99ccfa348 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Mon, 15 Oct 2018 16:43:16 -0700 Subject: [PATCH 03/11] remove unused try_cast kwarg --- pandas/core/frame.py | 2 +- pandas/core/ops.py | 17 +++++++---------- pandas/core/sparse/frame.py | 2 +- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 729b9b23536e8..56402a86df224 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -4942,7 +4942,7 @@ def _combine_match_index(self, other, func, level=None): index=left.index, columns=self.columns, copy=False) - def _combine_match_columns(self, other, func, level=None, try_cast=True): + def _combine_match_columns(self, other, func, level=None): assert isinstance(other, Series) left, right = self.align(other, join='outer', axis=1, level=level, copy=False) diff --git a/pandas/core/ops.py b/pandas/core/ops.py index aff6f17fba2e2..111d27fdac5c9 100644 --- a/pandas/core/ops.py +++ b/pandas/core/ops.py @@ -1731,10 +1731,10 @@ def column_op(a, b): def _combine_series_frame(self, other, func, fill_value=None, axis=None, - level=None, try_cast=True): + level=None): """ Apply binary operator `func` to self, other using alignment and fill - conventions determined by the fill_value, axis, level, and try_cast kwargs. + conventions determined by the fill_value, axis, and level kwargs. Parameters ---------- @@ -1744,7 +1744,6 @@ def _combine_series_frame(self, other, func, fill_value=None, axis=None, fill_value : object, default None axis : {0, 1, 'columns', 'index', None}, default None level : int or None, default None - try_cast : bool, default True Returns ------- @@ -1759,8 +1758,7 @@ def _combine_series_frame(self, other, func, fill_value=None, axis=None, if axis == 0: return self._combine_match_index(other, func, level=level) else: - return self._combine_match_columns(other, func, level=level, - try_cast=try_cast) + return self._combine_match_columns(other, func, level=level) else: if not len(other): return self * np.nan @@ -1771,8 +1769,7 @@ def _combine_series_frame(self, other, func, fill_value=None, axis=None, columns=self.columns) # default axis is columns - return self._combine_match_columns(other, func, level=level, - try_cast=try_cast) + return self._combine_match_columns(other, func, level=level) def _align_method_FRAME(left, right, axis): @@ -1872,7 +1869,7 @@ def f(self, other, axis=default_axis, level=None, fill_value=None): pass_op = op if axis in [0, "columns", None] else na_op return _combine_series_frame(self, other, pass_op, fill_value=fill_value, axis=axis, - level=level, try_cast=True) + level=level) else: if fill_value is not None: self = self.fillna(fill_value) @@ -1914,7 +1911,7 @@ def f(self, other, axis=default_axis, level=None): elif isinstance(other, ABCSeries): return _combine_series_frame(self, other, na_op, fill_value=None, axis=axis, - level=level, try_cast=False) + level=level) else: return self._combine_const(other, na_op, try_cast=False) @@ -1939,7 +1936,7 @@ def f(self, other): elif isinstance(other, ABCSeries): return _combine_series_frame(self, other, func, fill_value=None, axis=None, - level=None, try_cast=False) + level=None) else: # straight boolean comparisons we want to allow all columns diff --git a/pandas/core/sparse/frame.py b/pandas/core/sparse/frame.py index 36b6ea089f459..0b536c1bdf7cd 100644 --- a/pandas/core/sparse/frame.py +++ b/pandas/core/sparse/frame.py @@ -618,7 +618,7 @@ def _combine_match_index(self, other, func, level=None): new_data, index=new_index, columns=self.columns, default_fill_value=fill_value).__finalize__(self) - def _combine_match_columns(self, other, func, level=None, try_cast=True): + def _combine_match_columns(self, other, func, level=None): # patched version of DataFrame._combine_match_columns to account for # NumPy circumventing __rsub__ with float64 types, e.g.: 3.0 - series, # where 3.0 is numpy.float64 and series is a SparseSeries. Still From a9f6a230bdce75fbf6a8f7026231b3eb8f457cca Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Mon, 15 Oct 2018 16:45:26 -0700 Subject: [PATCH 04/11] avoid private constructor --- pandas/io/pytables.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pandas/io/pytables.py b/pandas/io/pytables.py index de193db846c50..0a2d34fec9496 100644 --- a/pandas/io/pytables.py +++ b/pandas/io/pytables.py @@ -2476,8 +2476,7 @@ def _get_index_factory(self, klass): if klass == DatetimeIndex: def f(values, freq=None, tz=None): # data are already in UTC, localize and convert if tz present - result = DatetimeIndex._simple_new(values.values, name=None, - freq=freq) + result = DatetimeIndex(values.values, name=None, freq=freq) if tz is not None: result = result.tz_localize('UTC').tz_convert(tz) return result From db44c4f22f65ec5d7abcc162c5bed4f2557ec76f Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Mon, 15 Oct 2018 16:47:55 -0700 Subject: [PATCH 05/11] Avoid need to override _generate_range in TimedeltaIndex --- pandas/core/arrays/timedeltas.py | 6 ++---- pandas/core/indexes/timedeltas.py | 20 ++++---------------- 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/pandas/core/arrays/timedeltas.py b/pandas/core/arrays/timedeltas.py index 4904a90ab7b2b..fe2d219f376f1 100644 --- a/pandas/core/arrays/timedeltas.py +++ b/pandas/core/arrays/timedeltas.py @@ -140,8 +140,7 @@ def __new__(cls, values, freq=None, start=None, end=None, periods=None, return result @classmethod - def _generate_range(cls, start, end, periods, freq, closed=None, **kwargs): - # **kwargs are for compat with TimedeltaIndex, which includes `name` + def _generate_range(cls, start, end, periods, freq, closed=None): periods = dtl.validate_periods(periods) if freq is None and any(x is None for x in [periods, start, end]): @@ -167,10 +166,9 @@ def _generate_range(cls, start, end, periods, freq, closed=None, **kwargs): if freq is not None: index = _generate_regular_range(start, end, periods, freq) - index = cls._simple_new(index, freq=freq, **kwargs) + index = cls._simple_new(index, freq=freq) else: index = np.linspace(start.value, end.value, periods).astype('i8') - # TODO: shouldn't we pass `name` here? (via **kwargs) index = cls._simple_new(index, freq=freq) if not left_closed: diff --git a/pandas/core/indexes/timedeltas.py b/pandas/core/indexes/timedeltas.py index 56b6dc7051d9f..ad380fd2e8544 100644 --- a/pandas/core/indexes/timedeltas.py +++ b/pandas/core/indexes/timedeltas.py @@ -147,12 +147,10 @@ def __new__(cls, data=None, unit=None, freq=None, start=None, end=None, if data is None: # TODO: Remove this block and associated kwargs; GH#20535 - if freq is None and com._any_none(periods, start, end): - raise ValueError('Must provide freq argument if no data is ' - 'supplied') - periods = dtl.validate_periods(periods) - return cls._generate_range(start, end, periods, name, freq, - closed=closed) + result = cls._generate_range(start, end, periods, freq=freq, + closed=closed) + result.name = name + return result if unit is not None: data = to_timedelta(data, unit=unit, box=False) @@ -181,16 +179,6 @@ def __new__(cls, data=None, unit=None, freq=None, start=None, end=None, return subarr - @classmethod - def _generate_range(cls, start, end, periods, - name=None, freq=None, closed=None): - # TimedeltaArray gets `name` via **kwargs, so we need to explicitly - # override it if name is passed as a positional argument - return super(TimedeltaIndex, cls)._generate_range(start, end, - periods, freq, - name=name, - closed=closed) - @classmethod def _simple_new(cls, values, name=None, freq=None, **kwargs): result = super(TimedeltaIndex, cls)._simple_new(values, freq, **kwargs) From f4b66c6f904dda902289f543f5fd10bed710ea53 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Mon, 15 Oct 2018 16:49:34 -0700 Subject: [PATCH 06/11] Avoid overriding _generate_range in DatetimeINdex --- pandas/core/indexes/datetimes.py | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/pandas/core/indexes/datetimes.py b/pandas/core/indexes/datetimes.py index e0219acc115b5..c9107d6509848 100644 --- a/pandas/core/indexes/datetimes.py +++ b/pandas/core/indexes/datetimes.py @@ -241,9 +241,11 @@ def __new__(cls, data=None, if data is None: # TODO: Remove this block and associated kwargs; GH#20535 - return cls._generate_range(start, end, periods, name, freq, - tz=tz, normalize=normalize, - closed=closed, ambiguous=ambiguous) + result = cls._generate_range(start, end, periods, + freq=freq, tz=tz, normalize=normalize, + closed=closed, ambiguous=ambiguous) + result.name = name + return result if not isinstance(data, (np.ndarray, Index, ABCSeries, DatetimeArrayMixin)): @@ -315,17 +317,6 @@ def __new__(cls, data=None, return subarr._deepcopy_if_needed(ref_to_data, copy) - @classmethod - @Appender(DatetimeArrayMixin._generate_range.__doc__) - def _generate_range(cls, start, end, periods, name=None, freq=None, - tz=None, normalize=False, ambiguous='raise', - closed=None): - out = super(DatetimeIndex, cls)._generate_range( - start, end, periods, freq, - tz=tz, normalize=normalize, ambiguous=ambiguous, closed=closed) - out.name = name - return out - def _convert_for_op(self, value): """ Convert value to be insertable to ndarray """ if self._has_same_tz(value): From c376799756ed0da59570bf6b347742c0e4f2f60c Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Mon, 15 Oct 2018 16:54:08 -0700 Subject: [PATCH 07/11] get kwargs out of generate_range --- pandas/core/arrays/datetimelike.py | 11 +++++++++-- pandas/core/indexes/datetimelike.py | 6 ++++++ pandas/core/indexes/period.py | 2 -- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/pandas/core/arrays/datetimelike.py b/pandas/core/arrays/datetimelike.py index 7fbda6b4c1a1f..05572021dac3d 100644 --- a/pandas/core/arrays/datetimelike.py +++ b/pandas/core/arrays/datetimelike.py @@ -331,6 +331,10 @@ def _validate_frequency(cls, index, freq, **kwargs): # Frequency validation is not meaningful for Period Array/Index return None + # DatetimeArray may pass `ambiguous`, nothing else will be accepted + # by cls._generate_range below + assert all(key == 'ambiguous' for key in kwargs) + inferred = index.inferred_freq if index.size == 0 or inferred == freq.freqstr: return None @@ -594,9 +598,12 @@ def _time_shift(self, periods, freq=None): start = self[0] + periods * self.freq end = self[-1] + periods * self.freq - attribs = self._get_attributes_dict() + + # Note: in the DatetimeTZ case, _generate_range will infer the + # appropriate timezone from `start` and `end`, so tz does not need + # to be passed explicitly. return self._generate_range(start=start, end=end, periods=None, - **attribs) + freq=self.freq) @classmethod def _add_datetimelike_methods(cls): diff --git a/pandas/core/indexes/datetimelike.py b/pandas/core/indexes/datetimelike.py index 8e919ba3599fc..eb8341f379f56 100644 --- a/pandas/core/indexes/datetimelike.py +++ b/pandas/core/indexes/datetimelike.py @@ -699,6 +699,12 @@ def astype(self, dtype, copy=True): raise TypeError(msg.format(name=type(self).__name__, dtype=dtype)) return super(DatetimeIndexOpsMixin, self).astype(dtype, copy=copy) + @Appender(DatetimeLikeArrayMixin._time_shift.__doc__) + def _time_shift(self, periods, freq=None): + result = DatetimeLikeArrayMixin._time_shift(self, periods, freq=freq) + result.name = self.name + return result + def _ensure_datetimelike_to_i8(other, to_utc=False): """ diff --git a/pandas/core/indexes/period.py b/pandas/core/indexes/period.py index 64a70b52b02a6..137b93c19c386 100644 --- a/pandas/core/indexes/period.py +++ b/pandas/core/indexes/period.py @@ -165,8 +165,6 @@ def __new__(cls, data=None, ordinal=None, freq=None, start=None, end=None, raise TypeError('__new__() got an unexpected keyword argument {}'. format(list(set(fields) - valid_field_set)[0])) - periods = dtl.validate_periods(periods) - if name is None and hasattr(data, 'name'): name = data.name From 47aebaec8736f986c719e4235ab357aa04cde383 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Mon, 15 Oct 2018 16:55:48 -0700 Subject: [PATCH 08/11] more precise conditions --- pandas/core/arrays/datetimelike.py | 5 +++-- pandas/core/arrays/period.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pandas/core/arrays/datetimelike.py b/pandas/core/arrays/datetimelike.py index 05572021dac3d..59ac98391b727 100644 --- a/pandas/core/arrays/datetimelike.py +++ b/pandas/core/arrays/datetimelike.py @@ -332,8 +332,9 @@ def _validate_frequency(cls, index, freq, **kwargs): return None # DatetimeArray may pass `ambiguous`, nothing else will be accepted - # by cls._generate_range below - assert all(key == 'ambiguous' for key in kwargs) + # by cls._generate_range below + acceptable = {'ambiguous'} if index.dtype.kind == 'M' else {} + assert all(key in acceptable for key in kwargs) inferred = index.inferred_freq if index.size == 0 or inferred == freq.freqstr: diff --git a/pandas/core/arrays/period.py b/pandas/core/arrays/period.py index 8624ddd8965e8..a4fdd6fcf49b8 100644 --- a/pandas/core/arrays/period.py +++ b/pandas/core/arrays/period.py @@ -180,7 +180,7 @@ def _generate_range(cls, start, end, periods, freq, fields): freq = Period._maybe_convert_freq(freq) field_count = len(fields) - if com.count_not_none(start, end) > 0: + if start is not None or end is not None: if field_count > 0: raise ValueError('Can either instantiate from fields ' 'or endpoints, but not both') From 44548291070f9284f55766c0837e8aa71d6fd565 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Mon, 15 Oct 2018 16:59:37 -0700 Subject: [PATCH 09/11] move _maybe_convert_timedelta back to PeriodIndex --- pandas/core/arrays/period.py | 45 +------------------------------- pandas/core/indexes/period.py | 48 +++++++++++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 46 deletions(-) diff --git a/pandas/core/arrays/period.py b/pandas/core/arrays/period.py index a4fdd6fcf49b8..ce54900898ea4 100644 --- a/pandas/core/arrays/period.py +++ b/pandas/core/arrays/period.py @@ -5,7 +5,6 @@ import numpy as np -from pandas._libs import lib from pandas._libs.tslib import NaT, iNaT from pandas._libs.tslibs.period import ( Period, IncompatibleFrequency, DIFFERENT_FREQ_INDEX, @@ -26,7 +25,7 @@ import pandas.core.common as com from pandas.tseries import frequencies -from pandas.tseries.offsets import Tick, DateOffset +from pandas.tseries.offsets import Tick from pandas.core.arrays import datetimelike as dtl from pandas.core.arrays.datetimelike import DatetimeLikeArrayMixin @@ -445,48 +444,6 @@ def _time_shift(self, n): values[self._isnan] = iNaT return self._shallow_copy(values=values) - def _maybe_convert_timedelta(self, other): - """ - Convert timedelta-like input to an integer multiple of self.freq - - Parameters - ---------- - other : timedelta, np.timedelta64, DateOffset, int, np.ndarray - - Returns - ------- - converted : int, np.ndarray[int64] - - Raises - ------ - IncompatibleFrequency : if the input cannot be written as a multiple - of self.freq. Note IncompatibleFrequency subclasses ValueError. - """ - if isinstance( - other, (timedelta, np.timedelta64, Tick, np.ndarray)): - offset = frequencies.to_offset(self.freq.rule_code) - if isinstance(offset, Tick): - # _check_timedeltalike_freq_compat will raise if incompatible - delta = self._check_timedeltalike_freq_compat(other) - return delta - elif isinstance(other, DateOffset): - freqstr = other.rule_code - base = frequencies.get_base_alias(freqstr) - if base == self.freq.rule_code: - return other.n - msg = DIFFERENT_FREQ_INDEX.format(self.freqstr, other.freqstr) - raise IncompatibleFrequency(msg) - elif lib.is_integer(other): - # integer is passed to .shift via - # _add_datetimelike_methods basically - # but ufunc may pass integer to _add_delta - return other - - # raise when input doesn't have freq - msg = "Input has different freq from {cls}(freq={freqstr})" - raise IncompatibleFrequency(msg.format(cls=type(self).__name__, - freqstr=self.freqstr)) - def _check_timedeltalike_freq_compat(self, other): """ Arithmetic operations with timedelta-like scalars or array `other` diff --git a/pandas/core/indexes/period.py b/pandas/core/indexes/period.py index 137b93c19c386..8cb4d445bfe46 100644 --- a/pandas/core/indexes/period.py +++ b/pandas/core/indexes/period.py @@ -1,5 +1,5 @@ # pylint: disable=E1101,E1103,W0232 -from datetime import datetime +from datetime import datetime, timedelta import numpy as np import warnings @@ -16,7 +16,9 @@ pandas_dtype, ensure_object) +from pandas.tseries import frequencies from pandas.tseries.frequencies import get_freq_code as _gfc +from pandas.tseries.offsets import Tick, DateOffset from pandas.core.indexes.datetimes import DatetimeIndex, Int64Index, Index from pandas.core.indexes.datetimelike import ( @@ -25,7 +27,7 @@ from pandas.core.tools.datetimes import parse_time_string from pandas._libs.lib import infer_dtype -from pandas._libs import tslib, index as libindex +from pandas._libs import lib, tslib, index as libindex from pandas._libs.tslibs.period import (Period, IncompatibleFrequency, DIFFERENT_FREQ_INDEX) from pandas._libs.tslibs import resolution, period @@ -724,6 +726,48 @@ def __setstate__(self, state): _unpickle_compat = __setstate__ + def _maybe_convert_timedelta(self, other): + """ + Convert timedelta-like input to an integer multiple of self.freq + + Parameters + ---------- + other : timedelta, np.timedelta64, DateOffset, int, np.ndarray + + Returns + ------- + converted : int, np.ndarray[int64] + + Raises + ------ + IncompatibleFrequency : if the input cannot be written as a multiple + of self.freq. Note IncompatibleFrequency subclasses ValueError. + """ + if isinstance( + other, (timedelta, np.timedelta64, Tick, np.ndarray)): + offset = frequencies.to_offset(self.freq.rule_code) + if isinstance(offset, Tick): + # _check_timedeltalike_freq_compat will raise if incompatible + delta = self._check_timedeltalike_freq_compat(other) + return delta + elif isinstance(other, DateOffset): + freqstr = other.rule_code + base = frequencies.get_base_alias(freqstr) + if base == self.freq.rule_code: + return other.n + msg = DIFFERENT_FREQ_INDEX.format(self.freqstr, other.freqstr) + raise IncompatibleFrequency(msg) + elif lib.is_integer(other): + # integer is passed to .shift via + # _add_datetimelike_methods basically + # but ufunc may pass integer to _add_delta + return other + + # raise when input doesn't have freq + msg = "Input has different freq from {cls}(freq={freqstr})" + raise IncompatibleFrequency(msg.format(cls=type(self).__name__, + freqstr=self.freqstr)) + PeriodIndex._add_comparison_ops() PeriodIndex._add_numeric_methods_disabled() From cc1e3eb3fc43227a82bd4cecbbf19435b649c426 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Mon, 15 Oct 2018 20:07:41 -0700 Subject: [PATCH 10/11] fixup missing validate_periods --- pandas/core/arrays/period.py | 1 + pandas/util/testing.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pandas/core/arrays/period.py b/pandas/core/arrays/period.py index ce54900898ea4..9bd1590eb242e 100644 --- a/pandas/core/arrays/period.py +++ b/pandas/core/arrays/period.py @@ -175,6 +175,7 @@ def _from_ordinals(cls, values, freq=None, **kwargs): @classmethod def _generate_range(cls, start, end, periods, freq, fields): + periods = dtl.validate_periods(periods) if freq is not None: freq = Period._maybe_convert_freq(freq) diff --git a/pandas/util/testing.py b/pandas/util/testing.py index 1bd9043f42634..c02cd487e4c57 100644 --- a/pandas/util/testing.py +++ b/pandas/util/testing.py @@ -2483,7 +2483,7 @@ def wrapper(*args, **kwargs): def assert_raises_regex(_exception, _regexp, _callable=None, *args, **kwargs): - """ + r""" Check that the specified Exception is raised and that the error message matches a given regular expression pattern. This may be a regular expression object or a string containing a regular expression suitable From 8d5539518754328fbc6b8b3c0a71b5563ed07249 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Tue, 16 Oct 2018 11:44:25 -0700 Subject: [PATCH 11/11] port non-central parts of #22862 --- pandas/core/accessor.py | 11 ++++++----- pandas/core/arrays/base.py | 2 +- pandas/core/indexes/base.py | 3 +-- pandas/tseries/frequencies.py | 1 + 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/pandas/core/accessor.py b/pandas/core/accessor.py index eab529584d1fb..f2f8ae58dec56 100644 --- a/pandas/core/accessor.py +++ b/pandas/core/accessor.py @@ -68,7 +68,6 @@ def _add_delegate_accessors(cls, delegate, accessors, typ, overwrite : boolean, default False overwrite the method/property in the target class if it exists """ - def _create_delegator_property(name): def _getter(self): @@ -107,9 +106,10 @@ def f(self, *args, **kwargs): def delegate_names(delegate, accessors, typ, overwrite=False): """ - Add delegated names to a class using a class decorator. This provides - an alternative usage to directly calling `_add_delegate_accessors` - below a class definition. + Add delegated names to a class using a class decorator. + + This provides an alternative usage to directly calling + `_add_delegate_accessors` below a class definition. Parameters ---------- @@ -121,7 +121,8 @@ def delegate_names(delegate, accessors, typ, overwrite=False): Returns ------- - decorator + callable + A class decorator Examples -------- diff --git a/pandas/core/arrays/base.py b/pandas/core/arrays/base.py index b745569d5bd76..c18af21078ecf 100644 --- a/pandas/core/arrays/base.py +++ b/pandas/core/arrays/base.py @@ -122,7 +122,7 @@ def _from_factorized(cls, values, original): Parameters ---------- values : ndarray - An integer ndarray with the factorized values. + An ndarray with the unique factorized values. original : ExtensionArray The original ExtensionArray that factorize was called on. diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 51c84d6e28cb4..4da9dfc06889d 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -229,7 +229,7 @@ class Index(IndexOpsMixin, PandasObject): _outer_indexer = libjoin.outer_join_indexer_object _typ = 'index' - _data = None + _data = None # type: Union[np.ndarray, ExtensionArray] _id = None name = None asi8 = None @@ -261,7 +261,6 @@ def __new__(cls, data=None, dtype=None, copy=False, name=None, return cls._simple_new(data, name) from .range import RangeIndex - # range if isinstance(data, RangeIndex): return RangeIndex(start=data, copy=copy, dtype=dtype, name=name) diff --git a/pandas/tseries/frequencies.py b/pandas/tseries/frequencies.py index d6e4824575468..22c7447768fff 100644 --- a/pandas/tseries/frequencies.py +++ b/pandas/tseries/frequencies.py @@ -233,6 +233,7 @@ def get_offset(name): def infer_freq(index, warn=True): + # type: (Union[Series, Index, PeriodArray]) -> Freq """ Infer the most likely frequency given the input index. If the frequency is uncertain, a warning will be printed.