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

[dataclasses plugin] Support kw_only=True #10867

Merged
merged 7 commits into from
Aug 8, 2021

Conversation

tgallant
Copy link
Contributor

Description

Fixes #10865

If all fields in a dataclass are keyword only then mypy should not raise errors regarding the order of attributes with default values. See the linked issue for a more detailed description.

This PR makes the relevant changes to handle that.

Test Plan

I've added tests to check-dataclasses.test to cover the new changes.

@tgallant tgallant force-pushed the dataclass_kw_only_order branch 2 times, most recently from dbfd425 to 1515be7 Compare July 25, 2021 01:35
@cdce8p cdce8p mentioned this pull request Aug 1, 2021
21 tasks
@cdce8p
Copy link
Collaborator

cdce8p commented Aug 1, 2021

Came across an interesting use case of KW_ONLY with inheritance, that should probably be supported as well (if not already done).

from dataclasses import dataclass, KW_ONLY

@dataclass
class Base:
    x: str
    _: KW_ONLY
    y: int = 0
    w: int = 1

@dataclass
class D(Base):
    z: str
    a: str = "a"
>>> D("Hello", "World")
D(x='Hello', y=0, w=1, z='World', a='a')

That works because of keyword reordering.
https://docs.python.org/3.10/library/dataclasses.html#re-ordering-of-keyword-only-parameters-in-init

@hauntsaninja
Copy link
Collaborator

Thanks for working on this! Could we also test that __init__ has the appropriate signature (e.g. by instantiating the classes)

@tgallant
Copy link
Contributor Author

tgallant commented Aug 2, 2021

Thanks for raising this case @cdce8p. I've added this example as a test case and updated the code to handle it. @hauntsaninja I also made sure to check the initialization in the test cases.

I was looking through the docs again and spotted this:

In a single dataclass, it is an error to specify more than one field whose type is KW_ONLY.

https://docs.python.org/3.10/library/dataclasses.html#dataclasses.KW_ONLY

It seemed like this would be a good thing to have a mypy check for. I added a check for this case in commit 75ef138

@hauntsaninja
Copy link
Collaborator

python/typeshed#5826 is now on mypy master, so if you merge you'll be able to pull that in.

It would be good to add tests of class instantiation that produce errors. Specifically, test cases should prove that the arguments are in fact keyword only and complain when passed positionally and that parameter reordering happens and we get type errors (i.e. make sure positional parameters have types that are distinct from each other and from kw only parameters)

@tgallant
Copy link
Contributor Author

tgallant commented Aug 5, 2021

i rebased this branch with master and updated the KW_ONLY usage according to the typeshed change. i will follow up with some more test cases

@tgallant
Copy link
Contributor Author

tgallant commented Aug 7, 2021

thanks for the helpful suggestions @hauntsaninja and @cdce8p. i've added test cases covering positional vs keyword arguments, reordering, and type errors. let me know if you think there are other cases that should be covered in this PR.

To account for the reordering of keyword only parameters `all_attrs` is sorted
based on the attr.kw_only value
https://docs.python.org/3.10/library/dataclasses.html#dataclasses.KW_ONLY

In this section in the documentation it states:

In a single dataclass, it is an error to specify more than one field whose type
is KW_ONLY.

This commit handles raising a mypy failure if this case is detected.
Copy link
Collaborator

@hauntsaninja hauntsaninja left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this is great! :-)

@hauntsaninja hauntsaninja merged commit ed2b4c7 into python:master Aug 8, 2021
@cdce8p
Copy link
Collaborator

cdce8p commented Aug 8, 2021

Thanks @tgallant 🎉

sobolevn added a commit that referenced this pull request Jun 23, 2023
It is not needed, because it is always serialized as `bool` and is always present.

It was added a long time ago in #10867 as a compat layer. But, since then we've added at least one `is_neither_frozen_nor_nonfrozen` attribute that is serialized / deserialized in a common way.

So, let's remove this hack for good.
sobolevn added a commit that referenced this pull request Jun 24, 2023
…ion (#15502)

It is not needed, because it is always serialized as `bool` and is
always present.

It was added a long time ago in
#10867 as a compat layer. But, since
then we've added at least one `is_neither_frozen_nor_nonfrozen`
attribute that is serialized / deserialized in a common way.

So, let's remove this hack for good.
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

Successfully merging this pull request may close these issues.

Don't warn about non keyword-only attributes after keyword-only attributes in dataclasses
4 participants