cattrs: Breaks when PEP 563 is active
- cattrs version: All versions, as far as I can tell
- Python version: Python 3.7
- Operating System: Arch Linux
Description
cattr.structure
breaks when PEP 563 is activated. This can be done in Python 3.7 with the new from __future__ import annotations
.
In short, this defers the evaluation of type annotations. So consider this class:
@attr.s(auto_attribs=True)
class Foo:
bar: str
Traditionally, __annotations__
looks like this:
>>> Foo.__annotations__
... {'bar': str}
but under PEP 563 (and eventually the default behaviour), it’ll look like this:
>>> Foo.__annotations__
... {'bar': 'str'}
This seems to confuse cattr and causes problems. Round-tripping the above class, we now see exceptions like this:
In [16]: cattr.structure(cattr.unstructure(Foo('Hello World')), Foo)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-16-1bbcc538d3df> in <module>()
----> 1 cattr.structure(cattr.unstructure(Foo('Hello World')), Foo)
~/.local/share/virtualenvs/aastrology-5jK3bc4O/lib/python3.7/site-packages/cattr/converters.py in structure(self, obj, cl)
176 """Convert unstructured Python data structures to structured data."""
177 # type: (Any, Type) -> Any
--> 178 return self._structure_func.dispatch(cl)(obj, cl)
179
180 # Classes to Python primitives.
~/.local/share/virtualenvs/aastrology-5jK3bc4O/lib/python3.7/site-packages/cattr/converters.py in structure_attrs_fromdict(self, obj, cl)
294 except KeyError:
295 continue
--> 296 conv_obj[name] = dispatch(type_)(val, type_)
297
298 return cl(**conv_obj)
~/.local/share/virtualenvs/aastrology-5jK3bc4O/lib/python3.7/site-packages/cattr/converters.py in _structure_default(self, obj, cl)
238 "it.".format(cl)
239 )
--> 240 raise ValueError(msg)
241
242 def _structure_call(self, obj, cl):
ValueError: Unsupported type: str. Register a structure hook for it.
This fix is probably to apply this logic: https://www.python.org/dev/peps/pep-0563/#resolving-type-hints-at-runtime
Here:
Which I’m currently digging into.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 8
- Comments: 26 (15 by maintainers)
Commits related to this issue
- Add an evaluation context to support typing.ForwardDef Type annotations can also be strings that are evaluated at run time. Internally, Python converts them into typing.ForwardDef objects and evals t... — committed to sangoma/cattrs by vodik 6 years ago
- Add an evaluation context to support typing.ForwardDef Type annotations can also be strings that are evaluated at run time. Internally, Python converts them into typing.ForwardDef objects and evals t... — committed to sangoma/cattrs by vodik 6 years ago
- Add an evaluation context to support typing.ForwardDef Type annotations can also be strings that are evaluated at run time. Internally, Python converts them into typing.ForwardDef objects and evals t... — committed to sangoma/cattrs by vodik 6 years ago
- Fixes #41: Breaks when PEP 563 is active. — committed to JiveHelix/cattrs by JiveHelix 4 years ago
- Issue #41: Reimplemented string type conversion using more robust ForwardRef combined with __module__ namespace lookup. Added unit tests to ensure proper conversion of compound types, like List[int] o... — committed to JiveHelix/cattrs by JiveHelix 4 years ago
- Fixes #41: Breaks when PEP 563 is active. — committed to darrenmeehan/cattrs by JiveHelix 4 years ago
- Issue #41: Reimplemented string type conversion using more robust ForwardRef combined with __module__ namespace lookup. Added unit tests to ensure proper conversion of compound types, like List[int] o... — committed to darrenmeehan/cattrs by JiveHelix 4 years ago
Today I run in the same bug, took me quite some time to figure out that the error
ValueError: Unsupported type: List[str]. Register a structure hook for it
was caused by
from __future__ import annotations
Any plans to release a new version with the suggested fix?
Not trivial to solve while keeping the current level of performance, but with 3.9 around the corner I’ll have to look into this more closely.
This is a disappointing issue. It’s my first day using cattrs and I hit this.
Oct 2019 and this bug still seems to be present. The proof of concept mentioned above is dated Sep 2018.
Is there any fix pending, or some workaround? The only thing I can think of is remove the
from __future__ import annotations
, but that defeats the purpose of it, and as mentioned will be the default in Python 4 (a long ways off I know, but …)Can you try using the GenConverter? That should work
I have a proof of concept fix, but won’t be able to polish it up until tonight.
This fix will hit two birds with one stone, as I guess it also means forward declarations where broken as well, as per #13