Skip to content

Commit 94e63ae

Browse files
committed
Merge pull request #7216 from jreback/ops2
DOC/CLN for GH7213/GH7206
2 parents e8d8c61 + 626cdf9 commit 94e63ae

File tree

6 files changed

+67
-45
lines changed

6 files changed

+67
-45
lines changed

doc/source/timeseries.rst

+9-9
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ regularity will result in a ``DatetimeIndex`` (but frequency is lost):
413413
Time/Date Components
414414
~~~~~~~~~~~~~~~~~~~~~~~~~~~
415415

416-
There are several time/date properties that one can access from ``Timestamp`` or a collection of timestamps like a ``DateTimeIndex``.
416+
There are several time/date properties that one can access from ``Timestamp`` or a collection of timestamps like a ``DateTimeIndex``.
417417

418418
.. csv-table::
419419
:header: "Property", "Description"
@@ -604,7 +604,7 @@ in the usual way.
604604
# Skip new years
605605
dt = datetime(2013, 12, 17)
606606
dt + bmth_us
607-
607+
608608
# Define date index with custom offset
609609
from pandas import DatetimeIndex
610610
DatetimeIndex(start='20100101',end='20120101',freq=bmth_us)
@@ -789,8 +789,8 @@ methods to return a list of holidays and only ``rules`` need to be defined
789789
in a specific holiday calendar class. Further, ``start_date`` and ``end_date``
790790
class attributes determine over what date range holidays are generated. These
791791
should be overwritten on the ``AbstractHolidayCalendar`` class to have the range
792-
apply to all calendar subclasses. ``USFederalHolidayCalendar`` is the
793-
only calendar that exists and primarily serves as an example for developing
792+
apply to all calendar subclasses. ``USFederalHolidayCalendar`` is the
793+
only calendar that exists and primarily serves as an example for developing
794794
other calendars.
795795

796796
For holidays that occur on fixed dates (e.g., US Memorial Day or July 4th) an
@@ -823,12 +823,12 @@ An example of how holidays and holiday calendars are defined:
823823
cal = ExampleCalendar()
824824
cal.holidays(datetime(2012, 1, 1), datetime(2012, 12, 31))
825825
826-
Using this calendar, creating an index or doing offset arithmetic skips weekends
826+
Using this calendar, creating an index or doing offset arithmetic skips weekends
827827
and holidays (i.e., Memorial Day/July 4th).
828828

829829
.. ipython:: python
830830
831-
DatetimeIndex(start='7/1/2012', end='7/10/2012',
831+
DatetimeIndex(start='7/1/2012', end='7/10/2012',
832832
freq=CDay(calendar=cal)).to_pydatetime()
833833
offset = CustomBusinessDay(calendar=cal)
834834
datetime(2012, 5, 25) + offset
@@ -840,11 +840,11 @@ Ranges are defined by the ``start_date`` and ``end_date`` class attributes
840840
of ``AbstractHolidayCalendar``. The defaults are below.
841841

842842
.. ipython:: python
843-
843+
844844
AbstractHolidayCalendar.start_date
845845
AbstractHolidayCalendar.end_date
846846
847-
These dates can be overwritten by setting the attributes as
847+
These dates can be overwritten by setting the attributes as
848848
datetime/Timestamp/string.
849849

850850
.. ipython:: python
@@ -1120,7 +1120,7 @@ Passing string represents lower frequency than `PeriodIndex` returns partial sli
11201120
dfp
11211121
dfp['2013-01-01 10H']
11221122
1123-
As the same as `DatetimeIndex`, the endpoints will be included in the result. Below example slices data starting from 10:00 to 11:59.
1123+
As the same as `DatetimeIndex`, the endpoints will be included in the result. Below example slices data starting from 10:00 to 11:59.
11241124

11251125
.. ipython:: python
11261126

pandas/core/base.py

+39-26
Original file line numberDiff line numberDiff line change
@@ -201,16 +201,6 @@ def __unicode__(self):
201201
return "%s(%s, dtype='%s')" % (type(self).__name__, prepr, self.dtype)
202202

203203

204-
# facilitate the properties on the wrapped ops
205-
def _field_accessor(name, docstring=None):
206-
op_accessor = '_{0}'.format(name)
207-
def f(self):
208-
return self._ops_compat(name,op_accessor)
209-
210-
f.__name__ = name
211-
f.__doc__ = docstring
212-
return property(f)
213-
214204
class IndexOpsMixin(object):
215205
""" common ops mixin to support a unified inteface / docs for Series / Index """
216206

@@ -219,24 +209,9 @@ def _is_allowed_index_op(self, name):
219209
raise TypeError("cannot perform an {name} operations on this type {typ}".format(
220210
name=name,typ=type(self._get_access_object())))
221211

222-
def _is_allowed_datetime_index_op(self, name):
223-
if not self._allow_datetime_index_ops:
224-
raise TypeError("cannot perform an {name} operations on this type {typ}".format(
225-
name=name,typ=type(self._get_access_object())))
226-
227-
def _is_allowed_period_index_op(self, name):
228-
if not self._allow_period_index_ops:
229-
raise TypeError("cannot perform an {name} operations on this type {typ}".format(
230-
name=name,typ=type(self._get_access_object())))
231-
232212
def _ops_compat(self, name, op_accessor):
233-
from pandas.tseries.index import DatetimeIndex
234-
from pandas.tseries.period import PeriodIndex
213+
235214
obj = self._get_access_object()
236-
if isinstance(obj, DatetimeIndex):
237-
self._is_allowed_datetime_index_op(name)
238-
elif isinstance(obj, PeriodIndex):
239-
self._is_allowed_period_index_op(name)
240215
try:
241216
return self._wrap_access_object(getattr(obj,op_accessor))
242217
except AttributeError:
@@ -336,6 +311,44 @@ def factorize(self, sort=False, na_sentinel=-1):
336311
from pandas.core.algorithms import factorize
337312
return factorize(self, sort=sort, na_sentinel=na_sentinel)
338313

314+
# facilitate the properties on the wrapped ops
315+
def _field_accessor(name, docstring=None):
316+
op_accessor = '_{0}'.format(name)
317+
def f(self):
318+
return self._ops_compat(name,op_accessor)
319+
320+
f.__name__ = name
321+
f.__doc__ = docstring
322+
return property(f)
323+
324+
class DatetimeIndexOpsMixin(object):
325+
""" common ops mixin to support a unified inteface datetimelike Index """
326+
327+
def _is_allowed_datetime_index_op(self, name):
328+
if not self._allow_datetime_index_ops:
329+
raise TypeError("cannot perform an {name} operations on this type {typ}".format(
330+
name=name,typ=type(self._get_access_object())))
331+
332+
def _is_allowed_period_index_op(self, name):
333+
if not self._allow_period_index_ops:
334+
raise TypeError("cannot perform an {name} operations on this type {typ}".format(
335+
name=name,typ=type(self._get_access_object())))
336+
337+
def _ops_compat(self, name, op_accessor):
338+
339+
from pandas.tseries.index import DatetimeIndex
340+
from pandas.tseries.period import PeriodIndex
341+
obj = self._get_access_object()
342+
if isinstance(obj, DatetimeIndex):
343+
self._is_allowed_datetime_index_op(name)
344+
elif isinstance(obj, PeriodIndex):
345+
self._is_allowed_period_index_op(name)
346+
try:
347+
return self._wrap_access_object(getattr(obj,op_accessor))
348+
except AttributeError:
349+
raise TypeError("cannot perform an {name} operations on this type {typ}".format(
350+
name=name,typ=type(obj)))
351+
339352
date = _field_accessor('date','Returns numpy array of datetime.date. The date part of the Timestamps')
340353
time = _field_accessor('time','Returns numpy array of datetime.time. The time part of the Timestamps')
341354
year = _field_accessor('year', "The year of the datetime")

pandas/tests/test_base.py

+15-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import pandas.compat as compat
55
import pandas as pd
66
from pandas.compat import u, StringIO
7-
from pandas.core.base import FrozenList, FrozenNDArray
7+
from pandas.core.base import FrozenList, FrozenNDArray, DatetimeIndexOpsMixin
88
from pandas.util.testing import assertRaisesRegexp, assert_isinstance
99
from pandas import Series, Index, Int64Index, DatetimeIndex, PeriodIndex
1010
from pandas import _np_version_under1p7
@@ -181,7 +181,13 @@ def check_ops_properties(self, props, filter=None, ignore_failures=False):
181181
# we mostly care about Series hwere anyhow
182182
if not ignore_failures:
183183
for o in self.not_valid_objs:
184-
self.assertRaises(TypeError, lambda : getattr(o,op))
184+
185+
# an object that is datetimelike will raise a TypeError, otherwise
186+
# an AttributeError
187+
if issubclass(type(o), DatetimeIndexOpsMixin):
188+
self.assertRaises(TypeError, lambda : getattr(o,op))
189+
else:
190+
self.assertRaises(AttributeError, lambda : getattr(o,op))
185191

186192
class TestIndexOps(Ops):
187193

@@ -462,6 +468,13 @@ def test_ops_properties_basic(self):
462468
for op in ['year','day','second','weekday']:
463469
self.assertRaises(TypeError, lambda x: getattr(self.dt_series,op))
464470

471+
# attribute access should still work!
472+
s = Series(dict(year=2000,month=1,day=10))
473+
self.assertEquals(s.year,2000)
474+
self.assertEquals(s.month,1)
475+
self.assertEquals(s.day,10)
476+
self.assertRaises(AttributeError, lambda : s.weekday)
477+
465478
class TestPeriodIndexOps(Ops):
466479
_allowed = '_allow_period_index_ops'
467480

pandas/tests/test_series.py

-6
Original file line numberDiff line numberDiff line change
@@ -5617,12 +5617,6 @@ def test_asfreq(self):
56175617
self.assertEqual(len(result), 0)
56185618
self.assertIsNot(result, ts)
56195619

5620-
def test_weekday(self):
5621-
# Just run the function
5622-
def f():
5623-
self.ts.weekday
5624-
self.assertRaises(TypeError, f)
5625-
56265620
def test_diff(self):
56275621
# Just run the function
56285622
self.ts.diff()

pandas/tseries/index.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from pandas.tseries.frequencies import (
1616
infer_freq, to_offset, get_period_alias,
1717
Resolution, get_reso_string, get_offset)
18+
from pandas.core.base import DatetimeIndexOpsMixin
1819
from pandas.tseries.offsets import DateOffset, generate_range, Tick, CDay
1920
from pandas.tseries.tools import parse_time_string, normalize_date
2021
from pandas.util.decorators import cache_readonly
@@ -102,7 +103,7 @@ def _ensure_datetime64(other):
102103

103104
_midnight = time(0, 0)
104105

105-
class DatetimeIndex(Int64Index):
106+
class DatetimeIndex(DatetimeIndexOpsMixin, Int64Index):
106107
"""
107108
Immutable ndarray of datetime64 data, represented internally as int64, and
108109
which can be boxed to Timestamp objects that are subclasses of datetime and

pandas/tseries/period.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from pandas.tseries.frequencies import (get_freq_code as _gfc,
99
_month_numbers, FreqGroup)
1010
from pandas.tseries.index import DatetimeIndex, Int64Index, Index
11+
from pandas.core.base import DatetimeIndexOpsMixin
1112
from pandas.tseries.tools import parse_time_string
1213
import pandas.tseries.frequencies as _freq_mod
1314

@@ -500,7 +501,7 @@ def wrapper(self, other):
500501
return wrapper
501502

502503

503-
class PeriodIndex(Int64Index):
504+
class PeriodIndex(DatetimeIndexOpsMixin, Int64Index):
504505
"""
505506
Immutable ndarray holding ordinal values indicating regular periods in
506507
time such as particular years, quarters, months, etc. A value of 1 is the

0 commit comments

Comments
 (0)