Skip to content

Need to call attrs.resolve_types before using structure_attrs_fromdict #692

@danarmak

Description

@danarmak

With PEP 563 enabled, the attrs field types are string values even if the original type annotation was not a string:

from __future__ import annotations
import attrs, cattrs

@attrs.define
class Foo:
    name: str

assert attrs.fields(Foo).name.type == 'str' # rather than the type str

Calling converter.structure would work, but converter.structure_attrs_fromdict fails:

assert converter.structure_attrs_fromdict({ "name": "foo" }, Foo) == Foo('foo')

Traceback (most recent call last):
  File "/home/danarmak/sb/aoa/agentune-analyze/agentune/playground.py", line 17, in <module>
    assert converter.structure_attrs_fromdict({ "name": "foo" }, Foo) == Foo('foo')
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/danarmak/.cache/pypoetry/virtualenvs/agentune-analyze-y3VXCvbo-py3.12/lib/python3.12/site-packages/cattrs/converters.py", line 779, in structure_attrs_fromdict
    conv_obj[getattr(a, "alias", a.name)] = self._structure_attribute(a, val)
                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/danarmak/.cache/pypoetry/virtualenvs/agentune-analyze-y3VXCvbo-py3.12/lib/python3.12/site-packages/cattrs/converters.py", line 760, in _structure_attribute
    return self._structure_func.dispatch(type_)(value, type_)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/danarmak/.cache/pypoetry/virtualenvs/agentune-analyze-y3VXCvbo-py3.12/lib/python3.12/site-packages/cattrs/dispatch.py", line 134, in dispatch_without_caching
    return res if res is not None else self._fallback_factory(typ)
                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/danarmak/.cache/pypoetry/virtualenvs/agentune-analyze-y3VXCvbo-py3.12/lib/python3.12/site-packages/cattrs/converters.py", line 1064, in <lambda>
    structure_fallback_factory: HookFactory[StructureHook] = lambda t: raise_error(
                                                                       ^^^^^^^^^^^^
  File "/home/danarmak/.cache/pypoetry/virtualenvs/agentune-analyze-y3VXCvbo-py3.12/lib/python3.12/site-packages/cattrs/fns.py", line 22, in raise_error
    raise StructureHandlerNotFoundError(msg, type_=cl)
cattrs.errors.StructureHandlerNotFoundError: Unsupported type: 'str'. Register a structure hook for it.

Context: I'm using structure_attrs_fromdict from a custom hook factory which manipulates the dict before passing it to the builtin logic. I can't call structure because that recurses into my hook, and I can't precache the default converter hooks because I don't know all the concrete types I will need to handle ahead of time.

I'm not sure how this can be improved in cattrs, other than calling resolve_types in structure_attrs_fromdict as well as the other places that call it, which may have downsides I'm not aware of.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions