Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dataclass fields not being fetched for resolve_types #901

Closed
praateekmahajan opened this issue Jan 4, 2022 · 3 comments
Closed

Dataclass fields not being fetched for resolve_types #901

praateekmahajan opened this issue Jan 4, 2022 · 3 comments

Comments

@praateekmahajan
Copy link

Disclaimer : This might be a cattrs issue (please let me know if I should close this and repost there).

Raising here since after my limited investigation it seems like it might be solvable within _funcs.py (might break other things). Per my understanding, the issue primarily stems from PEP 563. So the behavior changes based on if you use from __future__ import annotations in your code.

from __future__ import annotations # comment this line and rerun for success
from dataclasses import dataclass
from cattr import structure


@dataclass
class Foo:
    bar: int


print(structure({"bar": 123}, Foo))

This seems to be the code flow

  1. gen_structure_attrs_fromdict is called https://github.com/python-attrs/cattrs/blob/20ca64405944ea81ac207e070e180d2d805c8fd1/src/cattr/converters.py#L730-L734
  2. That calls fields in _compat.py in cattr. This fields works as expected. https://github.com/python-attrs/cattrs/blob/20ca64405944ea81ac207e070e180d2d805c8fd1/src/cattr/_compat.py#L49-L56
  3. For each of the field above if isisntance(field, str) then resolve_types is called in _funcs.py in attr.
    for field in fields(cls) if attribs is None else attribs:
  4. The resolve_types calls the fields in _make.py which raises NotAnAttrsClassError

    attrs/src/attr/_make.py

    Lines 2029 to 2054 in 3df7bbe

    def fields(cls):
    """
    Return the tuple of ``attrs`` attributes for a class.
    The tuple also allows accessing the fields by their names (see below for
    examples).
    :param type cls: Class to introspect.
    :raise TypeError: If *cls* is not a class.
    :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``
    class.
    :rtype: tuple (with name accessors) of `attrs.Attribute`
    .. versionchanged:: 16.2.0 Returned tuple allows accessing the fields
    by name.
    """
    if not isclass(cls):
    raise TypeError("Passed object must be a class.")
    attrs = getattr(cls, "__attrs_attrs__", None)
    if attrs is None:
    raise NotAnAttrsClassError(
    "{cls!r} is not an attrs-decorated class.".format(cls=cls)
    )
    return attrs

To me it seems like the fields in step 2 and 4 could/should be the same? I might be missing context, happy to work on this given some general guidance.

Thank you for the two powerful libraries!

@Tinche
Copy link
Member

Tinche commented Jan 4, 2022

Does it work with cattrs 1.10?

@euresti
Copy link
Contributor

euresti commented Jan 4, 2022

Did you mean to do from dataclasses import dataclass? Because then it's not an attrs class.

@praateekmahajan
Copy link
Author

@Tinche Just saw python-attrs/cattrs#195 and tried 1.10 out, seems like that works.

@euresti dataclasses was intentional, opened the issue in attr since seemed like a generic solution might belong in attr but seems like its being taken care of in cattrs.

Thanks, will close the ticket!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants