Skip to content

Commit e614a80

Browse files
committed
REF: Refactor Datetimelike delegation
This is a generalization of PeriodIndex's dispatching to PeriodArray, without any actual changes yet. This is split from pandas-dev#24024, where DatetimeIndex and TimedeltaIndex will implement and inherit from delgates similiar to PeriodDelegateMixin.
1 parent 5b0610b commit e614a80

File tree

2 files changed

+62
-22
lines changed

2 files changed

+62
-22
lines changed

pandas/core/indexes/datetimelike.py

+47
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"""
33
Base and utility classes for tseries type pandas objects.
44
"""
5+
import operator
56
import warnings
67

78
import numpy as np
@@ -22,6 +23,7 @@
2223
from pandas.core.dtypes.missing import isna
2324

2425
from pandas.core import algorithms, ops
26+
from pandas.core.accessor import PandasDelegate
2527
from pandas.core.arrays import PeriodArray
2628
from pandas.core.arrays.datetimelike import DatetimeLikeArrayMixin
2729
import pandas.core.indexes.base as ibase
@@ -855,3 +857,48 @@ def f(self):
855857
f.__name__ = fget.__name__
856858
f.__doc__ = fget.__doc__
857859
return property(f)
860+
861+
862+
class DatetimelikeDelegateMixin(PandasDelegate):
863+
"""
864+
Delegation mechanism, specific for Datetime, Timedelta, and Period types.
865+
866+
Functionality is delegated from the Index class to an Array class. A
867+
few things can be customized
868+
869+
* _delegate_class : type
870+
The class being delegated to.
871+
* _delegated_methods, delegated_properties : List
872+
The list of property / method names being delagated.
873+
* raw_methods : Set
874+
The set of methods whose results should should *not* be
875+
boxed in an index, after being returned from the array
876+
* raw_properties : Set
877+
The set of properties whose results should should *not* be
878+
boxed in an index, after being returned from the array
879+
"""
880+
# raw_methods : dispatch methods that shouldn't be boxed in an Index
881+
_raw_methods = set()
882+
# raw_properties : dispatch properties that shouldn't be boxed in an Index
883+
_raw_properties = set()
884+
name = None
885+
_data = None
886+
887+
@property
888+
def _delegate_class(self):
889+
raise AbstractMethodError
890+
891+
def _delegate_property_get(self, name, *args, **kwargs):
892+
result = getattr(self._data, name)
893+
if name not in self._raw_properties:
894+
result = Index(result, name=self.name)
895+
return result
896+
897+
def _delegate_property_set(self, name, value, *args, **kwargs):
898+
setattr(self._data, name, value)
899+
900+
def _delegate_method(self, name, *args, **kwargs):
901+
result = operator.methodcaller(name, *args, **kwargs)(self._data)
902+
if name not in self._raw_methods:
903+
result = Index(result, name=self.name)
904+
return result

pandas/core/indexes/period.py

+15-22
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# pylint: disable=E1101,E1103,W0232
22
from datetime import datetime, timedelta
3-
import operator
43
import warnings
54

65
import numpy as np
@@ -18,15 +17,16 @@
1817

1918
from pandas import compat
2019
from pandas.core import common as com
21-
from pandas.core.accessor import PandasDelegate, delegate_names
20+
from pandas.core.accessor import delegate_names
2221
from pandas.core.algorithms import unique1d
2322
import pandas.core.arrays.datetimelike as dtl
2423
from pandas.core.arrays.period import PeriodArray, period_array
2524
from pandas.core.base import _shared_docs
2625
import pandas.core.indexes.base as ibase
2726
from pandas.core.indexes.base import _index_shared_docs, ensure_index
2827
from pandas.core.indexes.datetimelike import (
29-
DatelikeOps, DatetimeIndexOpsMixin, wrap_arithmetic_op)
28+
DatelikeOps, DatetimeIndexOpsMixin, DatetimelikeDelegateMixin,
29+
wrap_arithmetic_op)
3030
from pandas.core.indexes.datetimes import DatetimeIndex, Index, Int64Index
3131
from pandas.core.missing import isna
3232
from pandas.core.ops import get_op_result_name
@@ -54,33 +54,26 @@ def _new_PeriodIndex(cls, **d):
5454
return cls(values, **d)
5555

5656

57-
class PeriodDelegateMixin(PandasDelegate):
57+
class PeriodDelegateMixin(DatetimelikeDelegateMixin):
5858
"""
5959
Delegate from PeriodIndex to PeriodArray.
6060
"""
61-
def _delegate_property_get(self, name, *args, **kwargs):
62-
result = getattr(self._data, name)
63-
box_ops = (
64-
set(PeriodArray._datetimelike_ops) - set(PeriodArray._bool_ops)
65-
)
66-
if name in box_ops:
67-
result = Index(result, name=self.name)
68-
return result
69-
70-
def _delegate_property_set(self, name, value, *args, **kwargs):
71-
setattr(self._data, name, value)
72-
73-
def _delegate_method(self, name, *args, **kwargs):
74-
result = operator.methodcaller(name, *args, **kwargs)(self._data)
75-
return Index(result, name=self.name)
61+
_delegate_class = PeriodArray
62+
_delegated_properties = (
63+
PeriodArray._datetimelike_ops + ['size', 'asi8', 'shape']
64+
)
65+
_delegated_methods = (
66+
set(PeriodArray._datetimelike_methods) -
67+
{'asfreq', 'to_timestamp'} | {'_addsub_int_array'}
68+
)
69+
_raw_properties = {'is_leap_year'}
7670

7771

7872
@delegate_names(PeriodArray,
79-
PeriodArray._datetimelike_ops + ['size', 'asi8', 'shape'],
73+
PeriodDelegateMixin._delegated_properties,
8074
typ='property')
8175
@delegate_names(PeriodArray,
82-
[x for x in PeriodArray._datetimelike_methods
83-
if x not in {"asfreq", "to_timestamp"}],
76+
PeriodDelegateMixin._delegated_methods,
8477
typ="method",
8578
overwrite=True)
8679
class PeriodIndex(DatelikeOps, DatetimeIndexOpsMixin,

0 commit comments

Comments
 (0)