From 87dfbb4013dea86238fc72d5addf0eae788f7d4b Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 23 Feb 2022 08:25:00 -0300 Subject: [PATCH] Disallow unordered sequences in pytest.approx Fix #9692 --- changelog/9692.improvement.rst | 1 + src/_pytest/python_api.py | 7 +++++-- testing/python/approx.py | 5 +++++ 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 changelog/9692.improvement.rst diff --git a/changelog/9692.improvement.rst b/changelog/9692.improvement.rst new file mode 100644 index 00000000000..2e1df4740bc --- /dev/null +++ b/changelog/9692.improvement.rst @@ -0,0 +1 @@ +:func:`pytest.approx` now raises a :class:`TypeError` when given an unordered sequence (such as :class:`set`). diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 9891946cd1e..2543a33d834 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -311,7 +311,7 @@ class ApproxSequencelike(ApproxBase): def __repr__(self) -> str: seq_type = type(self.expected) - if seq_type not in (tuple, list, set): + if seq_type not in (tuple, list): seq_type = list return "approx({!r})".format( seq_type(self._approx_scalar(x) for x in self.expected) @@ -372,6 +372,9 @@ def _yield_comparisons(self, actual): def _check_type(self) -> None: __tracebackhide__ = True + if not isinstance(self.expected, Sequence): + msg = f"pytest.approx() only supports ordered sequences, but got: {repr(self.expected)}" + raise TypeError(msg) for index, x in enumerate(self.expected): if isinstance(x, type(self.expected)): msg = "pytest.approx() does not support nested data structures: {!r} at index {}\n full sequence: {}" @@ -515,7 +518,7 @@ class ApproxDecimal(ApproxScalar): def approx(expected, rel=None, abs=None, nan_ok: bool = False) -> ApproxBase: - """Assert that two numbers (or two sets of numbers) are equal to each other + """Assert that two numbers (or two ordered sequences of numbers) are equal to each other within some tolerance. Due to the :std:doc:`tutorial/floatingpoint`, numbers that we diff --git a/testing/python/approx.py b/testing/python/approx.py index eb9bcd874c0..5f806566428 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -868,3 +868,8 @@ def __len__(self): expected = MySizedIterable() assert [1, 2, 3, 4] == approx(expected) + + 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"): + assert {1, 2, 3} == approx({1, 2, 3})