Skip to content

Commit 820e40e

Browse files
jbrockmendelPingviinituutti
authored andcommitted
Make DTA/TDA/PA return NotImplemented on comparisons (pandas-dev#24643)
1 parent e74c07c commit 820e40e

File tree

5 files changed

+26
-17
lines changed

5 files changed

+26
-17
lines changed

pandas/core/arrays/datetimes.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
is_extension_type, is_float_dtype, is_object_dtype, is_period_dtype,
2020
is_string_dtype, is_timedelta64_dtype, pandas_dtype)
2121
from pandas.core.dtypes.dtypes import DatetimeTZDtype
22-
from pandas.core.dtypes.generic import ABCIndexClass, ABCPandasArray, ABCSeries
22+
from pandas.core.dtypes.generic import (
23+
ABCDataFrame, ABCIndexClass, ABCPandasArray, ABCSeries)
2324
from pandas.core.dtypes.missing import isna
2425

2526
from pandas.core import ops
@@ -96,9 +97,8 @@ def _dt_array_cmp(cls, op):
9697
nat_result = True if opname == '__ne__' else False
9798

9899
def wrapper(self, other):
99-
# TODO: return NotImplemented for Series / Index and let pandas unbox
100-
# Right now, returning NotImplemented for Index fails because we
101-
# go into the index implementation, which may be a bug?
100+
if isinstance(other, (ABCDataFrame, ABCSeries, ABCIndexClass)):
101+
return NotImplemented
102102

103103
other = lib.item_from_zerodim(other)
104104

pandas/core/arrays/period.py

+6-11
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
_TD_DTYPE, ensure_object, is_datetime64_dtype, is_float_dtype,
1818
is_list_like, is_period_dtype, pandas_dtype)
1919
from pandas.core.dtypes.dtypes import PeriodDtype
20-
from pandas.core.dtypes.generic import ABCIndexClass, ABCPeriodIndex, ABCSeries
20+
from pandas.core.dtypes.generic import (
21+
ABCDataFrame, ABCIndexClass, ABCPeriodIndex, ABCSeries)
2122
from pandas.core.dtypes.missing import isna, notna
2223

2324
import pandas.core.algorithms as algos
@@ -48,26 +49,20 @@ def _period_array_cmp(cls, op):
4849

4950
def wrapper(self, other):
5051
op = getattr(self.asi8, opname)
51-
# We want to eventually defer to the Series or PeriodIndex (which will
52-
# return here with an unboxed PeriodArray). But before we do that,
53-
# we do a bit of validation on type (Period) and freq, so that our
54-
# error messages are sensible
52+
53+
if isinstance(other, (ABCDataFrame, ABCSeries, ABCIndexClass)):
54+
return NotImplemented
55+
5556
if is_list_like(other) and len(other) != len(self):
5657
raise ValueError("Lengths must match")
5758

58-
not_implemented = isinstance(other, (ABCSeries, ABCIndexClass))
59-
if not_implemented:
60-
other = other._values
61-
6259
if isinstance(other, Period):
6360
self._check_compatible_with(other)
6461

6562
result = op(other.ordinal)
6663
elif isinstance(other, cls):
6764
self._check_compatible_with(other)
6865

69-
if not_implemented:
70-
return NotImplemented
7166
result = op(other.asi8)
7267

7368
mask = self._isnan | other._isnan

pandas/core/arrays/timedeltas.py

+3
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ def _td_array_cmp(cls, op):
6464
nat_result = True if opname == '__ne__' else False
6565

6666
def wrapper(self, other):
67+
if isinstance(other, (ABCDataFrame, ABCSeries, ABCIndexClass)):
68+
return NotImplemented
69+
6770
if _is_convertible_to_td(other) or other is NaT:
6871
try:
6972
other = Timedelta(other)

pandas/core/indexes/datetimelike.py

+5
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,11 @@ def _create_comparison_method(cls, op):
109109
Create a comparison method that dispatches to ``cls.values``.
110110
"""
111111
def wrapper(self, other):
112+
if isinstance(other, ABCSeries):
113+
# the arrays defer to Series for comparison ops but the indexes
114+
# don't, so we have to unwrap here.
115+
other = other._values
116+
112117
result = op(self._data, maybe_unwrap_index(other))
113118
return result
114119

pandas/tests/arithmetic/test_period.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,10 @@ def test_parr_cmp_pi_mismatched_freq_raises(self, freq, box_with_array):
152152

153153
# TODO: Could parametrize over boxes for idx?
154154
idx = PeriodIndex(['2011', '2012', '2013', '2014'], freq='A')
155-
with pytest.raises(IncompatibleFrequency, match=msg):
155+
rev_msg = (r'Input has different freq=(M|2M|3M) from '
156+
r'PeriodArray\(freq=A-DEC\)')
157+
idx_msg = rev_msg if box_with_array is tm.to_array else msg
158+
with pytest.raises(IncompatibleFrequency, match=idx_msg):
156159
base <= idx
157160

158161
# Different frequency
@@ -164,7 +167,10 @@ def test_parr_cmp_pi_mismatched_freq_raises(self, freq, box_with_array):
164167
Period('2011', freq='4M') >= base
165168

166169
idx = PeriodIndex(['2011', '2012', '2013', '2014'], freq='4M')
167-
with pytest.raises(IncompatibleFrequency, match=msg):
170+
rev_msg = (r'Input has different freq=(M|2M|3M) from '
171+
r'PeriodArray\(freq=4M\)')
172+
idx_msg = rev_msg if box_with_array is tm.to_array else msg
173+
with pytest.raises(IncompatibleFrequency, match=idx_msg):
168174
base <= idx
169175

170176
@pytest.mark.parametrize('freq', ['M', '2M', '3M'])

0 commit comments

Comments
 (0)