python / cpython

The Python programming language
https://www.python.org/
Other
61.36k stars 29.55k forks source link

Dataclasses - Support use of Annotated including `field` as metainfo #107051

Open mementum opened 1 year ago

mementum commented 1 year ago

Dataclasses - Support use of Annotated including field as metainfo

dataclasses are great and I make extensive use of them but there is something which I always find non-matching. Example:

from dataclasses import dataclass, field

@dataclass
class Dummy:
    a: int = field(init=False, default=5)

Having declared a to be of type int the assignment is the result of a callable field which (as an end-user) I am not sure it is returning an int

Given that Annotated can convey metainformation, would it not be really appropriate to use it for dataclasses, as in:

from dataclasses import dataclass, field
from typing import Annotated

@dataclass
class Dummy
    a: Annotated[int, field(init=False)] = 5

This should be clearer for anyone:

Pitch

It modernizes the use of field, allows assigned a default value which actually matches the defined type, rather than relying on type-checkers having workarounds to cover the case.

It does not remove the old syntax.

Previous discussion

https://discuss.python.org/t/dataclasses-make-use-of-annotated/30028

Linked PRs

AlexWaygood commented 1 year ago

The response to your suggestion on discuss.python.org has been mixed-to-negative. While I agree that this might have been the approach we would have taken if Annotated had been added to the stdlib before dataclasses, I don't see any compelling reason to add a second way to do the same thing now, given that the existing way to do things is so established. This would add complexity to the code, and create a maintenance burden for core developers maintaining dataclasses, without allowing users to do anything that they couldn't already do with the existing dataclasses features. Using Annotated in the way you're proposing will also be much more fragile if a user has from __future__ import annotations enabled.

mementum commented 1 year ago

Dear Alex,

The response to your suggestion on discuss.python.org has been mixed-to-negative.

Let me argue that the answers can be divided in these groups:

  1. Those that have suddenly realized there is a typing problem related to dataclasses and in general, with some of the answers having absolutely nothing to do with the proposal. It is not my intention to critizice typing/annotations, which is an colossal effort built upon a dynamic language which had nothing with regards to it to start with. Hitting some bumps along the road is the less that can happen when undertaking such an endevour

  2. Those that say: "yeah, we can already assign a field who cares". Obviously users who are not really concerned with typing at all and will hate having to type the extra letters involved in using Annotated, needed opening/closing square brackets and having to readjust muscle memory, because typing correctness is not important, the important thing is typing faster.

  3. Those have have realized that the use of Annotated in similar forms (Pydantic, FastAPI, Typer, ...) is growing an provide a hint, clearly indicating ... this hint is a thing.

  4. Someone (notice the singular) who realizes the potential of it (and later takes part in the in-thread parallel philosophic discussion about typing)

  5. Those who suddenly upon seeing a PR, suggest writing a PEP, which I see as positive indication (+2)

Personally I see a lot of mixed, no negative and 3 positives.

While I agree that this might have been the approach we would have taken if Annotated had been added to the stdlib before dataclasses, I don't see any compelling reason to add a second way to do the same thing now, given that the existing way to do things is so established

I also saw no compelling need for typing to be added with the mega-burden it brought when it wasn't going to be enforced but I have learnt to see things differently.

without allowing users to do anything that they couldn't already do with the existing dataclasses features.

If I would only need my fingers to count the number of things have been added and are added to Python, which allow things to be done in different ways, but attaining the same result..

Using Annotated in the way you're proposing will also be much more fragile if a user has from future import annotations enabled.

I can't see how this would be more fragile. The implementation is using the same techniques used by the dataclasses implementors to catch the typing.ClassVar and dataclasses.InitVar annotations, whether they are stringified or not.

For your reference, here is the drafted PEP as suggested/requested in the thread:

Given that a PEP formalizes a design I added extra cases, not yet in the PR, to throw appropriate exceptions and how the parsing of the Annotated context-specific info can be dealt with in different ways.

mementum commented 1 year ago

Let me add another group to the answers, to make sure it doesn't count as a negative:

  1. Someone who doesn't like the idea because he doesn't like the complexities of field, __post_init__ and would rather write his own boilerplate in most cases. Another de-railed post in the discussion.
AlexWaygood commented 1 year ago

It's not me you need to convince. You need to show that there is significant support for your proposal among the community, or your PEP is unlikely to be accepted by the Steering Council. I don't believe you've demonstrated that yet, but it's your right to disagree with me on that point. Bear in mind, however, that you will require at least one core developer to sponsor your PEP if you want to submit it to the Steering Council for consideration.

For now, my advice to you is to continue making the case for your proposal on discuss.python.org. That is where PEPs that have not yet been accepted should be discussed, not the GitHub issue tracker. Best of luck! :)

mementum commented 1 year ago

Hi Alex,

I do fully agree that the place for a discussion is "Discuss", but since you made your point here I felt compelled to provide a reasoned answer.

The discussion, if any, will of course continue over at Discuss.

Best regards

mementum commented 1 year ago

In any case, the PR has been updated with the Exceptions proposed in the draft PEP to control duplicity of default/default_factory values and using Field inside Annotated and also as default value.

Best regards

sobolevn commented 11 months ago

It would be very hard for mypy to analyze Annotated[int, field(init=False)], because static type checkers right now always ignore metadata part.

So, I am -1 on this proposal.