{"record":{"id":"edcf92cb9d366e2a","repo":"pytest-dev/pytest","slug":"pytest-approx-does-not-support-nested-data-struc","errorCode":null,"errorMessage":"pytest.approx() does not support nested data structures: {!r} at index {}\n  full sequence: {}","messagePattern":"pytest\\.approx\\(\\) does not support nested data structures: (.+?) at index (.+?)\n  full sequence: (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/_pytest/approx.py","lineNumber":363,"sourceCode":"            yield actual[k], self.expected[k]\n\n\nclass ApproxSequenceLike(Approx[Sequence[Any]]):\n    \"\"\"Perform approximate comparisons where the expected value is a sequence of numbers.\"\"\"\n\n    def __init__(\n        self,\n        expected: Sequence[Any],\n        rel: float | Decimal | timedelta | None,\n        abs: float | Decimal | timedelta | None,\n        nan_ok: bool,\n    ) -> None:\n        __tracebackhide__ = True\n\n        for index, x in enumerate(expected):\n            if isinstance(x, type(expected)):\n                msg = \"pytest.approx() does not support nested data structures: {!r} at index {}\\n  full sequence: {}\"\n                raise TypeError(msg.format(x, index, pprint.pformat(expected)))\n\n        super().__init__(expected, rel=rel, abs=abs, nan_ok=nan_ok)\n\n    def __repr__(self) -> str:\n        seq_type = type(self.expected)\n        if seq_type not in (tuple, list):\n            seq_type = list\n        return f\"approx({seq_type(self._approx_scalar(x) for x in self.expected)!r})\"\n\n    def _repr_compare(self, other_side: Sequence[float]) -> list[str]:\n        import math\n\n        if len(self.expected) != len(other_side):\n            return [\n                \"Impossible to compare lists with different sizes.\",\n                f\"Lengths: {len(self.expected)} and {len(other_side)}\",\n            ]\n","sourceCodeStart":345,"sourceCodeEnd":381,"githubUrl":"https://github.com/pytest-dev/pytest/blob/0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc/src/_pytest/approx.py#L345-L381","documentation":"ApproxSequenceLike.__init__ rejects any element whose type matches the expected sequence's own type (e.g. a list inside a list, a tuple inside a tuple). pytest's sequence approximation is intentionally single-level: it zips expected and actual element-by-element. Nested sequences would be ambiguous about how to apply tolerance, so they are rejected up front with the offending element, its index, and the full sequence pretty-printed.","triggerScenarios":"Calling approx([[1.0, 2.0], [3.0, 4.0]]), approx([(1.0, 2.0)]) where the element is the same sequence type, or approx on a custom Sequence subclass whose items are also that subclass. Triggered at ApproxSequenceLike.__init__ (src/_pytest/approx.py:360-363). Note: lists inside tuples or tuples inside lists are allowed because only same-type nesting is checked.","commonSituations":"Matrix/multi-dimensional data represented as nested lists; comparing batched numerical results; converting numpy arrays to nested lists for comparison.","solutions":["Use a numpy array and approx(np.array(...)) for multi-dimensional numeric data.","Compare each inner sequence separately: `for e, a in zip(expected, actual): assert a == approx(e)`.","Convert the outer container so inner and outer are different sequence types (e.g. tuple of lists)."],"exampleFix":"# before\nassert actual == approx([[1.0, 2.0], [3.0, 4.0]])\n# after\nimport numpy as np\nassert np.array(actual) == approx(np.array([[1.0, 2.0], [3.0, 4.0]]))","handlingStrategy":"validation","validationCode":"from collections.abc import Sequence\ndef is_flat_sequence(seq) -> bool:\n    seq_t = type(seq)\n    return all(not isinstance(x, seq_t) for x in seq)\n# usage\nif is_flat_sequence(expected):\n    assert actual == approx(expected)\nelse:\n    import numpy as np\n    assert np.array(actual) == approx(np.array(expected))","typeGuard":"from collections.abc import Sequence\ndef is_flat_numeric_sequence(obj) -> bool:\n    return (\n        isinstance(obj, Sequence)\n        and not isinstance(obj, (str, bytes))\n        and all(not isinstance(x, type(obj)) for x in obj)\n    )","tryCatchPattern":null,"preventionTips":["Use numpy arrays + approx() for multi-dimensional numeric data.","Compare inner sequences individually in a loop.","Mix sequence types (tuple of lists) only as an explicit workaround."],"tags":["pytest","approx","sequence","nested-structure","list"],"backgroundTag":null,"analyzedSha":"0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc","analyzedAt":"2026-08-11T20:52:36.969Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}