cattrs
cattrs copied to clipboard
Importing `annotations` from `__future__` causes a StructureHandlerNotFoundError
- cattrs version:
22.1.0 - Python version:
3.10.1 - Operating System: Ubuntu
Description
Importing annotations from __future__ causes a StructureHandlerNotFoundError, whereas my registered structure function works fine when I do not import annotations from __future__.
What I Did
I ran a Python script with the following contents:
# from __future__ import annotations
from typing import Any
import attr
from cattrs import Converter
@attr.frozen
class C:
a: int
def structure_int(val: str, type_: Any) -> int:
return int(val)
c = Converter()
c.register_structure_hook(int, structure_int)
result = c.structure_attrs_fromtuple(["1"], C)
print(result)
When the first line is commented out, it works fine and prints the following as expected:
C(a=1)
When the first line is not commented out, it causes the following error:
Traceback (most recent call last):
File ".../.config/JetBrains/PyCharmCE2022.1/scratches/scratch_7.py", line 21, in <module>
result = c.structure_attrs_fromtuple(["1"], C)
File ".../.pyenv/versions/edgar-3.10/lib/python3.10/site-packages/cattrs/converters.py", line 403, in structure_attrs_fromtuple
converted = self._structure_attribute(a, value)
File ".../.pyenv/versions/edgar-3.10/lib/python3.10/site-packages/cattrs/converters.py", line 422, in _structure_attribute
return self._structure_func.dispatch(type_)(value, type_)
File ".../.pyenv/versions/edgar-3.10/lib/python3.10/site-packages/cattrs/converters.py", line 344, in _structure_error
raise StructureHandlerNotFoundError(msg, type_=cl)
cattrs.errors.StructureHandlerNotFoundError: Unsupported type: 'int'. Register a structure hook for it.
Ah, the tuple un/structuring functions aren't optimized yet. Until someone contributes this, you'll need to call attrs.resolve_types on your classes manually (needs to be done only once) if you're using from __future__ import annotations. The dict handling stuff does this automatically. Sorry :/
Hmm, that doesn't seem to work for me. I added attr.resolve_types(int, globals()) to the script above, and I got this exception:
attr.exceptions.NotAnAttrsClassError: <class 'int'> is not an attrs-decorated class. That makes sense, of course, because int is a primitive. Is there a different workaround for primitives?
You're structuring C, so call resolve_types(C).
Ah, I see. That worked. Thanks!