pytest-dev/pytest · error · TypeError
pytest.approx() only supports ordered sequences, but got
Error message
pytest.approx() only supports ordered sequences, but got: {expected!r} What it means
Raised by the approx() factory when expected is a Collection (and not str/bytes) but is not ordered — i.e., it lacks __getitem__ or is not a Sequence. The dispatch first checks Decimal, Mapping, numpy array, then sequence-like objects; an unordered collection (e.g. a set) falls through to the Collection branch and is rejected because approx comparison needs positional correspondence. datetime/timedelta and scalars are handled in later branches.
Solutions
- Convert to a sorted list: approx(sorted(my_set)).
- Convert to a tuple preserving intended order: approx(tuple(my_collection)).
- For unordered comparison, compare as a set explicitly rather than via approx().
Example fix
// before
assert result_set == approx({1, 2, 3})
// after
assert sorted(result_set) == approx(sorted([1, 2, 3])) Defensive patterns
Strategy: type-guard
Validate before calling
from collections.abc import Collection, Sequence
def approx_collection(expected, **kw):
if isinstance(expected, Collection) and not isinstance(expected, (str, bytes, Sequence)):
expected = sorted(expected)
return approx(expected, **kw) Type guard
from collections.abc import Sequence
def is_approximable_sequence(v) -> bool:
return isinstance(v, Sequence) or hasattr(v, '__getitem__') Prevention
- Convert sets to sorted lists before approx().
- Check the type is a Sequence (not just Collection) before approximating.
When it happens
Trigger: approx({1, 2, 3}) (a set); approx(frozenset(...)); approx(some_custom_collection_without_getitem).
Common situations: Asserting on set-valued results without converting to a sorted list; using approx on unordered collection types; custom collections that register as Collection but aren't subscriptable.
Related errors
- absolute tolerance for datetime/timedelta must be a…
- pytest.approx() does not support nested data structures
- relative tolerance for timedelta must be a number, got
- absolute tolerance can't be NaN.
- absolute tolerance can't be negative
AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11).
Data as JSON: /api/errors/50f8fc0d14e4a927.
Report an issue: GitHub.
Appendix: source
Thrown at src/_pytest/approx.py:967
# The actual logic for making approximate comparisons can be found in
# ApproxScalar, which is used to compare individual numbers. All of the
# other Approx classes eventually delegate to this class. The ApproxBase
# class provides some convenient methods and overloads, but isn't really
# essential.
__tracebackhide__ = True
if isinstance(expected, Decimal):
return ApproxDecimal(expected, rel=rel, abs=abs, nan_ok=nan_ok) # type: ignore[return-value]
elif isinstance(expected, Mapping):
return ApproxMapping(expected, rel=rel, abs=abs, nan_ok=nan_ok) # type: ignore[return-value]
elif (np_array := _as_numpy_array(expected)) is not None:
return ApproxNumpy(np_array, rel=rel, abs=abs, nan_ok=nan_ok)
elif _is_sequence_like(expected):
return ApproxSequenceLike(expected, rel=rel, abs=abs, nan_ok=nan_ok) # type: ignore[return-value]
elif isinstance(expected, Collection) and not isinstance(expected, str | bytes):
msg = f"pytest.approx() only supports ordered sequences, but got: {expected!r}"
raise TypeError(msg)
elif isinstance(expected, (datetime, timedelta)):
return ApproxTimedelta(expected, rel=rel, abs=abs, nan_ok=nan_ok) # type: ignore[return-value]
else:
return ApproxScalar(expected, rel=rel, abs=abs, nan_ok=nan_ok)
def _is_sequence_like(expected: object) -> TypeGuard[Sequence[Any]]:
return (
hasattr(expected, "__getitem__")
and isinstance(expected, Sized)
and not isinstance(expected, str | bytes)
)
def _as_numpy_array(obj: object) -> ndarray | None:
"""
Return an ndarray if the given object is implicitly convertible to ndarray,
and numpy is already imported, otherwise None.View on GitHub (pinned to 0d6fbdeffa)