Skip to content

Commit 511ae30

Browse files
jbrockmendeljreback
authored andcommitted
BUG: Assorted DTA/TDA/PI bugfixes (#24397)
1 parent 2a09706 commit 511ae30

File tree

9 files changed

+43
-2
lines changed

9 files changed

+43
-2
lines changed

doc/source/whatsnew/v0.24.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -1321,6 +1321,7 @@ Datetimelike
13211321
- Bug in :class:`DatetimeIndex` and :class:`TimedeltaIndex` where indexing with ``Ellipsis`` would incorrectly lose the index's ``freq`` attribute (:issue:`21282`)
13221322
- Clarified error message produced when passing an incorrect ``freq`` argument to :class:`DatetimeIndex` with ``NaT`` as the first entry in the passed data (:issue:`11587`)
13231323
- Bug in :func:`to_datetime` where ``box`` and ``utc`` arguments were ignored when passing a :class:`DataFrame` or ``dict`` of unit mappings (:issue:`23760`)
1324+
- Bug in :class:`PeriodIndex` where comparisons against an array-like object with length 1 failed to raise ``ValueError`` (:issue:`23078`)
13241325

13251326
Timedelta
13261327
^^^^^^^^^

pandas/core/arrays/datetimelike.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1298,7 +1298,8 @@ def _ensure_datetimelike_to_i8(other, to_utc=False):
12981298

12991299
if lib.is_scalar(other) and isna(other):
13001300
return iNaT
1301-
elif isinstance(other, (PeriodArray, ABCIndexClass)):
1301+
elif isinstance(other, (PeriodArray, ABCIndexClass,
1302+
DatetimeLikeArrayMixin)):
13021303
# convert tz if needed
13031304
if getattr(other, 'tz', None) is not None:
13041305
if to_utc:

pandas/core/arrays/datetimes.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ def _dt_array_cmp(cls, op):
9797
def wrapper(self, other):
9898
meth = getattr(dtl.DatetimeLikeArrayMixin, opname)
9999

100+
other = lib.item_from_zerodim(other)
101+
100102
if isinstance(other, (datetime, np.datetime64, compat.string_types)):
101103
if isinstance(other, (datetime, np.datetime64)):
102104
# GH#18435 strings get a pass from tzawareness compat
@@ -111,8 +113,10 @@ def wrapper(self, other):
111113
result = op(self.asi8, other.view('i8'))
112114
if isna(other):
113115
result.fill(nat_result)
114-
elif lib.is_scalar(other):
116+
elif lib.is_scalar(other) or np.ndim(other) == 0:
115117
return ops.invalid_comparison(self, other, op)
118+
elif len(other) != len(self):
119+
raise ValueError("Lengths must match")
116120
else:
117121
if isinstance(other, list):
118122
try:

pandas/core/arrays/period.py

+3
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ def wrapper(self, other):
5656
# return here with an unboxed PeriodArray). But before we do that,
5757
# we do a bit of validation on type (Period) and freq, so that our
5858
# error messages are sensible
59+
if is_list_like(other) and len(other) != len(self):
60+
raise ValueError("Lengths must match")
61+
5962
not_implemented = isinstance(other, (ABCSeries, ABCIndexClass))
6063
if not_implemented:
6164
other = other._values

pandas/core/arrays/timedeltas.py

+3
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ def wrapper(self, other):
8989
elif not is_list_like(other):
9090
return ops.invalid_comparison(self, other, op)
9191

92+
elif len(other) != len(self):
93+
raise ValueError("Lengths must match")
94+
9295
else:
9396
try:
9497
other = type(self)._from_sequence(other)._data

pandas/core/indexes/base.py

+1
Original file line numberDiff line numberDiff line change
@@ -5094,6 +5094,7 @@ def _evaluate_numeric_unary(self):
50945094
attrs = self._maybe_update_attributes(attrs)
50955095
return Index(op(self.values), **attrs)
50965096

5097+
_evaluate_numeric_unary.__name__ = opstr
50975098
return _evaluate_numeric_unary
50985099

50995100
cls.__neg__ = _make_evaluate_unary(operator.neg, '__neg__')

pandas/core/ops.py

+3
Original file line numberDiff line numberDiff line change
@@ -1390,6 +1390,7 @@ def f(self, other):
13901390

13911391
return self
13921392

1393+
f.__name__ = "__i{name}__".format(name=method.__name__.strip("__"))
13931394
return f
13941395

13951396
new_methods.update(
@@ -1574,6 +1575,7 @@ def wrapper(left, right):
15741575
return construct_result(left, result,
15751576
index=left.index, name=res_name, dtype=None)
15761577

1578+
wrapper.__name__ = op_name
15771579
return wrapper
15781580

15791581

@@ -1762,6 +1764,7 @@ def wrapper(self, other, axis=None):
17621764
return self._constructor(res_values, index=self.index,
17631765
name=res_name, dtype='bool')
17641766

1767+
wrapper.__name__ = op_name
17651768
return wrapper
17661769

17671770

pandas/core/series.py

+1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ def wrapper(self):
9191
raise TypeError("cannot convert the series to "
9292
"{0}".format(str(converter)))
9393

94+
wrapper.__name__ = "__{name}__".format(name=converter.__name__)
9495
return wrapper
9596

9697
# ----------------------------------------------------------------------

pandas/tests/arrays/test_datetimelike.py

+24
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,21 @@ def timedelta_index(request):
5959
class SharedTests(object):
6060
index_cls = None
6161

62+
def test_compare_len1_raises(self):
63+
# make sure we raise when comparing with different lengths, specific
64+
# to the case where one has length-1, which numpy would broadcast
65+
data = np.arange(10, dtype='i8')
66+
67+
idx = self.index_cls._simple_new(data, freq='D')
68+
arr = self.array_cls(idx)
69+
70+
with pytest.raises(ValueError, match="Lengths must match"):
71+
arr == arr[:1]
72+
73+
# test the index classes while we're at it, GH#23078
74+
with pytest.raises(ValueError, match="Lengths must match"):
75+
idx <= idx[[0]]
76+
6277
def test_take(self):
6378
data = np.arange(100, dtype='i8')
6479
np.random.shuffle(data)
@@ -119,6 +134,15 @@ class TestDatetimeArray(SharedTests):
119134
index_cls = pd.DatetimeIndex
120135
array_cls = DatetimeArray
121136

137+
def test_round(self, tz_naive_fixture):
138+
# GH#24064
139+
tz = tz_naive_fixture
140+
dti = pd.date_range('2016-01-01 01:01:00', periods=3, freq='H', tz=tz)
141+
142+
result = dti.round(freq='2T')
143+
expected = dti - pd.Timedelta(minutes=1)
144+
tm.assert_index_equal(result, expected)
145+
122146
def test_array_object_dtype(self, tz_naive_fixture):
123147
# GH#23524
124148
tz = tz_naive_fixture

0 commit comments

Comments
 (0)