-
Notifications
You must be signed in to change notification settings - Fork 4k
GH-32007: [Python] Support arithmetic on arrays and scalars #48085
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
295bee0
d8bd508
e9219b9
74aabc3
14d727e
76f031e
9ac3b49
bc7aafc
3d99be6
9ce8cd8
1110f09
b0feca6
aead5ad
a2d831d
e2b9d06
d1451b7
10104d6
72390ed
b765549
71b246f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,6 +35,7 @@ | |
| import pyarrow as pa | ||
| import pyarrow.tests.strategies as past | ||
| from pyarrow.vendored.version import Version | ||
| import pyarrow.compute as pc | ||
|
|
||
|
|
||
| @pytest.mark.processes | ||
|
|
@@ -4398,3 +4399,72 @@ def test_non_cpu_array(): | |
| arr.tolist() | ||
| with pytest.raises(NotImplementedError): | ||
| arr.validate(full=True) | ||
|
|
||
|
|
||
| def test_arithmetic_dunders(): | ||
| # GH-32007 | ||
| arr1 = pa.array([-1.1, 2.2, -3.3]) | ||
| arr2 = pa.array([2.2, 4.4, 5.5]) | ||
|
|
||
| assert (arr1 + arr2).equals(pc.add_checked(arr1, arr2)) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we really want to assert the "checked" aspect, then we should also include a case where overflow occurs.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The overall intention of this was to test that the dunder methods have the same output given the same input (kernels as well). Albeit, your suggestion is valid, so added extra tests to cover whether dunder methods indeed overflow. |
||
| assert (arr2 / arr1).equals(pc.divide_checked(arr2, arr1)) | ||
| assert (arr1 * arr2).equals(pc.multiply_checked(arr1, arr2)) | ||
| assert (-arr1).equals(pc.negate_checked(arr1)) | ||
| assert (arr1 ** 2).equals(pc.power_checked(arr1, 2)) | ||
| assert (arr1 - arr2).equals(pc.subtract_checked(arr1, arr2)) | ||
|
|
||
|
|
||
| def test_bitwise_dunders(): | ||
| # GH-32007 | ||
| arr1 = pa.array([-1, 2, -3]) | ||
| arr2 = pa.array([2, 4, 5]) | ||
|
|
||
| assert (arr1 & arr2).equals(pc.bit_wise_and(arr1, arr2)) | ||
| assert (arr1 | arr2).equals(pc.bit_wise_or(arr1, arr2)) | ||
| assert (arr1 ^ arr2).equals(pc.bit_wise_xor(arr1, arr2)) | ||
| assert (arr1 << arr2).equals(pc.shift_left_checked(arr1, arr2)) | ||
| assert (arr1 >> arr2).equals(pc.shift_right_checked(arr1, arr2)) | ||
|
|
||
|
|
||
| def test_dunders_unmatching_types(): | ||
| # GH-32007 | ||
| error_match = r"Function '\w+' has no kernel matching input types" | ||
| string_arr = pa.array(["a", "b", "c"]) | ||
| nested_arr = pa.array([{"x": 1, "y": True}, {"z": 3.4, "x": 4}]) | ||
| double_arr = pa.array([1.0, 2.0, 3.0]) | ||
|
|
||
| with pytest.raises(pa.ArrowNotImplementedError, match=error_match): | ||
| string_arr + nested_arr | ||
| with pytest.raises(pa.ArrowNotImplementedError, match=error_match): | ||
| string_arr - double_arr | ||
| with pytest.raises(pa.ArrowNotImplementedError, match=error_match): | ||
| double_arr * nested_arr | ||
|
|
||
|
|
||
| def test_dunders_mixed_types(): | ||
| # GH-32007 | ||
| arr = pa.array([11.0, 17.0, 23.0]) | ||
| val = pa.scalar(3) | ||
|
|
||
| assert (arr + val).equals(pc.add_checked(arr, val)) | ||
| assert (arr - val).equals(pc.subtract_checked(arr, val)) | ||
| assert (arr / val).equals(pc.divide_checked(arr, val)) | ||
| assert (arr * val).equals(pc.multiply_checked(arr, val)) | ||
| assert (arr ** val).equals(pc.power_checked(arr, val)) | ||
|
|
||
|
|
||
| def test_dunders_checked_overflow(): | ||
| # GH-32007 | ||
| arr = pa.array([127, -128], type=pa.int8()) | ||
| error_match = "overflow" | ||
|
|
||
| with pytest.raises(pa.ArrowInvalid, match=error_match): | ||
| arr + arr | ||
| with pytest.raises(pa.ArrowInvalid, match=error_match): | ||
| arr * arr | ||
| with pytest.raises(pa.ArrowInvalid, match=error_match): | ||
| arr - (-arr) | ||
| with pytest.raises(pa.ArrowInvalid, match=error_match): | ||
| arr ** pa.scalar(2, type=pa.int8()) | ||
| with pytest.raises(pa.ArrowInvalid, match=error_match): | ||
| arr / (-arr) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can I simply call
arr1 - 42or would that not work?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would work, yes. I wanted to show in the docstrings that the users can also use explicit scalars, that's why I went with this.