From 051d7a3433d1e2fc42b84f77331af84b737fe0d4 Mon Sep 17 00:00:00 2001 From: AD Date: Wed, 18 Jun 2025 21:51:15 +0530 Subject: [PATCH 1/7] Made the necessary changes --- src/_pytest/python_api.py | 19 +++++++++++++++++++ testing/python/approx.py | 6 ++++++ 2 files changed, 25 insertions(+) diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 07794abea95..41779746f85 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -530,6 +530,25 @@ class ApproxDecimal(ApproxScalar): DEFAULT_ABSOLUTE_TOLERANCE = Decimal("1e-12") DEFAULT_RELATIVE_TOLERANCE = Decimal("1e-6") + def __repr__(self) -> str: + if isinstance(self.rel, float): + rel = Decimal.from_float(self.rel) + else: + rel = self.rel + + if isinstance(self.abs, float): + abs_ = Decimal.from_float(self.abs) + else: + abs_ = self.abs + + if rel is not None and Decimal("1e-3") <= rel <= Decimal("1e3"): + tol_str = f"{rel:.1e}" + elif abs_ is not None: + tol_str = f"{abs_:.1e}" + else: + tol_str = "???" + + return f"{self.expected} ± {tol_str}" def approx(expected, rel=None, abs=None, nan_ok: bool = False) -> ApproxBase: """Assert that two numbers (or two ordered sequences of numbers) are equal to each other diff --git a/testing/python/approx.py b/testing/python/approx.py index 75b57b6965c..b5cfecf7da4 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -1015,6 +1015,12 @@ def __len__(self): expected_repr = "approx([1 ± 1.0e-06, 2 ± 2.0e-06, 3 ± 3.0e-06, 4 ± 4.0e-06])" assert repr(approx(expected)) == expected_repr + def test_decimal_approx_repr(self, monkeypatch): + monkeypatch.setitem(decimal.getcontext().traps, decimal.FloatOperation, True) + approx_obj = pytest.approx(decimal.Decimal("2.60")) + print(f"Attempting to represent pytest.approx(Decimal): {approx_obj}") + assert decimal.Decimal("2.600001") == approx_obj + def test_allow_ordered_sequences_only(self) -> None: """pytest.approx() should raise an error on unordered sequences (#9692).""" with pytest.raises(TypeError, match="only supports ordered sequences"): From cb81ab4a7900bcf33b47de0de2cf2996121edd36 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 18 Jun 2025 16:22:59 +0000 Subject: [PATCH 2/7] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/_pytest/python_api.py | 1 + testing/python/approx.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 41779746f85..1db667fcbe5 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -550,6 +550,7 @@ def __repr__(self) -> str: return f"{self.expected} ± {tol_str}" + def approx(expected, rel=None, abs=None, nan_ok: bool = False) -> ApproxBase: """Assert that two numbers (or two ordered sequences of numbers) are equal to each other within some tolerance. diff --git a/testing/python/approx.py b/testing/python/approx.py index b5cfecf7da4..88139d7e224 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -1018,7 +1018,7 @@ def __len__(self): def test_decimal_approx_repr(self, monkeypatch): monkeypatch.setitem(decimal.getcontext().traps, decimal.FloatOperation, True) approx_obj = pytest.approx(decimal.Decimal("2.60")) - print(f"Attempting to represent pytest.approx(Decimal): {approx_obj}") + print(f"Attempting to represent pytest.approx(Decimal): {approx_obj}") assert decimal.Decimal("2.600001") == approx_obj def test_allow_ordered_sequences_only(self) -> None: From 9c22774c7146381dfe6819a2ceae0eebce9b3033 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 18 Jun 2025 17:52:07 -0300 Subject: [PATCH 3/7] Create 13530.bugfix.rst --- changelog/13530.bugfix.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/13530.bugfix.rst diff --git a/changelog/13530.bugfix.rst b/changelog/13530.bugfix.rst new file mode 100644 index 00000000000..81bcd4c6adb --- /dev/null +++ b/changelog/13530.bugfix.rst @@ -0,0 +1 @@ +Fixed a crash when using :func:`pytest.approx` and :class:`decimal.Decimal` instances with ``decimal.FloatOperation`` trap set. From d6e79eafd9d9013e5ec2d4e2564222968b0e9375 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 18 Jun 2025 17:52:27 -0300 Subject: [PATCH 4/7] Update testing/python/approx.py --- testing/python/approx.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/python/approx.py b/testing/python/approx.py index 88139d7e224..81645fc9de6 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -1015,7 +1015,7 @@ def __len__(self): expected_repr = "approx([1 ± 1.0e-06, 2 ± 2.0e-06, 3 ± 3.0e-06, 4 ± 4.0e-06])" assert repr(approx(expected)) == expected_repr - def test_decimal_approx_repr(self, monkeypatch): + def test_decimal_approx_repr(self, monkeypatch) -> None: monkeypatch.setitem(decimal.getcontext().traps, decimal.FloatOperation, True) approx_obj = pytest.approx(decimal.Decimal("2.60")) print(f"Attempting to represent pytest.approx(Decimal): {approx_obj}") From 620aaadfe5ac183551566d8a9a896b8ebb353a44 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 18 Jun 2025 17:54:39 -0300 Subject: [PATCH 5/7] Improve changelog --- changelog/13530.bugfix.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog/13530.bugfix.rst b/changelog/13530.bugfix.rst index 81bcd4c6adb..1a5ab365f12 100644 --- a/changelog/13530.bugfix.rst +++ b/changelog/13530.bugfix.rst @@ -1 +1 @@ -Fixed a crash when using :func:`pytest.approx` and :class:`decimal.Decimal` instances with ``decimal.FloatOperation`` trap set. +Fixed a crash when using :func:`pytest.approx` and :class:`decimal.Decimal` instances with the :class:`decimal.FloatOperation` trap set. From 3001a554af363cca54a38c06c2249e841a3a2558 Mon Sep 17 00:00:00 2001 From: Aditi De <92822822+coder-aditi@users.noreply.github.com> Date: Thu, 19 Jun 2025 11:57:08 +0530 Subject: [PATCH 6/7] Removed debugging statement from testing/python/approx.py Co-authored-by: Bruno Oliveira --- testing/python/approx.py | 1 - 1 file changed, 1 deletion(-) diff --git a/testing/python/approx.py b/testing/python/approx.py index 81645fc9de6..6b46db3df65 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -1018,7 +1018,6 @@ def __len__(self): def test_decimal_approx_repr(self, monkeypatch) -> None: monkeypatch.setitem(decimal.getcontext().traps, decimal.FloatOperation, True) approx_obj = pytest.approx(decimal.Decimal("2.60")) - print(f"Attempting to represent pytest.approx(Decimal): {approx_obj}") assert decimal.Decimal("2.600001") == approx_obj def test_allow_ordered_sequences_only(self) -> None: From aa510b9b85cee60638b7abbfeb6cd9793fd28bbe Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 22 Jun 2025 12:56:08 -0300 Subject: [PATCH 7/7] Fix import --- src/_pytest/python_api.py | 3 +-- testing/python/approx.py | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 1db667fcbe5..b732b452683 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -541,12 +541,11 @@ def __repr__(self) -> str: else: abs_ = self.abs + tol_str = "???" if rel is not None and Decimal("1e-3") <= rel <= Decimal("1e3"): tol_str = f"{rel:.1e}" elif abs_ is not None: tol_str = f"{abs_:.1e}" - else: - tol_str = "???" return f"{self.expected} ± {tol_str}" diff --git a/testing/python/approx.py b/testing/python/approx.py index 6b46db3df65..2ca7ee70945 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -2,6 +2,7 @@ from __future__ import annotations from contextlib import contextmanager +import decimal from decimal import Decimal from fractions import Fraction from math import sqrt