python-attrs / cattrs

Composable custom class converters for attrs, dataclasses and friends.
https://catt.rs
MIT License
791 stars 110 forks source link

JsonConverter.structure cannot handle Annotated union type. #418

Closed declaresub closed 1 year ago

declaresub commented 1 year ago

Description

cattrs fails when attempting to structure data using a class with an Annotated union type.

What I Did

The code:

from typing import Annotated
import attrs
from cattrs.preconf.json import make_converter

conv = make_converter()

@attrs.define
class GoodModel:
    name: Annotated[str, 'required']

@attrs.define
class BadModel:
    name: Annotated[str | None, 'required'] 

data = {'name': 'test'}
print('Loading data using GoodModel.')
conv.structure(data, GoodModel)
print('Loading data using GoodModel succeeded.')
print('Loading data using BadModel.')
conv.structure(data, BadModel)

and the output:

Loading data using GoodModel.
Loading data using GoodModel succeeded.
Loading data using BadModel.
  + Exception Group Traceback (most recent call last):
  |   File "/Users/charles/Documents/annotated_test.py", line 20, in <module>
  |     conv.structure(data, BadModel)
  |   File "/Users/charles/Documents/ccWrangler/git/ccwrangler-api/.venv/3.11.4/lib/python3.11/site-packages/cattrs/converters.py", line 334, in structure
  |     return self._structure_func.dispatch(cl)(obj, cl)
  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |   File "<cattrs generated structure __main__.BadModel>", line 9, in structure_BadModel
  | cattrs.errors.ClassValidationError: While structuring BadModel (1 sub-exception)
  +-+---------------- 1 ----------------
    | Traceback (most recent call last):
    |   File "<cattrs generated structure __main__.BadModel>", line 5, in structure_BadModel
    |   File "/Users/charles/Documents/ccWrangler/git/ccwrangler-api/.venv/3.11.4/lib/python3.11/site-packages/cattrs/converters.py", line 646, in _structure_optional
    |     other = union_params[0] if union_params[1] is NoneType else union_params[1]
    |                                ~~~~~~~~~~~~^^^
    | IndexError: tuple index out of range
    | Structuring class BadModel @ attribute name
Tinche commented 1 year ago

Hm, confirmed. Should be an easy fix though, looking into it.

Tinche commented 1 year ago

Should be fixed on main!

declaresub commented 1 year ago

I tested the fix using the code example above; all appears good.