From 5be1a0d2ae44accf588edf996bc6c165f81748e5 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Mon, 5 Nov 2018 11:40:53 -0800 Subject: [PATCH] Extraneous parts broken off from other PRS --- pandas/core/arrays/datetimelike.py | 9 ++++----- pandas/core/arrays/datetimes.py | 2 ++ pandas/core/arrays/period.py | 5 ++++- pandas/core/indexes/datetimes.py | 31 +++++++++++++++++++++--------- pandas/core/indexes/timedeltas.py | 7 +++++-- 5 files changed, 37 insertions(+), 17 deletions(-) diff --git a/pandas/core/arrays/datetimelike.py b/pandas/core/arrays/datetimelike.py index 95b997fae6b6c..58044aeb7d84c 100644 --- a/pandas/core/arrays/datetimelike.py +++ b/pandas/core/arrays/datetimelike.py @@ -12,7 +12,8 @@ from pandas._libs.tslibs.period import ( Period, DIFFERENT_FREQ_INDEX, IncompatibleFrequency) -from pandas.errors import NullFrequencyError, PerformanceWarning +from pandas.errors import ( + AbstractMethodError, NullFrequencyError, PerformanceWarning) from pandas import compat from pandas.tseries import frequencies @@ -78,12 +79,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): @@ -108,7 +107,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): """ @@ -337,7 +336,7 @@ def _sub_period(self, other): .format(cls=type(self).__name__)) def _add_offset(self, offset): - raise com.AbstractMethodError(self) + raise AbstractMethodError(self) def _add_delta(self, other): """ diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index 0258e1e6e5973..e7edd54c4177b 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -170,6 +170,8 @@ class DatetimeArrayMixin(dtl.DatetimeLikeArrayMixin): # Constructors _attributes = ["freq", "tz"] + _tz = None + _freq = None @classmethod def _simple_new(cls, values, freq=None, tz=None, **kwargs): diff --git a/pandas/core/arrays/period.py b/pandas/core/arrays/period.py index 90e7beac63427..ea7eeb7fc9f8e 100644 --- a/pandas/core/arrays/period.py +++ b/pandas/core/arrays/period.py @@ -165,7 +165,10 @@ class PeriodArray(dtl.DatetimeLikeArrayMixin, ExtensionArray): # -------------------------------------------------------------------- # Constructors - def __init__(self, values, freq=None, copy=False): + + def __init__(self, values, freq=None, dtype=None, copy=False): + freq = dtl.validate_dtype_freq(dtype, freq) + if freq is not None: freq = Period._maybe_convert_freq(freq) diff --git a/pandas/core/indexes/datetimes.py b/pandas/core/indexes/datetimes.py index 210bdabbd9dd7..bd6f0c68a9aa5 100644 --- a/pandas/core/indexes/datetimes.py +++ b/pandas/core/indexes/datetimes.py @@ -182,7 +182,6 @@ class DatetimeIndex(DatetimeArrayMixin, DatelikeOps, TimelikeOps, """ _resolution = cache_readonly(DatetimeArrayMixin._resolution.fget) - _shallow_copy = Index._shallow_copy _typ = 'datetimeindex' _join_precedence = 10 @@ -199,11 +198,15 @@ def _join_i8_wrapper(joinf, **kwargs): _engine_type = libindex.DatetimeEngine - tz = None + _tz = None _freq = None _comparables = ['name', 'freqstr', 'tz'] _attributes = ['name', 'freq', 'tz'] + # dummy attribute so that datetime.__eq__(DatetimeArray) defers + # by returning NotImplemented + timetuple = None + # define my properties & methods for delegation _bool_ops = ['is_month_start', 'is_month_end', 'is_quarter_start', 'is_quarter_end', 'is_year_start', @@ -226,6 +229,9 @@ def _join_i8_wrapper(joinf, **kwargs): _timezone = cache_readonly(DatetimeArrayMixin._timezone.fget) is_normalized = cache_readonly(DatetimeArrayMixin.is_normalized.fget) + # -------------------------------------------------------------------- + # Constructors + def __new__(cls, data=None, freq=None, start=None, end=None, periods=None, tz=None, normalize=False, closed=None, ambiguous='raise', @@ -280,7 +286,7 @@ def __new__(cls, data=None, data = data.tz_localize(tz, ambiguous=ambiguous) else: # the tz's must match - if str(tz) != str(data.tz): + if not timezones.tz_compare(tz, data.tz): msg = ('data is already tz-aware {0}, unable to ' 'set specified tz: {1}') raise TypeError(msg.format(data.tz, tz)) @@ -327,12 +333,6 @@ def __new__(cls, data=None, return subarr._deepcopy_if_needed(ref_to_data, copy) - def _convert_for_op(self, value): - """ Convert value to be insertable to ndarray """ - if self._has_same_tz(value): - return _to_m8(value) - raise ValueError('Passed item and index have different timezone') - @classmethod def _simple_new(cls, values, name=None, freq=None, tz=None, dtype=None, **kwargs): @@ -349,6 +349,8 @@ def _simple_new(cls, values, name=None, freq=None, tz=None, result._reset_identity() return result + # -------------------------------------------------------------------- + @property def _values(self): # tz-naive -> ndarray @@ -448,6 +450,12 @@ def __setstate__(self, state): raise Exception("invalid pickle state") _unpickle_compat = __setstate__ + def _convert_for_op(self, value): + """ Convert value to be insertable to ndarray """ + if self._has_same_tz(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) @@ -1104,6 +1112,9 @@ def slice_indexer(self, start=None, end=None, step=None, kind=None): else: raise + # -------------------------------------------------------------------- + # Wrapping DatetimeArray + year = wrap_field_accessor(DatetimeArrayMixin.year) month = wrap_field_accessor(DatetimeArrayMixin.month) day = wrap_field_accessor(DatetimeArrayMixin.day) @@ -1142,6 +1153,8 @@ def slice_indexer(self, start=None, end=None, step=None, kind=None): month_name = wrap_array_method(DatetimeArrayMixin.month_name, True) day_name = wrap_array_method(DatetimeArrayMixin.day_name, True) + # -------------------------------------------------------------------- + @Substitution(klass='DatetimeIndex') @Appender(_shared_docs['searchsorted']) def searchsorted(self, value, side='left', sorter=None): diff --git a/pandas/core/indexes/timedeltas.py b/pandas/core/indexes/timedeltas.py index 22ecefae8cbe2..33361c851a4c5 100644 --- a/pandas/core/indexes/timedeltas.py +++ b/pandas/core/indexes/timedeltas.py @@ -209,8 +209,6 @@ def _simple_new(cls, values, name=None, freq=None, dtype=_TD_DTYPE): result._reset_identity() return result - _shallow_copy = Index._shallow_copy - @property def _formatter_func(self): from pandas.io.formats.format import _get_format_timedelta64 @@ -243,6 +241,9 @@ def _format_native_types(self, na_rep=u'NaT', date_format=None, **kwargs): nat_rep=na_rep, justify='all').get_result() + # ------------------------------------------------------------------- + # Wrapping TimedeltaArray + days = wrap_field_accessor(TimedeltaArrayMixin.days) seconds = wrap_field_accessor(TimedeltaArrayMixin.seconds) microseconds = wrap_field_accessor(TimedeltaArrayMixin.microseconds) @@ -250,6 +251,8 @@ def _format_native_types(self, na_rep=u'NaT', date_format=None, **kwargs): total_seconds = wrap_array_method(TimedeltaArrayMixin.total_seconds, True) + # ------------------------------------------------------------------- + @Appender(_index_shared_docs['astype']) def astype(self, dtype, copy=True): dtype = pandas_dtype(dtype)