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_transform] include __dataclass_fields__ in transformed types #14752

Merged
merged 1 commit into from
Feb 23, 2023

Conversation

wesleywright
Copy link
Collaborator

@wesleywright wesleywright commented Feb 21, 2023

dataclasses uses a __dataclass_fields__ attribute on each class to mark that it is a dataclass, and Typeshed checks for this attribute in its stubs for functions like dataclasses.is_dataclass and dataclasses.asdict.

In #14667, I mistakenly removed this attribute for classes transformed by a dataclass_transform. This was due to a misinterpretation of PEP 681 on my part; after rereading the section on dataclass semantics, it says:

Except where stated otherwise in this PEP, classes impacted by dataclass_transform, either by inheriting from a class that is decorated with dataclass_transform or by being decorated with a function decorated with dataclass_transform, are assumed to behave like stdlib dataclass.

The PEP doesn't seem to state anything about __dataclass_fields__ or the related functions as far as I can tell, so we should assume that transforms should match the behavior of dataclasses.dataclass in this regard and include the attribute. This also matches the behavior of Pyright, which the PEP defines as the reference implementation.

@github-actions
Copy link
Contributor

According to mypy_primer, this change has no effect on the checked open source code. 🤖🎉

#
# In either case, we're aiming to match the Typeshed stub for `is_dataclass`, which expects
# the instance to have a `__dataclass_fields__` attribute of type `dict[str, Field[Any]]`.
if self._spec is _TRANSFORM_SPEC_FOR_DATACLASSES:
Copy link
Collaborator

Choose a reason for hiding this comment

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

The is check probably doesn't work in incremental mode, when the spec has been deserialized. Another way to do this would be to add an internal boolean flag to the spec that is only true for regular dataclasses.

Copy link
Collaborator Author

@wesleywright wesleywright Feb 22, 2023

Choose a reason for hiding this comment

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

I believe it shouldn't hit any serialization issues because _TRANSFORM_SPEC_FOR_DATACLASSES is never actually attached to an AST node; we return it from another function in this plugin here when we fail to find a spec in the AST.

That said, it's definitely opaque and not very elegant; I should probably make a helper function or something similar at least

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes, you are right.

@cdce8p cdce8p mentioned this pull request Feb 22, 2023
@JukkaL JukkaL merged commit 54635de into python:master Feb 23, 2023
cdce8p pushed a commit to cdce8p/mypy that referenced this pull request Feb 23, 2023
…transformed types (python#14752)

`dataclasses` uses a `__dataclass_fields__` attribute on each class to
mark that it is a dataclass, and Typeshed checks for this attribute in
its stubs for functions like `dataclasses.is_dataclass` and
`dataclasses.asdict`.

In python#14667, I mistakenly removed this attribute for classes transformed
by a `dataclass_transform`. This was due to a misinterpretation of PEP
681 on my part; after rereading the [section on dataclass
semantics](https://peps.python.org/pep-0681/#dataclass-semantics), it
says:

> Except where stated otherwise in this PEP, classes impacted by
`dataclass_transform`, either by inheriting from a class that is
decorated with `dataclass_transform` or by being decorated with a
function decorated with `dataclass_transform`, are assumed to behave
like stdlib dataclass.

The PEP doesn't seem to state anything about `__dataclass_fields__` or
the related functions as far as I can tell, so we should assume that
transforms should match the behavior of `dataclasses.dataclass` in this
regard and include the attribute. This also matches the behavior of
Pyright, which the PEP defines as the reference implementation.

(cherry picked from commit 54635de)
hauntsaninja pushed a commit that referenced this pull request Feb 23, 2023
…transformed types (#14752) (#14769)

`dataclasses` uses a `__dataclass_fields__` attribute on each class to
mark that it is a dataclass, and Typeshed checks for this attribute in
its stubs for functions like `dataclasses.is_dataclass` and
`dataclasses.asdict`.

In #14667, I mistakenly removed this attribute for classes transformed
by a `dataclass_transform`. This was due to a misinterpretation of PEP
681 on my part; after rereading the [section on dataclass
semantics](https://peps.python.org/pep-0681/#dataclass-semantics), it
says:

> Except where stated otherwise in this PEP, classes impacted by
`dataclass_transform`, either by inheriting from a class that is
decorated with `dataclass_transform` or by being decorated with a
function decorated with `dataclass_transform`, are assumed to behave
like stdlib dataclass.

The PEP doesn't seem to state anything about `__dataclass_fields__` or
the related functions as far as I can tell, so we should assume that
transforms should match the behavior of `dataclasses.dataclass` in this
regard and include the attribute. This also matches the behavior of
Pyright, which the PEP defines as the reference implementation.

(cherry picked from commit 54635de)

Co-authored-by: Wesley Collin Wright <[email protected]>
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.

2 participants