@Zac-HD I’ve experimentally integrated ExceptionGroups (+ __note__
) into a library of mine (cattrs - 6 million downloads last month according to pypistats.org). The work is available on the tin/validation
branch.
I think the __note__
attribute turned out to be very useful.
Setup: two classes and an unstructured payload.
@define
class Inner:
a: int
@define
class Outer:
inners: list[Inner]
>>> payload = {"inners": [{"a": 1}, {"a": "not_an_int"}]}
When you try structuring, the exception:
>>> structure(payload, Outer)
+ Exception Group Traceback (most recent call last):
| File "<stdin>", line 1, in <module>
| File "/Users/tintvrtkovic/pg/cattrs/src/cattr/converters.py", line 308, in structure
| return self._structure_func.dispatch(cl)(obj, cl)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "<cattrs generated structure __main__.Outer>", line 9, in structure_Outer
| cattrs.errors.ClassValidationError: While structuring Outer
+-+---------------- 1 ----------------
| Exception Group Traceback (most recent call last):
| File "<cattrs generated structure __main__.Outer>", line 5, in structure_Outer
| File "/Users/tintvrtkovic/pg/cattrs/src/cattr/converters.py", line 500, in _structure_list
| raise IterableValidationError(f"While structuring {cl.__name__}", errors, cl)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| cattrs.errors.IterableValidationError: While structuring list
| Structuring class Outer @ attribute inners
+-+---------------- 1 ----------------
| Exception Group Traceback (most recent call last):
| File "/Users/tintvrtkovic/pg/cattrs/src/cattr/converters.py", line 493, in _structure_list
| res.append(handler(e, elem_type))
| ^^^^^^^^^^^^^^^^^^^^^
| File "<cattrs generated structure __main__.Inner>", line 9, in structure_Inner
| cattrs.errors.ClassValidationError: While structuring Inner
| Structuring list[__main__.Inner] @ index 1
+-+---------------- 1 ----------------
| Traceback (most recent call last):
| File "<cattrs generated structure __main__.Inner>", line 5, in structure_Inner
| ValueError: invalid literal for int() with base 10: 'not_an_int'
| Structuring class Inner @ attribute a
+------------------------------------
The notes essentially make detecting the exact problem spot easier. If you just look at the notes:
Structuring class Outer @ attribute inners
Structuring list[__main__.Inner] @ index 1
Structuring class Inner @ attribute a
It’s obvious the problem (the root ValueError) is at Outer.inners[1].a
.
I think the situation will be further improved when libraries like rich support ExceptionGroups. I could imagine the note being rendered in a different color in the terminal (or bold) to help it stand out.
Feel free to add any of this information to the PEP to help its case.