From c07752649fa96f4f0226e11cdbc67d8f3fd0d922 Mon Sep 17 00:00:00 2001 From: poulami-sau <109125687+poulami-sau@users.noreply.github.com> Date: Sun, 21 Apr 2024 20:40:46 -0400 Subject: [PATCH 01/11] added conversion of other_side to numpy array --- src/_pytest/python_api.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 0ba86e816d3..750769af7dd 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -163,6 +163,9 @@ def get_value_from_nested_list( self._approx_scalar, self.expected.tolist() ) + # convert other_side to numpy array to ensure shape attribute is available + other_side = _as_numpy_array(other_side) + if np_array_shape != other_side.shape: return [ "Impossible to compare arrays with different shapes.", From 485e8ef564889ce81cc0caf222471a3fa323ef12 Mon Sep 17 00:00:00 2001 From: poulami-sau <109125687+poulami-sau@users.noreply.github.com> Date: Sun, 21 Apr 2024 20:46:53 -0400 Subject: [PATCH 02/11] added test case in testing/python/approx.py based on test case provided by reporter in issue #12114 --- testing/python/approx.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/testing/python/approx.py b/testing/python/approx.py index 079667bd093..6a58cabfff3 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -763,6 +763,23 @@ def test_numpy_array_wrong_shape(self): assert a12 != approx(a21) assert a21 != approx(a12) + def test_numpy_array_implicit_conversion(self): + np = pytest.importorskip("numpy") + + class ImplicitArray: + """Type which is implicitly convertible to a numpy array.""" + + def __init__(self, vals): + self.vals = vals + + def __array__(self, dtype=None, copy=None): + print("called __array__ in ImplicitArray") + return np.array(self.vals) + + vec1 = ImplicitArray([1.0, 2.0, 3.0]) + vec2 = ImplicitArray([1.0, 2.0, 4.0]) + assert vec1 != approx(vec2) + def test_numpy_array_protocol(self): """ array-like objects such as tensorflow's DeviceArray are handled like ndarray. From 3989384cecfad34deebbd9100b110afe041ae7ef Mon Sep 17 00:00:00 2001 From: poulami-sau <109125687+poulami-sau@users.noreply.github.com> Date: Sun, 21 Apr 2024 20:47:17 -0400 Subject: [PATCH 03/11] added test case in testing/python/approx.py based on test case provided by reporter in issue #12114 --- testing/python/approx.py | 1 + 1 file changed, 1 insertion(+) diff --git a/testing/python/approx.py b/testing/python/approx.py index 6a58cabfff3..91cb666c5da 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -778,6 +778,7 @@ def __array__(self, dtype=None, copy=None): vec1 = ImplicitArray([1.0, 2.0, 3.0]) vec2 = ImplicitArray([1.0, 2.0, 4.0]) + # see issue #12114 for test case assert vec1 != approx(vec2) def test_numpy_array_protocol(self): From bdd952282aee9bd6f9845d1d18f7707b936c201b Mon Sep 17 00:00:00 2001 From: poulami-sau <109125687+poulami-sau@users.noreply.github.com> Date: Sun, 21 Apr 2024 20:49:44 -0400 Subject: [PATCH 04/11] added .travis.yml to test on travis ci --- .travis.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000000..12959730775 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,11 @@ +language: python + +rvm: + - "3.9" + +install: + - pip install --user pre-commit + - pip install tox + +script: + - pytest testing/python/approx.py From 72903386ad26d0a926efb9f7ed200c56b7a1da80 Mon Sep 17 00:00:00 2001 From: poulami-sau <109125687+poulami-sau@users.noreply.github.com> Date: Sun, 21 Apr 2024 20:54:03 -0400 Subject: [PATCH 05/11] edited travis file --- .travis.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 12959730775..d901dbc2b3b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,9 +3,5 @@ language: python rvm: - "3.9" -install: - - pip install --user pre-commit - - pip install tox - script: - pytest testing/python/approx.py From 9fb207e78a0b957b5bbbcb1f7758cd44885c8203 Mon Sep 17 00:00:00 2001 From: poulami-sau <109125687+poulami-sau@users.noreply.github.com> Date: Sun, 21 Apr 2024 20:58:41 -0400 Subject: [PATCH 06/11] deleted travis file --- .travis.yml | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index d901dbc2b3b..00000000000 --- a/.travis.yml +++ /dev/null @@ -1,7 +0,0 @@ -language: python - -rvm: - - "3.9" - -script: - - pytest testing/python/approx.py From b5ee309a2c54f9e71ca7f21aa7ed7304ba9b68c5 Mon Sep 17 00:00:00 2001 From: poulami-sau <109125687+poulami-sau@users.noreply.github.com> Date: Sun, 21 Apr 2024 21:04:28 -0400 Subject: [PATCH 07/11] test cases pass for pytest testing/python/approx.py --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index 7c35a615232..d7148acfc51 100644 --- a/AUTHORS +++ b/AUTHORS @@ -321,6 +321,7 @@ Pierre Sassoulas Pieter Mulder Piotr Banaszkiewicz Piotr Helm +Poulami Sau Prakhar Gurunani Prashant Anand Prashant Sharma From 6fa6835aa9aee709422b4f1cca9f948b55e60bc5 Mon Sep 17 00:00:00 2001 From: poulami-sau <109125687+poulami-sau@users.noreply.github.com> Date: Sun, 21 Apr 2024 21:37:13 -0400 Subject: [PATCH 08/11] idk --- changelog/12114.bugfix.rst | 1 + testing/python/approx.py | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) create mode 100644 changelog/12114.bugfix.rst diff --git a/changelog/12114.bugfix.rst b/changelog/12114.bugfix.rst new file mode 100644 index 00000000000..79849692505 --- /dev/null +++ b/changelog/12114.bugfix.rst @@ -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. diff --git a/testing/python/approx.py b/testing/python/approx.py index 91cb666c5da..875c8989106 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -773,12 +773,10 @@ def __init__(self, vals): self.vals = vals def __array__(self, dtype=None, copy=None): - print("called __array__ in ImplicitArray") return np.array(self.vals) vec1 = ImplicitArray([1.0, 2.0, 3.0]) vec2 = ImplicitArray([1.0, 2.0, 4.0]) - # see issue #12114 for test case assert vec1 != approx(vec2) def test_numpy_array_protocol(self): From f673c0771908c81b52f4368350e165d2336a0153 Mon Sep 17 00:00:00 2001 From: poulami-sau <109125687+poulami-sau@users.noreply.github.com> Date: Sun, 21 Apr 2024 21:57:52 -0400 Subject: [PATCH 09/11] added print statement in test case --- testing/python/approx.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/testing/python/approx.py b/testing/python/approx.py index 875c8989106..91cb666c5da 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -773,10 +773,12 @@ def __init__(self, vals): self.vals = vals def __array__(self, dtype=None, copy=None): + print("called __array__ in ImplicitArray") return np.array(self.vals) vec1 = ImplicitArray([1.0, 2.0, 3.0]) vec2 = ImplicitArray([1.0, 2.0, 4.0]) + # see issue #12114 for test case assert vec1 != approx(vec2) def test_numpy_array_protocol(self): From 314ef0424a205b206e03f09f1f16c7b6d545462f Mon Sep 17 00:00:00 2001 From: poulami-sau <109125687+poulami-sau@users.noreply.github.com> Date: Sun, 21 Apr 2024 21:58:12 -0400 Subject: [PATCH 10/11] removed print statement in test case --- testing/python/approx.py | 1 - 1 file changed, 1 deletion(-) diff --git a/testing/python/approx.py b/testing/python/approx.py index 91cb666c5da..968e8828512 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -773,7 +773,6 @@ def __init__(self, vals): self.vals = vals def __array__(self, dtype=None, copy=None): - print("called __array__ in ImplicitArray") return np.array(self.vals) vec1 = ImplicitArray([1.0, 2.0, 3.0]) From 476d9d07d6bfb3e83896abf6e85eb95c6dad405d Mon Sep 17 00:00:00 2001 From: poulami-sau <109125687+poulami-sau@users.noreply.github.com> Date: Mon, 22 Apr 2024 09:52:35 -0400 Subject: [PATCH 11/11] expanded the type annotation to include objects which may cast to a array and renamed other_side to other_side_as_array and asserted that it is not none --- src/_pytest/python_api.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 750769af7dd..7d89fdd809e 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -142,7 +142,7 @@ def __repr__(self) -> str: ) 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 @@ -164,12 +164,13 @@ def get_value_from_nested_list( ) # convert other_side to numpy array to ensure shape attribute is available - other_side = _as_numpy_array(other_side) + other_side_as_array = _as_numpy_array(other_side) + assert other_side_as_array is not None - if np_array_shape != other_side.shape: + 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 @@ -178,7 +179,7 @@ def get_value_from_nested_list( 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) if approx_value != other_value: abs_diff = abs(approx_value.expected - other_value) max_abs_diff = max(max_abs_diff, abs_diff) @@ -191,7 +192,7 @@ def get_value_from_nested_list( 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