Skip to content

include_subclasses does not support dataclasses #426

@eltoder

Description

@eltoder
  • cattrs version: 23.1.2
  • Python version: 3.9
  • Operating System: Linux

Description

According to the documentation, include_subclasses() supports both attrs and dataclasses. However, when I change the example to use dataclasses, I get an error:

from dataclasses import dataclass
from cattrs.strategies import include_subclasses
from cattrs import Converter

@dataclass
class Parent:
    a: int

@dataclass
class Child(Parent):
    b: str

converter = Converter()
include_subclasses(Parent, converter)

produces

Traceback (most recent call last):
  File "/home/eltoder/dev/scratch/cattrs_dc.py", line 14, in <module>
    include_subclasses(Parent, converter)
  File "/home/eltoder/.local/share/ext-python/python-3.9.16.146/lib/python3.9/site-packages/cattrs/strategies/_subclasses.py", line 73, in include_subclasses
    _include_subclasses_without_union_strategy(
  File "/home/eltoder/.local/share/ext-python/python-3.9.16.146/lib/python3.9/site-packages/cattrs/strategies/_subclasses.py", line 111, in _include_subclasses_without_union_strategy
    dis_fn = converter._get_dis_func(subclass_union)
  File "/home/eltoder/.local/share/ext-python/python-3.9.16.146/lib/python3.9/site-packages/cattrs/converters.py", line 756, in _get_dis_func
    return create_uniq_field_dis_func(*union_types)
  File "/home/eltoder/.local/share/ext-python/python-3.9.16.146/lib/python3.9/site-packages/cattrs/disambiguators.py", line 20, in create_uniq_field_dis_func
    cls_and_attrs = [
  File "/home/eltoder/.local/share/ext-python/python-3.9.16.146/lib/python3.9/site-packages/cattrs/disambiguators.py", line 21, in <listcomp>
    (cl, set(at.name for at in fields(get_origin(cl) or cl))) for cl in classes
  File "/home/eltoder/.local/share/ext-python/python-3.9.16.146/lib/python3.9/site-packages/attr/_make.py", line 1944, in fields
    raise NotAnAttrsClassError(f"{cls!r} is not an attrs-decorated class.")
attr.exceptions.NotAnAttrsClassError: <class '__main__.Child'> is not an attrs-decorated class.

It does work if I use union_strategy:

from cattrs.strategies import configure_tagged_union
include_subclasses(Parent, converter, union_strategy=configure_tagged_union)

Additionally, when union_strategy=configure_tagged_union is used, it would be nice to avoid using __subclasses__ so that new classes can be added dynamically. Let me know if you want me to open a separate issue for this.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions