Skip to content

Interoperability with dataclasses #565

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

Open
energizah opened this issue Aug 25, 2019 · 3 comments
Open

Interoperability with dataclasses #565

energizah opened this issue Aug 25, 2019 · 3 comments
Labels

Comments

@energizah
Copy link

The dataclasses ecosystem is growing rapidly. Currently, it's not easy for attrs classes to benefit from the developments in thedataclasses ecosystem. It would be nice to fix this somehow.

There are at least two use cases. One is where I write a class with attrs that holds a
class defined with dataclasses. I want to be able to use all the attrs functionality.

For example, the normally recursive function attr.asdict() doesn't
recurse into dataclasses.

@dataclasses.dataclass 
class A: 
    x: int 
                                                                                                                                                                                                                                                                                               
@attr.dataclass 
class B: 
    a: A 
                                                                                                                                                                                                                                                                                               

In [5]: B(A(1))                                                                                                                                                                                                                                                                                        
Out[5]: B(a=A(x=1))

In [6]: attr.asdict(B(A(1)))                                                                                                                                                                                                                                                                           
Out[6]: {'a': A(x=1)}

The other situation is where I want to use libraries developed for use with dataclasses
on my attrs classes. There are libraries which provide very useful functionality for
dataclasses, but not for attrs classes. For example, marshmallow_dataclass has some good ideas about serialization, and I might like to use it on my attrs classes.

Users of libraries that use attrs and dataclasses would benefit from easy interoperability
between the two systems. I've been wondering how to make this work.

Supporting both systems explicitly in every library

One solution would be to edit each of these functions to support both systems, by adding if statements

def asdict(cls):
    if attr.has(cls):
        ...
    if dataclasses.is_dataclass(cls):
        ...

This might need to be done in each library that intends to support both systems.

Supporting both systems implicitly in every library through an interface

It might be possible to support both systems through a common interface. For example, if
attrs classes got __dataclasses_params__ and __dataclasses_fields__ in addition to
__attrs_attrs__, using the dataclasses API as the common interface. This might
restrict usage in some ways because dataclasses has less functionality than attrs, but it could work relatively seamlessly. Alternatively, a shared compatibility interface could be defined in a third library, which could support dataclasses, attrs, and any other libraries that come to provide similar declarative-class-definition functionality.

Converting between attrs and dataclasses

Perhaps it would be useful to have a function for converting between dataclasses and
attrs so classes defined under one library can use the ecosystem written to support the
other. There would be nuances involved with making classes round-trippable since each
library supports different functionality.

I'm interested in everybody's thoughts on how to handle this situation. :-)

@hynek
Copy link
Member

hynek commented Sep 1, 2019

Well this is obviously a multi-tiered problem. I'm personally happy about having some kind of interop with DCs, since they are quite similar and everyone would win.


I think asdict would be best served by converting it into something singledispatch-based on Python 3+. That would give people a lot more flexibility for free. We could just use the old version on Python 2 and write a brand new one for 3+.

@glyph
Copy link
Contributor

glyph commented May 13, 2020

Would everything "just work" if we had a fallback thing for fields? singledispatch for extensibility seems like a good way to go, but I wouldn't want to have to explicitly register every dataclass in the world.

@hynek
Copy link
Member

hynek commented May 30, 2020

@glyph you mean like a special case  for dataclasses.is_dataclass? Sure why not.

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

No branches or pull requests

4 participants