From e3267bc0c01f2f3f492e9a4c5207c489d894beb0 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Thu, 8 Nov 2018 14:09:07 -0800 Subject: [PATCH 01/14] import mixins without mixins in names --- pandas/core/indexes/datetimes.py | 76 ++++++++++++------------ pandas/core/indexes/timedeltas.py | 24 ++++---- pandas/tests/arrays/test_datetimelike.py | 32 +++++----- 3 files changed, 69 insertions(+), 63 deletions(-) diff --git a/pandas/core/indexes/datetimes.py b/pandas/core/indexes/datetimes.py index 3a2f9986760d3..47e6462ae1df9 100644 --- a/pandas/core/indexes/datetimes.py +++ b/pandas/core/indexes/datetimes.py @@ -29,7 +29,9 @@ from pandas.core.dtypes.missing import isna import pandas.core.dtypes.concat as _concat -from pandas.core.arrays.datetimes import DatetimeArrayMixin, _to_m8 +from pandas.core.arrays.datetimes import ( + DatetimeArrayMixin as DatetimeArray, + _to_m8) from pandas.core.arrays import datetimelike as dtl from pandas.core.indexes.base import Index, _index_shared_docs @@ -68,7 +70,7 @@ def _new_DatetimeIndex(cls, d): return result -class DatetimeIndex(DatetimeArrayMixin, DatelikeOps, TimelikeOps, +class DatetimeIndex(DatetimeArray, DatelikeOps, TimelikeOps, DatetimeIndexOpsMixin, Int64Index): """ Immutable ndarray of datetime64 data, represented internally as int64, and @@ -182,7 +184,7 @@ class DatetimeIndex(DatetimeArrayMixin, DatelikeOps, TimelikeOps, pandas.to_datetime : Convert argument to datetime """ - _resolution = cache_readonly(DatetimeArrayMixin._resolution.fget) + _resolution = cache_readonly(DatetimeArray._resolution.fget) _typ = 'datetimeindex' _join_precedence = 10 @@ -227,8 +229,8 @@ def _join_i8_wrapper(joinf, **kwargs): _is_numeric_dtype = False _infer_as_myclass = True - _timezone = cache_readonly(DatetimeArrayMixin._timezone.fget) - is_normalized = cache_readonly(DatetimeArrayMixin.is_normalized.fget) + _timezone = cache_readonly(DatetimeArray._timezone.fget) + is_normalized = cache_readonly(DatetimeArray.is_normalized.fget) # -------------------------------------------------------------------- # Constructors @@ -262,7 +264,7 @@ def __new__(cls, data=None, return result if not isinstance(data, (np.ndarray, Index, ABCSeries, - DatetimeArrayMixin)): + DatetimeArray)): if is_scalar(data): raise ValueError('DatetimeIndex() must be called with a ' 'collection of some kind, %s was passed' @@ -280,7 +282,7 @@ def __new__(cls, data=None, data = tools.to_datetime(data, dayfirst=dayfirst, yearfirst=yearfirst) - if isinstance(data, DatetimeArrayMixin): + if isinstance(data, DatetimeArray): if tz is None: tz = data.tz elif data.tz is None: @@ -1124,43 +1126,43 @@ def slice_indexer(self, start=None, end=None, step=None, kind=None): # -------------------------------------------------------------------- # Wrapping DatetimeArray - year = wrap_field_accessor(DatetimeArrayMixin.year) - month = wrap_field_accessor(DatetimeArrayMixin.month) - day = wrap_field_accessor(DatetimeArrayMixin.day) - hour = wrap_field_accessor(DatetimeArrayMixin.hour) - minute = wrap_field_accessor(DatetimeArrayMixin.minute) - second = wrap_field_accessor(DatetimeArrayMixin.second) - microsecond = wrap_field_accessor(DatetimeArrayMixin.microsecond) - nanosecond = wrap_field_accessor(DatetimeArrayMixin.nanosecond) - weekofyear = wrap_field_accessor(DatetimeArrayMixin.weekofyear) + year = wrap_field_accessor(DatetimeArray.year) + month = wrap_field_accessor(DatetimeArray.month) + day = wrap_field_accessor(DatetimeArray.day) + hour = wrap_field_accessor(DatetimeArray.hour) + minute = wrap_field_accessor(DatetimeArray.minute) + second = wrap_field_accessor(DatetimeArray.second) + microsecond = wrap_field_accessor(DatetimeArray.microsecond) + nanosecond = wrap_field_accessor(DatetimeArray.nanosecond) + weekofyear = wrap_field_accessor(DatetimeArray.weekofyear) week = weekofyear - dayofweek = wrap_field_accessor(DatetimeArrayMixin.dayofweek) + dayofweek = wrap_field_accessor(DatetimeArray.dayofweek) weekday = dayofweek - weekday_name = wrap_field_accessor(DatetimeArrayMixin.weekday_name) + weekday_name = wrap_field_accessor(DatetimeArray.weekday_name) - dayofyear = wrap_field_accessor(DatetimeArrayMixin.dayofyear) - quarter = wrap_field_accessor(DatetimeArrayMixin.quarter) - days_in_month = wrap_field_accessor(DatetimeArrayMixin.days_in_month) + dayofyear = wrap_field_accessor(DatetimeArray.dayofyear) + quarter = wrap_field_accessor(DatetimeArray.quarter) + days_in_month = wrap_field_accessor(DatetimeArray.days_in_month) daysinmonth = days_in_month - is_month_start = wrap_field_accessor(DatetimeArrayMixin.is_month_start) - is_month_end = wrap_field_accessor(DatetimeArrayMixin.is_month_end) - is_quarter_start = wrap_field_accessor(DatetimeArrayMixin.is_quarter_start) - is_quarter_end = wrap_field_accessor(DatetimeArrayMixin.is_quarter_end) - is_year_start = wrap_field_accessor(DatetimeArrayMixin.is_year_start) - is_year_end = wrap_field_accessor(DatetimeArrayMixin.is_year_end) - is_leap_year = wrap_field_accessor(DatetimeArrayMixin.is_leap_year) - - tz_localize = wrap_array_method(DatetimeArrayMixin.tz_localize, True) - tz_convert = wrap_array_method(DatetimeArrayMixin.tz_convert, True) - to_perioddelta = wrap_array_method(DatetimeArrayMixin.to_perioddelta, + is_month_start = wrap_field_accessor(DatetimeArray.is_month_start) + is_month_end = wrap_field_accessor(DatetimeArray.is_month_end) + is_quarter_start = wrap_field_accessor(DatetimeArray.is_quarter_start) + is_quarter_end = wrap_field_accessor(DatetimeArray.is_quarter_end) + is_year_start = wrap_field_accessor(DatetimeArray.is_year_start) + is_year_end = wrap_field_accessor(DatetimeArray.is_year_end) + is_leap_year = wrap_field_accessor(DatetimeArray.is_leap_year) + + tz_localize = wrap_array_method(DatetimeArray.tz_localize, True) + tz_convert = wrap_array_method(DatetimeArray.tz_convert, True) + to_perioddelta = wrap_array_method(DatetimeArray.to_perioddelta, False) - to_period = wrap_array_method(DatetimeArrayMixin.to_period, True) - normalize = wrap_array_method(DatetimeArrayMixin.normalize, True) - to_julian_date = wrap_array_method(DatetimeArrayMixin.to_julian_date, + to_period = wrap_array_method(DatetimeArray.to_period, True) + normalize = wrap_array_method(DatetimeArray.normalize, True) + to_julian_date = wrap_array_method(DatetimeArray.to_julian_date, False) - month_name = wrap_array_method(DatetimeArrayMixin.month_name, True) - day_name = wrap_array_method(DatetimeArrayMixin.day_name, True) + month_name = wrap_array_method(DatetimeArray.month_name, True) + day_name = wrap_array_method(DatetimeArray.day_name, True) # -------------------------------------------------------------------- diff --git a/pandas/core/indexes/timedeltas.py b/pandas/core/indexes/timedeltas.py index 5b077a6984114..1ed5faae5e2a4 100644 --- a/pandas/core/indexes/timedeltas.py +++ b/pandas/core/indexes/timedeltas.py @@ -2,6 +2,9 @@ from datetime import datetime import numpy as np + +import pandas.compat as compat + from pandas.core.dtypes.common import ( _TD_DTYPE, is_integer, @@ -12,22 +15,22 @@ is_timedelta64_ns_dtype, pandas_dtype, ensure_int64) +import pandas.core.dtypes.concat as _concat from pandas.core.dtypes.missing import isna from pandas.core.arrays.timedeltas import ( - TimedeltaArrayMixin, _is_convertible_to_td, _to_m8) + TimedeltaArrayMixin as TimedeltaArray, + _is_convertible_to_td, _to_m8) from pandas.core.arrays import datetimelike as dtl from pandas.core.indexes.base import Index from pandas.core.indexes.numeric import Int64Index -import pandas.compat as compat from pandas.tseries.frequencies import to_offset from pandas.core.base import _shared_docs from pandas.core.indexes.base import _index_shared_docs import pandas.core.common as com from pandas.core.ops import get_op_result_name -import pandas.core.dtypes.concat as _concat from pandas.util._decorators import Appender, Substitution from pandas.core.indexes.datetimelike import ( TimelikeOps, DatetimeIndexOpsMixin, wrap_arithmetic_op, @@ -39,7 +42,7 @@ from pandas._libs.tslibs.timedeltas import array_to_timedelta64 -class TimedeltaIndex(TimedeltaArrayMixin, DatetimeIndexOpsMixin, +class TimedeltaIndex(TimedeltaArray, DatetimeIndexOpsMixin, TimelikeOps, Int64Index): """ Immutable ndarray of timedelta64 data, represented internally as int64, and @@ -232,8 +235,7 @@ def _maybe_update_attributes(self, attrs): return attrs def _evaluate_with_timedelta_like(self, other, op): - result = TimedeltaArrayMixin._evaluate_with_timedelta_like(self, other, - op) + result = TimedeltaArray._evaluate_with_timedelta_like(self, other, op) return wrap_arithmetic_op(self, other, result) def _format_native_types(self, na_rep=u'NaT', date_format=None, **kwargs): @@ -245,12 +247,12 @@ def _format_native_types(self, na_rep=u'NaT', date_format=None, **kwargs): # ------------------------------------------------------------------- # Wrapping TimedeltaArray - days = wrap_field_accessor(TimedeltaArrayMixin.days) - seconds = wrap_field_accessor(TimedeltaArrayMixin.seconds) - microseconds = wrap_field_accessor(TimedeltaArrayMixin.microseconds) - nanoseconds = wrap_field_accessor(TimedeltaArrayMixin.nanoseconds) + days = wrap_field_accessor(TimedeltaArray.days) + seconds = wrap_field_accessor(TimedeltaArray.seconds) + microseconds = wrap_field_accessor(TimedeltaArray.microseconds) + nanoseconds = wrap_field_accessor(TimedeltaArray.nanoseconds) - total_seconds = wrap_array_method(TimedeltaArrayMixin.total_seconds, True) + total_seconds = wrap_array_method(TimedeltaArray.total_seconds, True) # ------------------------------------------------------------------- diff --git a/pandas/tests/arrays/test_datetimelike.py b/pandas/tests/arrays/test_datetimelike.py index 3fd03a351de7c..99979acdcf9a4 100644 --- a/pandas/tests/arrays/test_datetimelike.py +++ b/pandas/tests/arrays/test_datetimelike.py @@ -4,7 +4,9 @@ import pandas as pd from pandas.core.arrays import ( - DatetimeArrayMixin, PeriodArray, TimedeltaArrayMixin) + DatetimeArrayMixin as DatetimeArray, + PeriodArray, + TimedeltaArrayMixin as TimedeltaArray) import pandas.util.testing as tm @@ -60,7 +62,7 @@ class TestDatetimeArray(object): def test_from_dti(self, tz_naive_fixture): tz = tz_naive_fixture dti = pd.date_range('2016-01-01', periods=3, tz=tz) - arr = DatetimeArrayMixin(dti) + arr = DatetimeArray(dti) assert list(dti) == list(arr) # Check that Index.__new__ knows what to do with DatetimeArray @@ -71,7 +73,7 @@ def test_from_dti(self, tz_naive_fixture): def test_astype_object(self, tz_naive_fixture): tz = tz_naive_fixture dti = pd.date_range('2016-01-01', periods=3, tz=tz) - arr = DatetimeArrayMixin(dti) + arr = DatetimeArray(dti) asobj = arr.astype('O') assert isinstance(asobj, np.ndarray) assert asobj.dtype == 'O' @@ -81,11 +83,11 @@ def test_astype_object(self, tz_naive_fixture): def test_to_perioddelta(self, datetime_index, freqstr): # GH#23113 dti = datetime_index - arr = DatetimeArrayMixin(dti) + arr = DatetimeArray(dti) expected = dti.to_perioddelta(freq=freqstr) result = arr.to_perioddelta(freq=freqstr) - assert isinstance(result, TimedeltaArrayMixin) + assert isinstance(result, TimedeltaArray) # placeholder until these become actual EA subclasses and we can use # an EA-specific tm.assert_ function @@ -94,7 +96,7 @@ def test_to_perioddelta(self, datetime_index, freqstr): @pytest.mark.parametrize('freqstr', ['D', 'B', 'W', 'M', 'Q', 'Y']) def test_to_period(self, datetime_index, freqstr): dti = datetime_index - arr = DatetimeArrayMixin(dti) + arr = DatetimeArray(dti) expected = dti.to_period(freq=freqstr) result = arr.to_period(freq=freqstr) @@ -108,7 +110,7 @@ def test_to_period(self, datetime_index, freqstr): def test_bool_properties(self, datetime_index, propname): # in this case _bool_ops is just `is_leap_year` dti = datetime_index - arr = DatetimeArrayMixin(dti) + arr = DatetimeArray(dti) assert dti.freq == arr.freq result = getattr(arr, propname) @@ -119,7 +121,7 @@ def test_bool_properties(self, datetime_index, propname): @pytest.mark.parametrize('propname', pd.DatetimeIndex._field_ops) def test_int_properties(self, datetime_index, propname): dti = datetime_index - arr = DatetimeArrayMixin(dti) + arr = DatetimeArray(dti) result = getattr(arr, propname) expected = np.array(getattr(dti, propname), dtype=result.dtype) @@ -130,7 +132,7 @@ def test_int_properties(self, datetime_index, propname): class TestTimedeltaArray(object): def test_from_tdi(self): tdi = pd.TimedeltaIndex(['1 Day', '3 Hours']) - arr = TimedeltaArrayMixin(tdi) + arr = TimedeltaArray(tdi) assert list(arr) == list(tdi) # Check that Index.__new__ knows what to do with TimedeltaArray @@ -140,7 +142,7 @@ def test_from_tdi(self): def test_astype_object(self): tdi = pd.TimedeltaIndex(['1 Day', '3 Hours']) - arr = TimedeltaArrayMixin(tdi) + arr = TimedeltaArray(tdi) asobj = arr.astype('O') assert isinstance(asobj, np.ndarray) assert asobj.dtype == 'O' @@ -148,7 +150,7 @@ def test_astype_object(self): def test_to_pytimedelta(self, timedelta_index): tdi = timedelta_index - arr = TimedeltaArrayMixin(tdi) + arr = TimedeltaArray(tdi) expected = tdi.to_pytimedelta() result = arr.to_pytimedelta() @@ -157,7 +159,7 @@ def test_to_pytimedelta(self, timedelta_index): def test_total_seconds(self, timedelta_index): tdi = timedelta_index - arr = TimedeltaArrayMixin(tdi) + arr = TimedeltaArray(tdi) expected = tdi.total_seconds() result = arr.total_seconds() @@ -167,7 +169,7 @@ def test_total_seconds(self, timedelta_index): @pytest.mark.parametrize('propname', pd.TimedeltaIndex._field_ops) def test_int_properties(self, timedelta_index, propname): tdi = timedelta_index - arr = TimedeltaArrayMixin(tdi) + arr = TimedeltaArray(tdi) result = getattr(arr, propname) expected = np.array(getattr(tdi, propname), dtype=result.dtype) @@ -200,9 +202,9 @@ def test_to_timestamp(self, how, period_index): pi = period_index arr = PeriodArray(pi) - expected = DatetimeArrayMixin(pi.to_timestamp(how=how)) + expected = DatetimeArray(pi.to_timestamp(how=how)) result = arr.to_timestamp(how=how) - assert isinstance(result, DatetimeArrayMixin) + assert isinstance(result, DatetimeArray) # placeholder until these become actual EA subclasses and we can use # an EA-specific tm.assert_ function From d4bde651dfe10d72b8be4d7e532df965854bd933 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Thu, 8 Nov 2018 14:15:29 -0800 Subject: [PATCH 02/14] isort timedeltas, datetimelike, datetime index files --- pandas/core/indexes/datetimelike.py | 44 ++++++++------------- pandas/core/indexes/datetimes.py | 60 +++++++++++------------------ pandas/core/indexes/timedeltas.py | 42 ++++++++------------ setup.cfg | 3 -- 4 files changed, 55 insertions(+), 94 deletions(-) diff --git a/pandas/core/indexes/datetimelike.py b/pandas/core/indexes/datetimelike.py index 59429488a7c2f..1d9d3b1d3bd16 100644 --- a/pandas/core/indexes/datetimelike.py +++ b/pandas/core/indexes/datetimelike.py @@ -4,44 +4,32 @@ """ import warnings -from pandas import compat -from pandas.compat.numpy import function as nv -from pandas.core.tools.timedeltas import to_timedelta - import numpy as np -from pandas._libs import lib, iNaT, NaT -from pandas._libs.tslibs.timestamps import round_nsint64, RoundTo +from pandas._libs import NaT, iNaT, lib +from pandas._libs.tslibs.timestamps import RoundTo, round_nsint64 +import pandas.compat as compat +from pandas.compat.numpy import function as nv +from pandas.util._decorators import Appender, cache_readonly from pandas.core.dtypes.common import ( - ensure_int64, - is_dtype_equal, - is_float, - is_integer, - is_list_like, - is_scalar, - is_bool_dtype, - is_period_dtype, - is_categorical_dtype, - is_datetime_or_timedelta_dtype, - is_float_dtype, - is_integer_dtype, - is_object_dtype, - is_string_dtype) -from pandas.core.dtypes.generic import ( - ABCIndex, ABCSeries, ABCIndexClass) + ensure_int64, is_bool_dtype, is_categorical_dtype, + is_datetime_or_timedelta_dtype, is_dtype_equal, is_float, is_float_dtype, + is_integer, is_integer_dtype, is_list_like, is_object_dtype, + is_period_dtype, is_scalar, is_string_dtype) +import pandas.core.dtypes.concat as _concat +from pandas.core.dtypes.generic import ABCIndex, ABCIndexClass, ABCSeries from pandas.core.dtypes.missing import isna -from pandas.core import common as com, algorithms, ops - -import pandas.io.formats.printing as printing +from pandas.core import algorithms, common as com, ops from pandas.core.arrays import PeriodArray from pandas.core.arrays.datetimelike import DatetimeLikeArrayMixin +import pandas.core.indexes.base as ibase from pandas.core.indexes.base import Index, _index_shared_docs -from pandas.util._decorators import Appender, cache_readonly -import pandas.core.dtypes.concat as _concat +from pandas.core.tools.timedeltas import to_timedelta + +import pandas.io.formats.printing as printing -import pandas.core.indexes.base as ibase _index_doc_kwargs = dict(ibase._index_doc_kwargs) diff --git a/pandas/core/indexes/datetimes.py b/pandas/core/indexes/datetimes.py index 47e6462ae1df9..9f31aa802ac41 100644 --- a/pandas/core/indexes/datetimes.py +++ b/pandas/core/indexes/datetimes.py @@ -1,59 +1,45 @@ # pylint: disable=E1101 from __future__ import division + +from datetime import datetime, time, timedelta import operator import warnings -from datetime import time, datetime, timedelta import numpy as np from pytz import utc -from pandas.core.base import _shared_docs +from pandas._libs import ( + Timestamp, index as libindex, join as libjoin, lib, tslib as libts) +from pandas._libs.tslibs import ( + ccalendar, conversion, fields, parsing, timezones) +import pandas.compat as compat +from pandas.util._decorators import Appender, Substitution, cache_readonly from pandas.core.dtypes.common import ( - _INT64_DTYPE, - _NS_DTYPE, - is_datetime64_dtype, - is_datetimetz, - is_dtype_equal, - is_integer, - is_float, - is_integer_dtype, - is_datetime64_ns_dtype, - is_period_dtype, - is_string_like, - is_list_like, - is_scalar, - pandas_dtype, - ensure_int64) + _INT64_DTYPE, _NS_DTYPE, ensure_int64, is_datetime64_dtype, + is_datetime64_ns_dtype, is_datetimetz, is_dtype_equal, is_float, + is_integer, is_integer_dtype, is_list_like, is_period_dtype, is_scalar, + is_string_like, pandas_dtype) +import pandas.core.dtypes.concat as _concat from pandas.core.dtypes.generic import ABCSeries from pandas.core.dtypes.missing import isna -import pandas.core.dtypes.concat as _concat -from pandas.core.arrays.datetimes import ( - DatetimeArrayMixin as DatetimeArray, - _to_m8) from pandas.core.arrays import datetimelike as dtl - +from pandas.core.arrays.datetimes import ( + DatetimeArrayMixin as DatetimeArray, _to_m8) +from pandas.core.base import _shared_docs +import pandas.core.common as com from pandas.core.indexes.base import Index, _index_shared_docs +from pandas.core.indexes.datetimelike import ( + DatelikeOps, DatetimeIndexOpsMixin, TimelikeOps, wrap_array_method, + wrap_field_accessor) from pandas.core.indexes.numeric import Int64Index from pandas.core.ops import get_op_result_name -import pandas.compat as compat -from pandas.tseries.frequencies import to_offset, Resolution -from pandas.core.indexes.datetimelike import ( - DatelikeOps, TimelikeOps, DatetimeIndexOpsMixin, - wrap_field_accessor, wrap_array_method) -from pandas.tseries.offsets import ( - CDay, prefix_mapping) - -from pandas.util._decorators import Appender, cache_readonly, Substitution -import pandas.core.common as com -import pandas.tseries.offsets as offsets import pandas.core.tools.datetimes as tools -from pandas._libs import (lib, index as libindex, tslib as libts, - join as libjoin, Timestamp) -from pandas._libs.tslibs import (timezones, conversion, fields, parsing, - ccalendar) +from pandas.tseries import offsets +from pandas.tseries.frequencies import Resolution, to_offset +from pandas.tseries.offsets import CDay, prefix_mapping def _new_DatetimeIndex(cls, d): diff --git a/pandas/core/indexes/timedeltas.py b/pandas/core/indexes/timedeltas.py index 1ed5faae5e2a4..45848cb78afac 100644 --- a/pandas/core/indexes/timedeltas.py +++ b/pandas/core/indexes/timedeltas.py @@ -3,43 +3,33 @@ import numpy as np +from pandas._libs import ( + NaT, Timedelta, index as libindex, join as libjoin, lib) +from pandas._libs.tslibs.timedeltas import array_to_timedelta64 import pandas.compat as compat +from pandas.util._decorators import Appender, Substitution from pandas.core.dtypes.common import ( - _TD_DTYPE, - is_integer, - is_float, - is_list_like, - is_scalar, - is_timedelta64_dtype, - is_timedelta64_ns_dtype, - pandas_dtype, - ensure_int64) + _TD_DTYPE, ensure_int64, is_float, is_integer, is_list_like, is_scalar, + is_timedelta64_dtype, is_timedelta64_ns_dtype, pandas_dtype) import pandas.core.dtypes.concat as _concat from pandas.core.dtypes.missing import isna -from pandas.core.arrays.timedeltas import ( - TimedeltaArrayMixin as TimedeltaArray, - _is_convertible_to_td, _to_m8) from pandas.core.arrays import datetimelike as dtl - -from pandas.core.indexes.base import Index -from pandas.core.indexes.numeric import Int64Index - -from pandas.tseries.frequencies import to_offset +from pandas.core.arrays.timedeltas import ( + TimedeltaArrayMixin as TimedeltaArray, _is_convertible_to_td, _to_m8) from pandas.core.base import _shared_docs -from pandas.core.indexes.base import _index_shared_docs import pandas.core.common as com -from pandas.core.ops import get_op_result_name -from pandas.util._decorators import Appender, Substitution +from pandas.core.indexes.base import Index, _index_shared_docs from pandas.core.indexes.datetimelike import ( - TimelikeOps, DatetimeIndexOpsMixin, wrap_arithmetic_op, - wrap_array_method, wrap_field_accessor) + DatetimeIndexOpsMixin, TimelikeOps, wrap_arithmetic_op, wrap_array_method, + wrap_field_accessor) +from pandas.core.indexes.numeric import Int64Index +from pandas.core.ops import get_op_result_name from pandas.core.tools.timedeltas import ( - to_timedelta, _coerce_scalar_to_timedelta_type) -from pandas._libs import (lib, index as libindex, - join as libjoin, Timedelta, NaT) -from pandas._libs.tslibs.timedeltas import array_to_timedelta64 + _coerce_scalar_to_timedelta_type, to_timedelta) + +from pandas.tseries.frequencies import to_offset class TimedeltaIndex(TimedeltaArray, DatetimeIndexOpsMixin, diff --git a/setup.cfg b/setup.cfg index 17b88d084ebf6..874b0ea23b2ba 100644 --- a/setup.cfg +++ b/setup.cfg @@ -114,9 +114,6 @@ skip= pandas/core/indexes/numeric.py, pandas/core/indexes/interval.py, pandas/core/indexes/multi.py, - pandas/core/indexes/timedeltas.py, - pandas/core/indexes/datetimelike.py, - pandas/core/indexes/datetimes.py, pandas/core/indexes/base.py, pandas/core/indexes/accessors.py, pandas/core/indexes/period.py, From a2754c1fb0fa054ed72577ea40cfe69127abd3fe Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Thu, 8 Nov 2018 14:19:45 -0800 Subject: [PATCH 03/14] Section header --- pandas/core/arrays/period.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pandas/core/arrays/period.py b/pandas/core/arrays/period.py index 5a75f2706b218..d71a0988a47ab 100644 --- a/pandas/core/arrays/period.py +++ b/pandas/core/arrays/period.py @@ -330,6 +330,9 @@ def start_time(self): def end_time(self): return self.to_timestamp(how='end') + # -------------------------------------------------------------------- + # Array-like / EA-Interface Methods + def __repr__(self): return '<{}>\n{}\nLength: {}, dtype: {}'.format( self.__class__.__name__, @@ -459,6 +462,8 @@ def value_counts(self, dropna=False): name=result.index.name) return Series(result.values, index=index, name=result.name) + # -------------------------------------------------------------------- + def shift(self, periods=1): """ Shift values by desired number. @@ -613,6 +618,7 @@ def to_timestamp(self, freq=None, how='start'): # ------------------------------------------------------------------ # Formatting + def _format_native_types(self, na_rep=u'NaT', date_format=None, **kwargs): """ actually format my specific types """ # TODO(DatetimeArray): remove From e81f5d6bff3baaadec3782a5a1354dcf6710b2b3 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Thu, 8 Nov 2018 15:38:29 -0800 Subject: [PATCH 04/14] implement repr, with tests, truncate long reprs for periodarray, rearrange things that got shuffled in rebasing --- pandas/core/arrays/datetimelike.py | 31 ++++++- pandas/core/arrays/datetimes.py | 2 +- pandas/core/arrays/period.py | 108 +++++++++++-------------- pandas/core/arrays/timedeltas.py | 3 + pandas/core/indexes/datetimes.py | 11 ++- pandas/core/indexes/period.py | 15 ++-- pandas/core/indexes/timedeltas.py | 3 + pandas/tests/arrays/test_datetimes.py | 34 ++++++++ pandas/tests/arrays/test_period.py | 22 ++++- pandas/tests/arrays/test_timedeltas.py | 34 ++++++++ 10 files changed, 185 insertions(+), 78 deletions(-) create mode 100644 pandas/tests/arrays/test_datetimes.py create mode 100644 pandas/tests/arrays/test_timedeltas.py diff --git a/pandas/core/arrays/datetimelike.py b/pandas/core/arrays/datetimelike.py index 7f1c86938a354..8e08e9334c49f 100644 --- a/pandas/core/arrays/datetimelike.py +++ b/pandas/core/arrays/datetimelike.py @@ -127,10 +127,14 @@ def values(self): @property def asi8(self): # do not cache or you'll create a memory leak - return self.values.view('i8') + return self._data.view('i8') - # ------------------------------------------------------------------ - # Array-like Methods + # ---------------------------------------------------------------- + # Array-Like / EA-Interface Methods + + @property + def nbytes(self): + return self._data.nbytes @property def shape(self): @@ -197,6 +201,27 @@ def astype(self, dtype, copy=True): return self._box_values(self.asi8) return super(DatetimeLikeArrayMixin, self).astype(dtype, copy) + # ------------------------------------------------------------------ + # Formatting + + def __repr__(self): + if len(self) <= 6: + # TODO: 6 is an arbitrary cutoff; make configurable? + items = [str(s) for s in self] + else: + items = ([str(s) for s in self[:3]] + + ['...'] + + [str(s) for s in self[-3:]]) + + result = '<{cls}>\n{items}\nLength: {length}, dtype: {dtype}'.format( + cls=type(self).__name__, items=items, + length=len(self), dtype=self.dtype) + + if not is_period_dtype(self): + result += ', freq: {freqstr}'.format(freqstr=self.freqstr) + + return result + # ------------------------------------------------------------------ # Null Handling diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index e7edd54c4177b..375180cf4ef7d 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -374,7 +374,7 @@ def _resolution(self): return libresolution.resolution(self.asi8, self.tz) # ---------------------------------------------------------------- - # Array-like Methods + # Array-Like / EA-Interface Methods def __iter__(self): """ diff --git a/pandas/core/arrays/period.py b/pandas/core/arrays/period.py index d71a0988a47ab..9f64cff0dfe36 100644 --- a/pandas/core/arrays/period.py +++ b/pandas/core/arrays/period.py @@ -272,10 +272,6 @@ def _concat_same_type(cls, to_concat): # -------------------------------------------------------------------- # Data / Attributes - @property - def nbytes(self): - # TODO(DatetimeArray): remove - return self._data.nbytes @cache_readonly def dtype(self): @@ -286,10 +282,6 @@ def _ndarray_values(self): # Ordinals return self._data - @property - def asi8(self): - return self._data - @property def freq(self): """Return the frequency object for this PeriodArray.""" @@ -330,17 +322,50 @@ def start_time(self): def end_time(self): return self.to_timestamp(how='end') + def to_timestamp(self, freq=None, how='start'): + """ + Cast to DatetimeArray/Index + + Parameters + ---------- + freq : string or DateOffset, optional + Target frequency. The default is 'D' for week or longer, + 'S' otherwise + how : {'s', 'e', 'start', 'end'} + + Returns + ------- + DatetimeArray/Index + """ + from pandas.core.arrays import DatetimeArrayMixin + + how = libperiod._validate_end_alias(how) + + end = how == 'E' + if end: + if freq == 'B': + # roll forward to ensure we land on B date + adjust = Timedelta(1, 'D') - Timedelta(1, 'ns') + return self.to_timestamp(how='start') + adjust + else: + adjust = Timedelta(1, 'ns') + return (self + self.freq).to_timestamp(how='start') - adjust + + if freq is None: + base, mult = frequencies.get_freq_code(self.freq) + freq = frequencies.get_to_timestamp_base(base) + else: + freq = Period._maybe_convert_freq(freq) + + base, mult = frequencies.get_freq_code(freq) + new_data = self.asfreq(freq, how=how) + + new_data = libperiod.periodarr_to_dt64arr(new_data.asi8, base) + return DatetimeArrayMixin(new_data, freq='infer') + # -------------------------------------------------------------------- # Array-like / EA-Interface Methods - def __repr__(self): - return '<{}>\n{}\nLength: {}, dtype: {}'.format( - self.__class__.__name__, - [str(s) for s in self], - len(self), - self.dtype - ) - def __setitem__( self, key, # type: Union[int, Sequence[int], Sequence[bool]] @@ -575,47 +600,6 @@ def asfreq(self, freq=None, how='E'): return type(self)(new_data, freq=freq) - def to_timestamp(self, freq=None, how='start'): - """ - Cast to DatetimeArray/Index - - Parameters - ---------- - freq : string or DateOffset, optional - Target frequency. The default is 'D' for week or longer, - 'S' otherwise - how : {'s', 'e', 'start', 'end'} - - Returns - ------- - DatetimeArray/Index - """ - from pandas.core.arrays import DatetimeArrayMixin - - how = libperiod._validate_end_alias(how) - - end = how == 'E' - if end: - if freq == 'B': - # roll forward to ensure we land on B date - adjust = Timedelta(1, 'D') - Timedelta(1, 'ns') - return self.to_timestamp(how='start') + adjust - else: - adjust = Timedelta(1, 'ns') - return (self + self.freq).to_timestamp(how='start') - adjust - - if freq is None: - base, mult = frequencies.get_freq_code(self.freq) - freq = frequencies.get_to_timestamp_base(base) - else: - freq = Period._maybe_convert_freq(freq) - - base, mult = frequencies.get_freq_code(freq) - new_data = self.asfreq(freq, how=how) - - new_data = libperiod.periodarr_to_dt64arr(new_data.asi8, base) - return DatetimeArrayMixin(new_data, freq='infer') - # ------------------------------------------------------------------ # Formatting @@ -639,9 +623,13 @@ def _format_native_types(self, na_rep=u'NaT', date_format=None, **kwargs): values = np.array([formatter(dt) for dt in values]) return values + # Delegation... + def strftime(self, date_format): + return self._format_native_types(date_format=date_format) + def repeat(self, repeats, *args, **kwargs): """ - Repeat elements of a Categorical. + Repeat elements of a PeriodArray. See also -------- @@ -652,10 +640,6 @@ def repeat(self, repeats, *args, **kwargs): values = self._data.repeat(repeats) return type(self)(values, self.freq) - # Delegation... - def strftime(self, date_format): - return self._format_native_types(date_format=date_format) - def astype(self, dtype, copy=True): # TODO: Figure out something better here... # We have DatetimeLikeArrayMixin -> diff --git a/pandas/core/arrays/timedeltas.py b/pandas/core/arrays/timedeltas.py index 9653121879c0d..bed09a45a10ae 100644 --- a/pandas/core/arrays/timedeltas.py +++ b/pandas/core/arrays/timedeltas.py @@ -180,6 +180,9 @@ def _generate_range(cls, start, end, periods, freq, closed=None): return cls._simple_new(index, freq=freq) + # ---------------------------------------------------------------- + # Array-Like / EA-Interface Methods + # ---------------------------------------------------------------- # Arithmetic Methods diff --git a/pandas/core/indexes/datetimes.py b/pandas/core/indexes/datetimes.py index 9f31aa802ac41..dce6f3cbf876e 100644 --- a/pandas/core/indexes/datetimes.py +++ b/pandas/core/indexes/datetimes.py @@ -170,8 +170,6 @@ class DatetimeIndex(DatetimeArray, DatelikeOps, TimelikeOps, pandas.to_datetime : Convert argument to datetime """ - _resolution = cache_readonly(DatetimeArray._resolution.fget) - _typ = 'datetimeindex' _join_precedence = 10 @@ -215,8 +213,6 @@ def _join_i8_wrapper(joinf, **kwargs): _is_numeric_dtype = False _infer_as_myclass = True - _timezone = cache_readonly(DatetimeArray._timezone.fget) - is_normalized = cache_readonly(DatetimeArray.is_normalized.fget) # -------------------------------------------------------------------- # Constructors @@ -1112,6 +1108,13 @@ def slice_indexer(self, start=None, end=None, step=None, kind=None): # -------------------------------------------------------------------- # Wrapping DatetimeArray + # override DatetimeLikeArrayMixin.__repr__ + __repr__ = Index.__repr__ + + _timezone = cache_readonly(DatetimeArray._timezone.fget) + is_normalized = cache_readonly(DatetimeArray.is_normalized.fget) + _resolution = cache_readonly(DatetimeArray._resolution.fget) + year = wrap_field_accessor(DatetimeArray.year) month = wrap_field_accessor(DatetimeArray.month) day = wrap_field_accessor(DatetimeArray.day) diff --git a/pandas/core/indexes/period.py b/pandas/core/indexes/period.py index 128068959ebd3..3a867e15b5339 100644 --- a/pandas/core/indexes/period.py +++ b/pandas/core/indexes/period.py @@ -256,8 +256,15 @@ def _simple_new(cls, values, name=None, freq=None, **kwargs): result._reset_identity() return result + # ------------------------------------------------------------------------ + # Wrapping PeriodArray + + # override DatetimeLikeArrayMixin.__repr__ + __repr__ = Index.__repr__ + # ------------------------------------------------------------------------ # Data + @property def _ndarray_values(self): return self._data._ndarray_values @@ -361,13 +368,6 @@ def asfreq(self, freq=None, how='E'): result = self._data.asfreq(freq=freq, how=how) return self._simple_new(result, name=self.name) - def _nat_new(self, box=True): - # TODO(DatetimeArray): remove this - result = self._data._nat_new(box=box) - if box: - result = self._simple_new(result, name=self.name) - return result - def to_timestamp(self, freq=None, how='start'): from pandas import DatetimeIndex result = self._data.to_timestamp(freq=freq, how=how) @@ -425,6 +425,7 @@ def _maybe_convert_timedelta(self, other): # ------------------------------------------------------------------------ # Indexing + @cache_readonly def _engine(self): return self._engine_type(lambda: self, len(self)) diff --git a/pandas/core/indexes/timedeltas.py b/pandas/core/indexes/timedeltas.py index 45848cb78afac..66e96269b3e88 100644 --- a/pandas/core/indexes/timedeltas.py +++ b/pandas/core/indexes/timedeltas.py @@ -237,6 +237,9 @@ def _format_native_types(self, na_rep=u'NaT', date_format=None, **kwargs): # ------------------------------------------------------------------- # Wrapping TimedeltaArray + # override DatetimeLikeArrayMixin.__repr__ + __repr__ = Index.__repr__ + days = wrap_field_accessor(TimedeltaArray.days) seconds = wrap_field_accessor(TimedeltaArray.seconds) microseconds = wrap_field_accessor(TimedeltaArray.microseconds) diff --git a/pandas/tests/arrays/test_datetimes.py b/pandas/tests/arrays/test_datetimes.py new file mode 100644 index 0000000000000..4da0eccaeaf29 --- /dev/null +++ b/pandas/tests/arrays/test_datetimes.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- + +import pandas as pd +from pandas.core.arrays import DatetimeArrayMixin as DatetimeArray + + +class TestDatetimeArray(object): + def test_repr(self): + dti = pd.date_range('1994-07-01', periods=9, freq='W', tz='US/Central') + arr = DatetimeArray(dti) + + # non-truncated + expected = ( + "\n" + "['1994-07-03 00:00:00-05:00', '1994-07-10 00:00:00-05:00']\n" + "Length: 2, dtype: datetime64[ns, US/Central], freq: W-SUN") + result = repr(arr[:2]) + assert result == expected + + # truncated + expected = ( + "\n" + "[" + "'1994-07-03 00:00:00-05:00', " + "'1994-07-10 00:00:00-05:00', " + "'1994-07-17 00:00:00-05:00', " + "'...', " + "'1994-08-14 00:00:00-05:00', " + "'1994-08-21 00:00:00-05:00', " + "'1994-08-28 00:00:00-05:00'" + "]\n" + "Length: 9, dtype: datetime64[ns, US/Central], freq: W-SUN") + result = repr(arr) + assert result == expected diff --git a/pandas/tests/arrays/test_period.py b/pandas/tests/arrays/test_period.py index 0125729048cdd..be75de0a953dd 100644 --- a/pandas/tests/arrays/test_period.py +++ b/pandas/tests/arrays/test_period.py @@ -190,8 +190,28 @@ def test_setitem_raises_type(): # ---------------------------------------------------------------------------- # Ops -def tet_sub_period(): +def test_sub_period(): arr = period_array(['2000', '2001'], freq='D') other = pd.Period("2000", freq="M") with tm.assert_raises_regex(IncompatibleFrequency, "freq"): arr - other + + +# ---------------------------------------------------------------------------- +# Unsorted + +def test_repr(): + arr = period_array(['2000', '2001'], freq='D') + + expected = ("\n" + "['2000-01-01', '2001-01-01']\n" + "Length: 2, dtype: period[D]") + assert repr(arr) == expected + + # long array shows ends + pi = pd.period_range('2001', periods=1000, freq='Y') + arr = period_array(pi) + + expected = ("\n" + "['2001', '2002', '2003', '...', '2998', '2999', '3000']\n" + "Length: 1000, dtype: period[A-DEC]") diff --git a/pandas/tests/arrays/test_timedeltas.py b/pandas/tests/arrays/test_timedeltas.py new file mode 100644 index 0000000000000..8ac9046570b51 --- /dev/null +++ b/pandas/tests/arrays/test_timedeltas.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- + +import pandas as pd +from pandas.core.arrays import TimedeltaArrayMixin as TimedeltaArray + + +class TestTimedeltaArray(object): + def test_repr(self): + tdi = pd.timedelta_range('1D', periods=10, freq='D') + arr = TimedeltaArray(tdi) + + # non- truncated + expected = ( + "\n" + "['1 days 00:00:00', '2 days 00:00:00']\n" + "Length: 2, dtype: timedelta64[ns], freq: None") + result = repr(arr[:2]) + assert result == expected + + # truncated + expected = ( + "\n" + "[" + "'1 days 00:00:00', " + "'2 days 00:00:00', " + "'3 days 00:00:00', " + "'...', " + "'8 days 00:00:00', " + "'9 days 00:00:00', " + "'10 days 00:00:00" + "']\n" + "Length: 10, dtype: timedelta64[ns], freq: None") + result = repr(arr) + assert result == expected From 1647ea256c446d1e3b94ffd36091b102914137cf Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Thu, 8 Nov 2018 16:48:34 -0800 Subject: [PATCH 05/14] isort --- pandas/tests/arrays/test_datetimelike.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pandas/tests/arrays/test_datetimelike.py b/pandas/tests/arrays/test_datetimelike.py index 99979acdcf9a4..651b7cb052065 100644 --- a/pandas/tests/arrays/test_datetimelike.py +++ b/pandas/tests/arrays/test_datetimelike.py @@ -4,8 +4,7 @@ import pandas as pd from pandas.core.arrays import ( - DatetimeArrayMixin as DatetimeArray, - PeriodArray, + DatetimeArrayMixin as DatetimeArray, PeriodArray, TimedeltaArrayMixin as TimedeltaArray) import pandas.util.testing as tm From db1d4468083aa1e9a3aa793c05b0543d54495e27 Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Fri, 9 Nov 2018 15:21:20 -0600 Subject: [PATCH 06/14] remove repr changes --- pandas/core/arrays/datetimelike.py | 21 ---------------- pandas/core/indexes/datetimes.py | 3 --- pandas/core/indexes/timedeltas.py | 3 --- pandas/tests/arrays/test_datetimes.py | 32 +++++++++++++++---------- pandas/tests/arrays/test_period.py | 22 +---------------- pandas/tests/arrays/test_timedeltas.py | 33 +++++++++++++++----------- 6 files changed, 39 insertions(+), 75 deletions(-) diff --git a/pandas/core/arrays/datetimelike.py b/pandas/core/arrays/datetimelike.py index 2087a02f068cf..8fc31e0b33be8 100644 --- a/pandas/core/arrays/datetimelike.py +++ b/pandas/core/arrays/datetimelike.py @@ -201,27 +201,6 @@ def astype(self, dtype, copy=True): return self._box_values(self.asi8) return super(DatetimeLikeArrayMixin, self).astype(dtype, copy) - # ------------------------------------------------------------------ - # Formatting - - def __repr__(self): - if len(self) <= 6: - # TODO: 6 is an arbitrary cutoff; make configurable? - items = [str(s) for s in self] - else: - items = ([str(s) for s in self[:3]] + - ['...'] + - [str(s) for s in self[-3:]]) - - result = '<{cls}>\n{items}\nLength: {length}, dtype: {dtype}'.format( - cls=type(self).__name__, items=items, - length=len(self), dtype=self.dtype) - - if not is_period_dtype(self): - result += ', freq: {freqstr}'.format(freqstr=self.freqstr) - - return result - # ------------------------------------------------------------------ # Null Handling diff --git a/pandas/core/indexes/datetimes.py b/pandas/core/indexes/datetimes.py index dce6f3cbf876e..8638f7bb952f8 100644 --- a/pandas/core/indexes/datetimes.py +++ b/pandas/core/indexes/datetimes.py @@ -1108,9 +1108,6 @@ def slice_indexer(self, start=None, end=None, step=None, kind=None): # -------------------------------------------------------------------- # Wrapping DatetimeArray - # override DatetimeLikeArrayMixin.__repr__ - __repr__ = Index.__repr__ - _timezone = cache_readonly(DatetimeArray._timezone.fget) is_normalized = cache_readonly(DatetimeArray.is_normalized.fget) _resolution = cache_readonly(DatetimeArray._resolution.fget) diff --git a/pandas/core/indexes/timedeltas.py b/pandas/core/indexes/timedeltas.py index 66e96269b3e88..45848cb78afac 100644 --- a/pandas/core/indexes/timedeltas.py +++ b/pandas/core/indexes/timedeltas.py @@ -237,9 +237,6 @@ def _format_native_types(self, na_rep=u'NaT', date_format=None, **kwargs): # ------------------------------------------------------------------- # Wrapping TimedeltaArray - # override DatetimeLikeArrayMixin.__repr__ - __repr__ = Index.__repr__ - days = wrap_field_accessor(TimedeltaArray.days) seconds = wrap_field_accessor(TimedeltaArray.seconds) microseconds = wrap_field_accessor(TimedeltaArray.microseconds) diff --git a/pandas/tests/arrays/test_datetimes.py b/pandas/tests/arrays/test_datetimes.py index cb914e43d946e..c1d574a756c70 100644 --- a/pandas/tests/arrays/test_datetimes.py +++ b/pandas/tests/arrays/test_datetimes.py @@ -9,33 +9,39 @@ import pandas as pd from pandas.core.arrays import DatetimeArrayMixin as DatetimeArray import pandas.util.testing as tm +import pytest class TestDatetimeArray(object): + + @pytest.mark.xfail(resaon='DatetimeArray', strict=True) def test_repr(self): - dti = pd.date_range('1994-07-01', periods=9, freq='W', tz='US/Central') + dti = pd.date_range('1994-07-01', periods=2, freq='W', tz='US/Central') arr = DatetimeArray(dti) # non-truncated expected = ( - "\n" + "\n" "['1994-07-03 00:00:00-05:00', '1994-07-10 00:00:00-05:00']\n" "Length: 2, dtype: datetime64[ns, US/Central], freq: W-SUN") - result = repr(arr[:2]) + result = repr(arr) assert result == expected + @pytest.mark.xfail(resaon='DatetimeArray', strict=True) + def test_repr_truncates(self): # truncated + dti = pd.date_range('1994-07-01', periods=1000, freq='W', + tz='US/Central') + arr = DatetimeArray(dti) expected = ( - "\n" - "[" - "'1994-07-03 00:00:00-05:00', " - "'1994-07-10 00:00:00-05:00', " - "'1994-07-17 00:00:00-05:00', " - "'...', " - "'1994-08-14 00:00:00-05:00', " - "'1994-08-21 00:00:00-05:00', " - "'1994-08-28 00:00:00-05:00'" - "]\n" + "\n" + "['1994-07-03 00:00:00-05:00', " + " '1994-07-10 00:00:00-05:00', " + " '1994-07-17 00:00:00-05:00', " + " '...', " + " '1994-08-14 00:00:00-05:00', " + " '1994-08-21 00:00:00-05:00', " + " '1994-08-28 00:00:00-05:00']\n" "Length: 9, dtype: datetime64[ns, US/Central], freq: W-SUN") result = repr(arr) assert result == expected diff --git a/pandas/tests/arrays/test_period.py b/pandas/tests/arrays/test_period.py index be75de0a953dd..013b1ca26f0e9 100644 --- a/pandas/tests/arrays/test_period.py +++ b/pandas/tests/arrays/test_period.py @@ -1,5 +1,4 @@ import numpy as np -import pytest from pandas._libs.tslibs import iNaT from pandas._libs.tslibs.period import IncompatibleFrequency @@ -10,6 +9,7 @@ import pandas as pd from pandas.core.arrays import PeriodArray, period_array import pandas.util.testing as tm +import pytest # ---------------------------------------------------------------------------- # Constructors @@ -195,23 +195,3 @@ def test_sub_period(): other = pd.Period("2000", freq="M") with tm.assert_raises_regex(IncompatibleFrequency, "freq"): arr - other - - -# ---------------------------------------------------------------------------- -# Unsorted - -def test_repr(): - arr = period_array(['2000', '2001'], freq='D') - - expected = ("\n" - "['2000-01-01', '2001-01-01']\n" - "Length: 2, dtype: period[D]") - assert repr(arr) == expected - - # long array shows ends - pi = pd.period_range('2001', periods=1000, freq='Y') - arr = period_array(pi) - - expected = ("\n" - "['2001', '2002', '2003', '...', '2998', '2999', '3000']\n" - "Length: 1000, dtype: period[A-DEC]") diff --git a/pandas/tests/arrays/test_timedeltas.py b/pandas/tests/arrays/test_timedeltas.py index 8ac9046570b51..136f4dc2fc855 100644 --- a/pandas/tests/arrays/test_timedeltas.py +++ b/pandas/tests/arrays/test_timedeltas.py @@ -1,34 +1,39 @@ # -*- coding: utf-8 -*- - import pandas as pd from pandas.core.arrays import TimedeltaArrayMixin as TimedeltaArray +import pytest class TestTimedeltaArray(object): + + @pytest.mark.xfail(reason='DatetimeArray', strict=True) def test_repr(self): - tdi = pd.timedelta_range('1D', periods=10, freq='D') + tdi = pd.timedelta_range('1D', periods=2, freq='D') arr = TimedeltaArray(tdi) # non- truncated expected = ( - "\n" + "\n" "['1 days 00:00:00', '2 days 00:00:00']\n" "Length: 2, dtype: timedelta64[ns], freq: None") - result = repr(arr[:2]) + result = repr(arr) assert result == expected + @pytest.mark.xfail(reason='DatetimeArray', strict=True) + def test_repr_truncated(self): # truncated + tdi = pd.timedelta_range('1D', periods=1000, freq='D') + arr = TimedeltaArray(tdi) + expected = ( - "\n" - "[" - "'1 days 00:00:00', " - "'2 days 00:00:00', " - "'3 days 00:00:00', " - "'...', " - "'8 days 00:00:00', " - "'9 days 00:00:00', " - "'10 days 00:00:00" - "']\n" + "\n" + "['1 days 00:00:00', '2 days 00:00:00', " + " '3 days 00:00:00', " + " '...', " + " '8 days 00:00:00', " + " '9 days 00:00:00', " + " '10 days 00:00:00" + " ']\n" "Length: 10, dtype: timedelta64[ns], freq: None") result = repr(arr) assert result == expected From 14d5e76967eb271e5a252885c5640407c2e969d8 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Fri, 9 Nov 2018 18:41:06 -0800 Subject: [PATCH 07/14] isort fixup --- pandas/tests/arrays/test_datetimes.py | 2 +- pandas/tests/arrays/test_period.py | 2 +- pandas/tests/arrays/test_timedeltas.py | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pandas/tests/arrays/test_datetimes.py b/pandas/tests/arrays/test_datetimes.py index c1d574a756c70..ae2265dde83d4 100644 --- a/pandas/tests/arrays/test_datetimes.py +++ b/pandas/tests/arrays/test_datetimes.py @@ -5,11 +5,11 @@ import operator import numpy as np +import pytest import pandas as pd from pandas.core.arrays import DatetimeArrayMixin as DatetimeArray import pandas.util.testing as tm -import pytest class TestDatetimeArray(object): diff --git a/pandas/tests/arrays/test_period.py b/pandas/tests/arrays/test_period.py index 013b1ca26f0e9..d8a67d67fb766 100644 --- a/pandas/tests/arrays/test_period.py +++ b/pandas/tests/arrays/test_period.py @@ -1,4 +1,5 @@ import numpy as np +import pytest from pandas._libs.tslibs import iNaT from pandas._libs.tslibs.period import IncompatibleFrequency @@ -9,7 +10,6 @@ import pandas as pd from pandas.core.arrays import PeriodArray, period_array import pandas.util.testing as tm -import pytest # ---------------------------------------------------------------------------- # Constructors diff --git a/pandas/tests/arrays/test_timedeltas.py b/pandas/tests/arrays/test_timedeltas.py index 136f4dc2fc855..ea0fc871afcd3 100644 --- a/pandas/tests/arrays/test_timedeltas.py +++ b/pandas/tests/arrays/test_timedeltas.py @@ -1,7 +1,8 @@ # -*- coding: utf-8 -*- +import pytest + import pandas as pd from pandas.core.arrays import TimedeltaArrayMixin as TimedeltaArray -import pytest class TestTimedeltaArray(object): From dd8505318127f76aa03847599d4fedcfcd3990ae Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Sat, 10 Nov 2018 17:01:42 -0800 Subject: [PATCH 08/14] typo fixup --- pandas/core/arrays/period.py | 2 +- pandas/tests/arrays/test_datetimes.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pandas/core/arrays/period.py b/pandas/core/arrays/period.py index c234f0443a240..962be7a12de20 100644 --- a/pandas/core/arrays/period.py +++ b/pandas/core/arrays/period.py @@ -324,7 +324,7 @@ def end_time(self): def to_timestamp(self, freq=None, how='start'): """ - Cast to DatetimeArray/Index + Cast to DatetimeArray/Index. Parameters ---------- diff --git a/pandas/tests/arrays/test_datetimes.py b/pandas/tests/arrays/test_datetimes.py index ae2265dde83d4..dcc00eda86234 100644 --- a/pandas/tests/arrays/test_datetimes.py +++ b/pandas/tests/arrays/test_datetimes.py @@ -14,7 +14,7 @@ class TestDatetimeArray(object): - @pytest.mark.xfail(resaon='DatetimeArray', strict=True) + @pytest.mark.xfail(reason='DatetimeArray', strict=True) def test_repr(self): dti = pd.date_range('1994-07-01', periods=2, freq='W', tz='US/Central') arr = DatetimeArray(dti) @@ -27,7 +27,7 @@ def test_repr(self): result = repr(arr) assert result == expected - @pytest.mark.xfail(resaon='DatetimeArray', strict=True) + @pytest.mark.xfail(reason='DatetimeArray', strict=True) def test_repr_truncates(self): # truncated dti = pd.date_range('1994-07-01', periods=1000, freq='W', From 469ac83c0d95397e890a563b07284f9da4521c25 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Sun, 11 Nov 2018 09:21:53 -0800 Subject: [PATCH 09/14] remove repr tests --- pandas/tests/arrays/test_datetimes.py | 35 -------------------------- pandas/tests/arrays/test_timedeltas.py | 33 +----------------------- 2 files changed, 1 insertion(+), 67 deletions(-) diff --git a/pandas/tests/arrays/test_datetimes.py b/pandas/tests/arrays/test_datetimes.py index dcc00eda86234..d64bed8c32f15 100644 --- a/pandas/tests/arrays/test_datetimes.py +++ b/pandas/tests/arrays/test_datetimes.py @@ -12,41 +12,6 @@ import pandas.util.testing as tm -class TestDatetimeArray(object): - - @pytest.mark.xfail(reason='DatetimeArray', strict=True) - def test_repr(self): - dti = pd.date_range('1994-07-01', periods=2, freq='W', tz='US/Central') - arr = DatetimeArray(dti) - - # non-truncated - expected = ( - "\n" - "['1994-07-03 00:00:00-05:00', '1994-07-10 00:00:00-05:00']\n" - "Length: 2, dtype: datetime64[ns, US/Central], freq: W-SUN") - result = repr(arr) - assert result == expected - - @pytest.mark.xfail(reason='DatetimeArray', strict=True) - def test_repr_truncates(self): - # truncated - dti = pd.date_range('1994-07-01', periods=1000, freq='W', - tz='US/Central') - arr = DatetimeArray(dti) - expected = ( - "\n" - "['1994-07-03 00:00:00-05:00', " - " '1994-07-10 00:00:00-05:00', " - " '1994-07-17 00:00:00-05:00', " - " '...', " - " '1994-08-14 00:00:00-05:00', " - " '1994-08-21 00:00:00-05:00', " - " '1994-08-28 00:00:00-05:00']\n" - "Length: 9, dtype: datetime64[ns, US/Central], freq: W-SUN") - result = repr(arr) - assert result == expected - - class TestDatetimeArrayComparisons(object): # TODO: merge this into tests/arithmetic/test_datetime64 once it is # sufficiently robust diff --git a/pandas/tests/arrays/test_timedeltas.py b/pandas/tests/arrays/test_timedeltas.py index ea0fc871afcd3..5748eb3b8ff4f 100644 --- a/pandas/tests/arrays/test_timedeltas.py +++ b/pandas/tests/arrays/test_timedeltas.py @@ -6,35 +6,4 @@ class TestTimedeltaArray(object): - - @pytest.mark.xfail(reason='DatetimeArray', strict=True) - def test_repr(self): - tdi = pd.timedelta_range('1D', periods=2, freq='D') - arr = TimedeltaArray(tdi) - - # non- truncated - expected = ( - "\n" - "['1 days 00:00:00', '2 days 00:00:00']\n" - "Length: 2, dtype: timedelta64[ns], freq: None") - result = repr(arr) - assert result == expected - - @pytest.mark.xfail(reason='DatetimeArray', strict=True) - def test_repr_truncated(self): - # truncated - tdi = pd.timedelta_range('1D', periods=1000, freq='D') - arr = TimedeltaArray(tdi) - - expected = ( - "\n" - "['1 days 00:00:00', '2 days 00:00:00', " - " '3 days 00:00:00', " - " '...', " - " '8 days 00:00:00', " - " '9 days 00:00:00', " - " '10 days 00:00:00" - " ']\n" - "Length: 10, dtype: timedelta64[ns], freq: None") - result = repr(arr) - assert result == expected + pass From 65209f15f6bc4717f74bbf51923d00c3ff6b2189 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Sun, 11 Nov 2018 10:12:26 -0800 Subject: [PATCH 10/14] fixup imports --- pandas/tests/arrays/test_datetimelike.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pandas/tests/arrays/test_datetimelike.py b/pandas/tests/arrays/test_datetimelike.py index 1df03d377f41f..bb4022c9cac9a 100644 --- a/pandas/tests/arrays/test_datetimelike.py +++ b/pandas/tests/arrays/test_datetimelike.py @@ -62,7 +62,7 @@ def test_array_object_dtype(self, tz_naive_fixture): # GH#23524 tz = tz_naive_fixture dti = pd.date_range('2016-01-01', periods=3, tz=tz) - arr = DatetimeArrayMixin(dti) + arr = DatetimeArray(dti) expected = np.array(list(dti)) @@ -77,7 +77,7 @@ def test_array(self, tz_naive_fixture): # GH#23524 tz = tz_naive_fixture dti = pd.date_range('2016-01-01', periods=3, tz=tz) - arr = DatetimeArrayMixin(dti) + arr = DatetimeArray(dti) expected = dti.asi8.view('M8[ns]') result = np.array(arr) @@ -92,7 +92,7 @@ def test_array_i8_dtype(self, tz_naive_fixture): # GH#23524 tz = tz_naive_fixture dti = pd.date_range('2016-01-01', periods=3, tz=tz) - arr = DatetimeArrayMixin(dti) + arr = DatetimeArray(dti) expected = dti.asi8 result = np.array(arr, dtype='i8') From 0ada03004726d9558dd10f94772a359d9cb7721f Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Sun, 11 Nov 2018 13:54:00 -0800 Subject: [PATCH 11/14] flake8 fixups --- pandas/tests/arrays/test_datetimes.py | 1 - pandas/tests/arrays/test_timedeltas.py | 4 ---- 2 files changed, 5 deletions(-) diff --git a/pandas/tests/arrays/test_datetimes.py b/pandas/tests/arrays/test_datetimes.py index d64bed8c32f15..2b630b98b69a2 100644 --- a/pandas/tests/arrays/test_datetimes.py +++ b/pandas/tests/arrays/test_datetimes.py @@ -5,7 +5,6 @@ import operator import numpy as np -import pytest import pandas as pd from pandas.core.arrays import DatetimeArrayMixin as DatetimeArray diff --git a/pandas/tests/arrays/test_timedeltas.py b/pandas/tests/arrays/test_timedeltas.py index 5748eb3b8ff4f..3ff807daeeab9 100644 --- a/pandas/tests/arrays/test_timedeltas.py +++ b/pandas/tests/arrays/test_timedeltas.py @@ -1,8 +1,4 @@ # -*- coding: utf-8 -*- -import pytest - -import pandas as pd -from pandas.core.arrays import TimedeltaArrayMixin as TimedeltaArray class TestTimedeltaArray(object): From 0a17757a3d4c69b88e809ece5ce636f103911097 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Sun, 11 Nov 2018 15:58:11 -0800 Subject: [PATCH 12/14] docstring suggestions --- pandas/core/arrays/timedeltas.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/pandas/core/arrays/timedeltas.py b/pandas/core/arrays/timedeltas.py index 4082ce8881ef5..9dbdd6ff8b562 100644 --- a/pandas/core/arrays/timedeltas.py +++ b/pandas/core/arrays/timedeltas.py @@ -415,20 +415,25 @@ def sequence_to_td64ns(data, copy=False, unit="ns", errors="raise"): array : list-like copy : bool, default False unit : str, default "ns" + The timedelta unit to treat integers as multiples of. errors : {"raise", "coerce", "ignore"}, default "raise" + How to handle elements that cannot be converted to timedelta64[ns]. + See ``pandas.to_timedelta`` for details. Returns ------- - ndarray[timedelta64[ns]] + converted : numpy.ndarray + The sequence converted to a numpy array with dtype ``timedelta64[ns]``. inferred_freq : Tick or None + The inferred frequency of the sequence. Raises ------ - ValueError : data cannot be converted to timedelta64[ns] + ValueError : Data cannot be converted to timedelta64[ns]. Notes ----- - Unlike `pandas.to_timedelta`, if setting `errors=ignore` will not cause + Unlike `pandas.to_timedelta`, if setting ``errors=ignore`` will not cause errors to be ignored; they are caught and subsequently ignored at a higher level. """ @@ -500,12 +505,13 @@ def ints_to_td64ns(data, unit="ns"): Parameters ---------- - data : np.ndarray with integer-dtype + data : numpy.ndarray with integer-dtype unit : str, default "ns" + The timedelta unit to treat integers as multiples of. Returns ------- - ndarray[timedelta64[ns]] + numpy.ndarray : timedelta64[ns] array converted from data bool : whether a copy was made """ copy_made = False @@ -541,15 +547,18 @@ def objects_to_td64ns(data, unit="ns", errors="raise"): ---------- data : ndarray or Index unit : str, default "ns" + The timedelta unit to treat integers as multiples of. errors : {"raise", "coerce", "ignore"}, default "raise" + How to handle elements that cannot be converted to timedelta64[ns]. + See ``pandas.to_timedelta`` for details. Returns ------- - ndarray[timedelta64[ns]] + numpy.ndarray : timedelta64[ns] array converted from data Raises ------ - ValueError : data cannot be converted to timedelta64[ns] + ValueError : Data cannot be converted to timedelta64[ns]. Notes ----- From 4ac9576d03aaaf76144a620e24ab7198178bd69c Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Sun, 11 Nov 2018 19:19:59 -0800 Subject: [PATCH 13/14] fixup unused import --- pandas/core/indexes/timedeltas.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pandas/core/indexes/timedeltas.py b/pandas/core/indexes/timedeltas.py index ac9ac4186f186..d9625d38b85de 100644 --- a/pandas/core/indexes/timedeltas.py +++ b/pandas/core/indexes/timedeltas.py @@ -5,7 +5,6 @@ from pandas._libs import ( NaT, Timedelta, index as libindex, join as libjoin, lib) -from pandas._libs.tslibs.timedeltas import array_to_timedelta64 import pandas.compat as compat from pandas.util._decorators import Appender, Substitution From c7211f79c0ce4e1f8c9a035ce0c00364885d29c8 Mon Sep 17 00:00:00 2001 From: Joris Van den Bossche Date: Mon, 12 Nov 2018 11:53:26 +0100 Subject: [PATCH 14/14] undo remaining repr changes --- pandas/core/arrays/period.py | 8 ++++++++ pandas/core/indexes/period.py | 3 --- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/pandas/core/arrays/period.py b/pandas/core/arrays/period.py index 962be7a12de20..b343d42ef3b7c 100644 --- a/pandas/core/arrays/period.py +++ b/pandas/core/arrays/period.py @@ -366,6 +366,14 @@ def to_timestamp(self, freq=None, how='start'): # -------------------------------------------------------------------- # Array-like / EA-Interface Methods + def __repr__(self): + return '<{}>\n{}\nLength: {}, dtype: {}'.format( + self.__class__.__name__, + [str(s) for s in self], + len(self), + self.dtype + ) + def __setitem__( self, key, # type: Union[int, Sequence[int], Sequence[bool]] diff --git a/pandas/core/indexes/period.py b/pandas/core/indexes/period.py index 3a867e15b5339..7890f03a1eba7 100644 --- a/pandas/core/indexes/period.py +++ b/pandas/core/indexes/period.py @@ -259,9 +259,6 @@ def _simple_new(cls, values, name=None, freq=None, **kwargs): # ------------------------------------------------------------------------ # Wrapping PeriodArray - # override DatetimeLikeArrayMixin.__repr__ - __repr__ = Index.__repr__ - # ------------------------------------------------------------------------ # Data