Skip to content

Commit d47e94a

Browse files
authored
CLN: do length-checking in boilerplate deocrator (#34081)
1 parent d6d1a76 commit d47e94a

File tree

14 files changed

+47
-53
lines changed

14 files changed

+47
-53
lines changed

pandas/core/arrays/categorical.py

-4
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,6 @@ def _cat_compare_op(op):
6666

6767
@unpack_zerodim_and_defer(opname)
6868
def func(self, other):
69-
if is_list_like(other) and len(other) != len(self):
70-
# TODO: Could this fail if the categories are listlike objects?
71-
raise ValueError("Lengths must match.")
72-
7369
if not self.ordered:
7470
if opname in ["__lt__", "__gt__", "__le__", "__ge__"]:
7571
raise TypeError(

pandas/core/arrays/datetimelike.py

-6
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,6 @@ def _validate_comparison_value(self, other):
8585
elif not is_list_like(other):
8686
raise InvalidComparison(other)
8787

88-
elif len(other) != len(self):
89-
raise ValueError("Lengths must match")
90-
9188
else:
9289
try:
9390
other = self._validate_listlike(other, opname, allow_object=True)
@@ -1230,9 +1227,6 @@ def _add_timedelta_arraylike(self, other):
12301227
"""
12311228
# overridden by PeriodArray
12321229

1233-
if len(self) != len(other):
1234-
raise ValueError("cannot add indices of unequal length")
1235-
12361230
if isinstance(other, np.ndarray):
12371231
# ndarray[timedelta64]; wrap in TimedeltaIndex for op
12381232
from pandas.core.arrays import TimedeltaArray

pandas/core/arrays/datetimes.py

-3
Original file line numberDiff line numberDiff line change
@@ -652,9 +652,6 @@ def _assert_tzawareness_compat(self, other):
652652

653653
def _sub_datetime_arraylike(self, other):
654654
"""subtract DatetimeArray/Index or ndarray[datetime64]"""
655-
if len(self) != len(other):
656-
raise ValueError("cannot add indices of unequal length")
657-
658655
if isinstance(other, np.ndarray):
659656
assert is_datetime64_dtype(other)
660657
other = type(self)(other)

pandas/core/arrays/integer.py

-4
Original file line numberDiff line numberDiff line change
@@ -517,8 +517,6 @@ def cmp_method(self, other):
517517
raise NotImplementedError(
518518
"can only perform ops with 1-d structures"
519519
)
520-
if len(self) != len(other):
521-
raise ValueError("Lengths must match to compare")
522520

523521
if other is libmissing.NA:
524522
# numpy does not handle pd.NA well as "other" scalar (it returns
@@ -622,8 +620,6 @@ def integer_arithmetic_method(self, other):
622620
raise NotImplementedError(
623621
"can only perform ops with 1-d structures"
624622
)
625-
if len(self) != len(other):
626-
raise ValueError("Lengths must match")
627623
if not (is_float_dtype(other) or is_integer_dtype(other)):
628624
raise TypeError("can only perform ops with numeric values")
629625

pandas/core/arrays/timedeltas.py

+4-18
Original file line numberDiff line numberDiff line change
@@ -460,10 +460,6 @@ def __mul__(self, other):
460460
if not hasattr(other, "dtype"):
461461
# list, tuple
462462
other = np.array(other)
463-
if len(other) != len(self) and not is_timedelta64_dtype(other):
464-
# Exclude timedelta64 here so we correctly raise TypeError
465-
# for that instead of ValueError
466-
raise ValueError("Cannot multiply with unequal lengths")
467463

468464
if is_object_dtype(other.dtype):
469465
# this multiplication will succeed only if all elements of other
@@ -507,10 +503,7 @@ def __truediv__(self, other):
507503
# e.g. list, tuple
508504
other = np.array(other)
509505

510-
if len(other) != len(self):
511-
raise ValueError("Cannot divide vectors with unequal lengths")
512-
513-
elif is_timedelta64_dtype(other.dtype):
506+
if is_timedelta64_dtype(other.dtype):
514507
# let numpy handle it
515508
return self._data / other
516509

@@ -560,10 +553,7 @@ def __rtruediv__(self, other):
560553
# e.g. list, tuple
561554
other = np.array(other)
562555

563-
if len(other) != len(self):
564-
raise ValueError("Cannot divide vectors with unequal lengths")
565-
566-
elif is_timedelta64_dtype(other.dtype):
556+
if is_timedelta64_dtype(other.dtype):
567557
# let numpy handle it
568558
return other / self._data
569559

@@ -612,10 +602,8 @@ def __floordiv__(self, other):
612602
if not hasattr(other, "dtype"):
613603
# list, tuple
614604
other = np.array(other)
615-
if len(other) != len(self):
616-
raise ValueError("Cannot divide with unequal lengths")
617605

618-
elif is_timedelta64_dtype(other.dtype):
606+
if is_timedelta64_dtype(other.dtype):
619607
other = type(self)(other)
620608

621609
# numpy timedelta64 does not natively support floordiv, so operate
@@ -666,10 +654,8 @@ def __rfloordiv__(self, other):
666654
if not hasattr(other, "dtype"):
667655
# list, tuple
668656
other = np.array(other)
669-
if len(other) != len(self):
670-
raise ValueError("Cannot divide with unequal lengths")
671657

672-
elif is_timedelta64_dtype(other.dtype):
658+
if is_timedelta64_dtype(other.dtype):
673659
other = type(self)(other)
674660

675661
# numpy timedelta64 does not natively support floordiv, so operate

pandas/core/indexes/base.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
from pandas.core.indexes.frozen import FrozenList
7676
import pandas.core.missing as missing
7777
from pandas.core.ops import get_op_result_name
78+
from pandas.core.ops.common import unpack_zerodim_and_defer
7879
from pandas.core.ops.invalid import make_invalid_op
7980
from pandas.core.sorting import ensure_key_mapped
8081
from pandas.core.strings import StringMethods
@@ -108,10 +109,8 @@
108109

109110

110111
def _make_comparison_op(op, cls):
112+
@unpack_zerodim_and_defer(op.__name__)
111113
def cmp_method(self, other):
112-
if isinstance(other, (np.ndarray, Index, ABCSeries, ExtensionArray)):
113-
if other.ndim > 0 and len(self) != len(other):
114-
raise ValueError("Lengths must match to compare")
115114

116115
if is_object_dtype(self.dtype) and isinstance(other, ABCCategorical):
117116
left = type(other)(self._values, dtype=other.dtype)

pandas/core/ops/common.py

+23-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
"""
22
Boilerplate functions used in defining binary operations.
33
"""
4+
from collections import UserDict
45
from functools import wraps
56
from typing import Callable
67

7-
from pandas._libs.lib import item_from_zerodim
8+
import numpy as np
9+
10+
from pandas._libs.lib import is_list_like, item_from_zerodim
811
from pandas._typing import F
912

1013
from pandas.core.dtypes.generic import ABCDataFrame, ABCIndexClass, ABCSeries
@@ -62,6 +65,25 @@ def new_method(self, other):
6265

6366
other = item_from_zerodim(other)
6467

68+
if isinstance(self, (ABCSeries, ABCDataFrame)) and isinstance(
69+
other, (ABCSeries, ABCDataFrame)
70+
):
71+
# we dont require length matches
72+
pass
73+
elif is_list_like(other, allow_sets=False) and not isinstance(
74+
other, (dict, UserDict)
75+
):
76+
if len(other) != len(self):
77+
if len(other) == 1 and not hasattr(other, "dtype"):
78+
# i.e. unpack scalar list, but leave e.g. Categorical,
79+
# for which the scalar behavior doesnt match the
80+
# array behavior
81+
other = other[0]
82+
else:
83+
raise ValueError(
84+
"Lengths must match", self.shape, np.shape(other), type(other)
85+
)
86+
6587
return method(self, other)
6688

6789
return new_method

pandas/tests/arithmetic/test_datetime64.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2206,7 +2206,7 @@ def test_sub_dti_dti(self):
22062206
# different length raises ValueError
22072207
dti1 = date_range("20130101", periods=3)
22082208
dti2 = date_range("20130101", periods=4)
2209-
msg = "cannot add indices of unequal length"
2209+
msg = "Lengths must match"
22102210
with pytest.raises(ValueError, match=msg):
22112211
dti1 - dti2
22122212

pandas/tests/arithmetic/test_numeric.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,7 @@ def test_mul_datelike_raises(self, numeric_idx):
647647

648648
def test_mul_size_mismatch_raises(self, numeric_idx):
649649
idx = numeric_idx
650-
msg = "operands could not be broadcast together"
650+
msg = "Lengths must match"
651651
with pytest.raises(ValueError, match=msg):
652652
idx * idx[0:3]
653653
with pytest.raises(ValueError, match=msg):

pandas/tests/arithmetic/test_timedelta64.py

+10-7
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ def test_addition_ops(self):
451451
tm.assert_index_equal(result, expected)
452452

453453
# unequal length
454-
msg = "cannot add indices of unequal length"
454+
msg = "Lengths must match"
455455
with pytest.raises(ValueError, match=msg):
456456
tdi + dti[0:1]
457457
with pytest.raises(ValueError, match=msg):
@@ -1730,7 +1730,7 @@ def test_tdarr_div_length_mismatch(self, box_with_array):
17301730
mismatched = [1, 2, 3, 4]
17311731

17321732
rng = tm.box_expected(rng, box_with_array)
1733-
msg = "Cannot divide vectors|Unable to coerce to Series"
1733+
msg = "Lengths must match|Unable to coerce to Series"
17341734
for obj in [mismatched, mismatched[:2]]:
17351735
# one shorter, one longer
17361736
for other in [obj, np.array(obj), pd.Index(obj)]:
@@ -1912,12 +1912,15 @@ def test_td64arr_mul_tdscalar_invalid(self, box_with_array, scalar_td):
19121912
def test_td64arr_mul_too_short_raises(self, box_with_array):
19131913
idx = TimedeltaIndex(np.arange(5, dtype="int64"))
19141914
idx = tm.box_expected(idx, box_with_array)
1915-
msg = (
1916-
"cannot use operands with types dtype|"
1917-
"Cannot multiply with unequal lengths|"
1918-
"Unable to coerce to Series"
1915+
msg = "|".join(
1916+
[
1917+
"Lengths must match", # <- EA, Index, Series
1918+
"cannot use operands with types dtype", # <- DataFrame
1919+
"Unable to coerce to Series", # <- Series
1920+
]
19191921
)
1920-
with pytest.raises(TypeError, match=msg):
1922+
with pytest.raises((ValueError, TypeError), match=msg):
1923+
# length check before dtype check
19211924
idx * idx[:3]
19221925
with pytest.raises(ValueError, match=msg):
19231926
idx * np.array([1, 2])

pandas/tests/arrays/boolean/test_logical.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def test_empty_ok(self, all_logical_operators):
4646
def test_logical_length_mismatch_raises(self, all_logical_operators):
4747
op_name = all_logical_operators
4848
a = pd.array([True, False, None], dtype="boolean")
49-
msg = "Lengths must match to compare"
49+
msg = "Lengths must match"
5050

5151
with pytest.raises(ValueError, match=msg):
5252
getattr(a, op_name)([True, False])

pandas/tests/arrays/integer/test_arithmetic.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,9 @@ def test_error(self, data, all_arithmetic_operators):
232232
result = opa(pd.DataFrame({"A": s}))
233233
assert result is NotImplemented
234234

235-
msg = r"can only perform ops with 1-d structures"
236-
with pytest.raises(NotImplementedError, match=msg):
235+
# msg = r"can only perform ops with 1-d structures"
236+
msg = "Lengths must match"
237+
with pytest.raises(ValueError, match=msg):
237238
opa(np.arange(len(s)).reshape(-1, len(s)))
238239

239240
@pytest.mark.parametrize("zero, negative", [(0, False), (0.0, False), (-0.0, True)])

pandas/tests/arrays/string_/test_string.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ def test_add_2d():
9898
a + b
9999

100100
s = pd.Series(a)
101-
with pytest.raises(ValueError, match="3 != 1"):
101+
with pytest.raises(ValueError, match="Lengths must match"):
102102
s + b
103103

104104

pandas/tests/indexes/interval/test_interval.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,7 @@ def test_comparison(self):
575575
msg = r"unorderable types: Interval\(\) > int\(\)"
576576
with pytest.raises(TypeError, match=msg):
577577
self.index > np.arange(2)
578-
msg = "Lengths must match to compare"
578+
msg = "Lengths must match"
579579
with pytest.raises(ValueError, match=msg):
580580
self.index > np.arange(3)
581581

0 commit comments

Comments
 (0)