- cattrs version: 22.1.0.dev0
- Python version: 3.7.5
- Operating System: macOS Monterey (12.2.1)
Description
This is referring to the _exceptions attribute on some of the exceptions raised in cattrs when structuring
I was trying to use cattrs inbuilt exceptions for structuring nested attrs classes. I noticed that in this case, KeyError and TypeError exceptions are nested to exactly where the issue occurred, which is great!
But I was expecting the same type of formatting to show up for Value Errors, which is not the case, they don't specify where the issue was caused. Similar issue happens for when there are extra Fields (Also, I think there should be a separate Exception class for that, but I'll make a new issue for that — #237 )
Also, should _exceptions be made public ?
What I Did
POC of issue:
import cattrs
from cattrs.errors import ClassValidationError
from attrs import define, field
from attrs.validators import lt
@define
class _InnerInnerClass:
f_inner_inner: int
@define
class _InnerClass:
f_inner_1: int
f_inner_2: int = field(validator=lt(2))
inner_inner_props: _InnerInnerClass
@define
class ComposedClass:
inner_props: _InnerClass
f: str
def make_my_class(payload, payload_kind):
print(f"PAYLOAD_TYPE={payload_kind}")
c = cattrs.GenConverter(forbid_extra_keys=True)
try:
c.structure(payload, ComposedClass)
except ClassValidationError as ex:
print(ex.__dict__, end="\n\n")
return
print("Success", end="\n\n")
if __name__ == "__main__":
success_payload = {
"f": "outer_most_string",
"inner_props": {
"f_inner_1": 10,
"f_inner_2": 1,
"inner_inner_props": {"f_inner_inner": 99},
},
}
make_my_class(success_payload, "SUCCESS")
value_error_payload = {
"f": "outer_most_string",
"inner_props": {
"f_inner_1": 10,
"f_inner_2": 12, # Bad value
"inner_inner_props": {"f_inner_inner": 99},
},
}
make_my_class(value_error_payload, "BAD_VALUE")
type_error_payload = {
"f": "outer_most_string",
"inner_props": {
"f_inner_1": 10,
"f_inner_2": None, # Bad type
"inner_inner_props": {"f_inner_inner": 99},
},
}
make_my_class(type_error_payload, "BAD_TYPE")
# Missing/Bad Key
key_error_payload = {
"f": "outer_most_string",
"inner_props": {
"f_inner_1": 10,
"f_inner_2_bad_key": 12,
"inner_inner_props": {"f_inner_inner": 99},
},
}
make_my_class(key_error_payload, "BAD_KEY")
extra_fields_payload = {
"f": "outer_most_string",
"inner_props": {
"f_inner_1": 10,
"f_inner_2": 1,
"f_extra": 900,
"inner_inner_props": {"f_inner_inner": 99},
},
}
make_my_class(extra_fields_payload, "EXTRA_FIELDS")
Output:
$ python src/playground.py
PAYLOAD_TYPE=SUCCESS
Success
PAYLOAD_TYPE=BAD_VALUE
{'cl': <class '__main__.ComposedClass'>, '_message': 'While structuring ComposedClass', '_exceptions': [ValueError("'f_inner_2' must be < 2: 12")], '__note__': None}
PAYLOAD_TYPE=BAD_TYPE
{'cl': <class '__main__.ComposedClass'>, '_message': 'While structuring ComposedClass', '_exceptions': [ClassValidationError('While structuring _InnerClass', [TypeError("int() argument must be a string, a bytes-like object or a number, not 'NoneType'")])], '__note__': None}
PAYLOAD_TYPE=BAD_KEY
{'cl': <class '__main__.ComposedClass'>, '_message': 'While structuring ComposedClass', '_exceptions': [ClassValidationError('While structuring _InnerClass', [KeyError('f_inner_2')])], '__note__': None}
PAYLOAD_TYPE=EXTRA_FIELDS
{'cl': <class '__main__.ComposedClass'>, '_message': 'While structuring ComposedClass', '_exceptions': [Exception('Extra fields in constructor for _InnerClass: f_extra')], '__note__': None}
Description
This is referring to the
_exceptionsattribute on some of the exceptions raised in cattrs when structuringI was trying to use cattrs inbuilt exceptions for structuring nested attrs classes. I noticed that in this case, KeyError and TypeError exceptions are nested to exactly where the issue occurred, which is great!
But I was expecting the same type of formatting to show up for Value Errors, which is not the case, they don't specify where the issue was caused. Similar issue happens for when there are extra Fields (Also, I think there should be a separate Exception class for that, but I'll make a new issue for that — #237 )
Also, should
_exceptionsbe made public ?What I Did
POC of issue:
Output: