biqqles / dataclassy

A fast and flexible reimplementation of data classes
https://pypi.org/project/dataclassy
Mozilla Public License 2.0
81 stars 9 forks source link

Add mypy plugin #24

Closed giannitedesco closed 3 years ago

giannitedesco commented 3 years ago

This is a first cut, just to prove the concept.

I can run mypy --show-traceback --strict on the following script and it works:

from dataclassy import dataclass

@dataclass
class Foo:
    a: int
    b: str = 'default'

    def method(self) -> str:
        return f'{self.b}/{self.a}'

class Bar(Foo):
    c: float

w = Foo(1, 'abc')
x = Foo(2)
y = Bar(3, 4.5)
z = Bar(6, 7.8, 'now')

I think this still needs to support various options like init=False, generation of __eq__ and __lt__ methods before we should merge it and I'll work on that next.

Are there any other features I need to support, I wonder? Probably I should support make_dataclass() in some way? Perhaps that can only work when the inputs are all constant expressions - I will have a look to see how namedtuple() is handled, since that is a similar kind of thing. We can probably live without that for now?

biqqles commented 3 years ago

Nice progress! The semantics of make_dataclass should be identical to dataclasses' version, except for the flexible inheritance. It's used so rarely that for now you could simply fall back to the stdlib version imo.

giannitedesco commented 3 years ago

I just had a look and it seems that the existing dataclasses plugin doesn't even support that. Furthermore, namedtuple() has specific support in mypy semantic analyzer (not a plugin). So i'm quite happy leaving that off the list for now.

My plan is to add __eq__, and __lt__ and understand relevant decorator args this weekend and try use it a bit in anger and then ready-for-review the PR.

giannitedesco commented 3 years ago

Been a bit busy with other projects, but things are slowly progressing. All decorator arguments are now parsed, checking works properly in the case of @dataclassy(init=False). I will add logic for __eq__, __lt__, __repro__, and __iter__, methods next. That's all pretty straightforward.

I think there also needs to be some logic for when __hash__ method gets created and for what to do when kwargs=True.

giannitedesco commented 3 years ago

Okay, so nothing needs to be done for __eq__, __lt__, __repr__.

Dealing with __iter__ is either impossible or complicated, you will get ~type Any for any fields~ a "type is not Iterable" error when unpacking dataclassy type that was given decorator param iter=True. I will need some help from mypy people to solve that, I think.

I haven't looked at __hash__ properly but I am suspecting the same sort of issues there.

For these reasons, I will make this ready for review as a pretty usable first cut. And I will try and figure out the rest later!

biqqles commented 3 years ago

Very, very nice work, thank you!