Skip to content
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

Fixed Bug Regarding Attribute Error in pytest.approx For Types Implicitly Convertible to Numpy Arrays #12232

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ Pierre Sassoulas
Pieter Mulder
Piotr Banaszkiewicz
Piotr Helm
Poulami Sau
Prakhar Gurunani
Prashant Anand
Prashant Sharma
Expand Down
1 change: 1 addition & 0 deletions changelog/12114.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed attribute error in pytest.approx for types implicitly convertible to numpy arrays by converting other_side to a numpy array so that np_array_shape != other_side.shape can be properly checked.
14 changes: 9 additions & 5 deletions src/_pytest/python_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@
)
return f"approx({list_scalars!r})"

def _repr_compare(self, other_side: "ndarray") -> List[str]:
def _repr_compare(self, other_side: Union["ndarray", List[Any]]) -> List[str]:
import itertools
import math

Expand All @@ -163,10 +163,14 @@
self._approx_scalar, self.expected.tolist()
)

if np_array_shape != other_side.shape:
# convert other_side to numpy array to ensure shape attribute is available
other_side_as_array = _as_numpy_array(other_side)
assert other_side_as_array is not None

Check warning on line 168 in src/_pytest/python_api.py

View check run for this annotation

Codecov / codecov/patch

src/_pytest/python_api.py#L167-L168

Added lines #L167 - L168 were not covered by tests
RonnyPfannschmidt marked this conversation as resolved.
Show resolved Hide resolved

if np_array_shape != other_side_as_array.shape:
return [
"Impossible to compare arrays with different shapes.",
f"Shapes: {np_array_shape} and {other_side.shape}",
f"Shapes: {np_array_shape} and {other_side_as_array.shape}",
]

number_of_elements = self.expected.size
Expand All @@ -175,7 +179,7 @@
different_ids = []
for index in itertools.product(*(range(i) for i in np_array_shape)):
approx_value = get_value_from_nested_list(approx_side_as_seq, index)
other_value = get_value_from_nested_list(other_side, index)
other_value = get_value_from_nested_list(other_side_as_array, index)

Check warning on line 182 in src/_pytest/python_api.py

View check run for this annotation

Codecov / codecov/patch

src/_pytest/python_api.py#L182

Added line #L182 was not covered by tests
if approx_value != other_value:
abs_diff = abs(approx_value.expected - other_value)
max_abs_diff = max(max_abs_diff, abs_diff)
Expand All @@ -188,7 +192,7 @@
message_data = [
(
str(index),
str(get_value_from_nested_list(other_side, index)),
str(get_value_from_nested_list(other_side_as_array, index)),
str(get_value_from_nested_list(approx_side_as_seq, index)),
)
for index in different_ids
Expand Down
17 changes: 17 additions & 0 deletions testing/python/approx.py
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,23 @@
assert a12 != approx(a21)
assert a21 != approx(a12)

def test_numpy_array_implicit_conversion(self):
np = pytest.importorskip("numpy")

class ImplicitArray:

Check warning on line 769 in testing/python/approx.py

View check run for this annotation

Codecov / codecov/patch

testing/python/approx.py#L769

Added line #L769 was not covered by tests
"""Type which is implicitly convertible to a numpy array."""

def __init__(self, vals):
self.vals = vals

Check warning on line 773 in testing/python/approx.py

View check run for this annotation

Codecov / codecov/patch

testing/python/approx.py#L772-L773

Added lines #L772 - L773 were not covered by tests

def __array__(self, dtype=None, copy=None):
return np.array(self.vals)

Check warning on line 776 in testing/python/approx.py

View check run for this annotation

Codecov / codecov/patch

testing/python/approx.py#L775-L776

Added lines #L775 - L776 were not covered by tests

vec1 = ImplicitArray([1.0, 2.0, 3.0])
vec2 = ImplicitArray([1.0, 2.0, 4.0])

Check warning on line 779 in testing/python/approx.py

View check run for this annotation

Codecov / codecov/patch

testing/python/approx.py#L778-L779

Added lines #L778 - L779 were not covered by tests
# see issue #12114 for test case
assert vec1 != approx(vec2)

Check warning on line 781 in testing/python/approx.py

View check run for this annotation

Codecov / codecov/patch

testing/python/approx.py#L781

Added line #L781 was not covered by tests

def test_numpy_array_protocol(self):
"""
array-like objects such as tensorflow's DeviceArray are handled like ndarray.
Expand Down
Loading