I maintain pydantic which uses type annotations to provide runtime data validation.
I should point out that "accept PEP 649" and "break pydantic" are
not the only options here. The thing that will break pydantic is
the end of PEP 563's deprecation period, not a failure to
implement PEP 649.
Other viable options include:
- Leave PEP 563 opt-in until we can agree on a solution to the
problem.
- Leave PEP 563 opt-in forever.
- Deprecate PEP 563 and go back to status quo ante.
I haven't followed this closely enough — if PEP 649 were accepted
today, would it even be ready for use before the 3.10 code freeze
(which is in a few weeks)?
Assuming this is a real problem (and based in part on how long
it took for attrs to get what support it has for PEP 563, I
wouldn't be surprised if PEP 563 is quietly throwing a spanner in
the works in several other places as well), my vote is to leave
PEP 563 opt-in until at least 3.11 rather than try to rush through
a discussion on and implementation of PEP 649.
Best,
Paul
I haven't followed this closely enough — if PEP 649 were accepted today, would it even be ready for use before the 3.10 code freeze (which is in a few weeks)?
Perhaps I'm a poor judge of the quality of my own code. But I'd say I have a working prototype and it seems... fine. It didn't require a lot of changes, it just needed the right changes in the right spots. Getting my interactions with symtable and compile were the hardest parts and I think those are all sorted out now.
Cheers,
/arry
Message archived at https://mail.python.org/archives/list/pytho...@python.org/message/PBGFXPC7D3NFLJSFQBDAQQCW6JCMVCFC/
I've read the recent discussions regarding PEP 649 and PEP 563 with interest, Larry Hastings recently contacted me when prompted to do so in a related discussion.I maintain pydantic which uses type annotations to provide runtime data validation.I'm extremely worried that if PEP 649 gets rejected, pydantic will not be able to fully support python 3.10 and may even end up getting abandoned, at best it will be much slower and more brittle.Please, please put pragmatism over principle and accept PEP 649.
It seems evident that the problems with PEP 563 have been
well-known at least to pydantic for several years, as you can see
in the issue Samuel Colvin linked:
https://github.com/samuelcolvin/pydantic/issues/2678
That said, while I do think that "please contact upstream when you
see a problem developing, not just before a major deadline" is a
good lesson to take away from this, it is probably not worth
litigating the question of the particular manner of the
notification. As much as I think it would have been good for this
discussion to happen 6 months, 1 year, 2 years or 3 years ago,
"before the code freeze" is a heck of a lot better than "after the
release" (which is often when the notification comes in, and why
we have been encouraging people to test against alphas and betas).
Hopefully we can let it rest by saying that the timing of learning
about this apparently urgent situation could have been much
better, but it could have been worse as well.
Best,
Paul
_______________________________________________ Python-Dev mailing list -- pytho...@python.org To unsubscribe send an email to python-d...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at https://mail.python.org/archives/list/pytho...@python.org/message/5TGKKRZXGQROQKS2WX6WFGCHTMNUJYBF/
Making this an "us versus them" discussion just makes the whole situation feel confrontational when instead everyone is trying to figure out the best thing for everybody when there's no perfect answer.
And as I noted in my last post — many folks have not been paying attention to the typing discussions because they didn’t realize it concerned them.
I don't have any objections, and I certainly see the wisdom in such a decision.
Best wishes,
/arry
After PEP 563, only `'List[int]'` is practical so we can stop
supporting `List["int"]` and others at some point.
So playing with runtime type will become easier in the future.
Am I wrong?
I wonder if anyone has considered the impact of PEP 563 on dataclasses ?
And I have a whole pile of code that fully expects the Fields' type attribute to be an actual type object that I can call to crate an instance of that type (or call a method on it, which is what I am actually doing)
So my code will very much break with this change.
I fully understand that the __dataclass_fields__ attribute was probably never intended to be part of the public API, so I get what I deserve.
However, the Field object is documented, as such:
"""class dataclasses.Field
Field objects describe each defined field. These objects are created internally, and are returned by the fields() module-level method (see below). Users should never instantiate a Field object directly. Its documented attributes are:
name: The name of the field.
type: The type of the field.
default, default_factory, init, repr, hash, compare, and metadata have the identical meaning and values as they do in the field() declaration.
Other attributes may exist, but they are private and must not be inspected or relied on."""
That last sentence implies that the type attribute CAN be inspected and relied upon, which is what I am doing.
And I haven't tried to solve this problem in my use case, but I'm not sure it can be done -- when I get around to inspecting the type of the Field objects, I have no idea what namespace they are in -- so I can't reconstruct them from the string. I really need the type object itself.
So I'll probably need to re-write much of the dataclasses decorator, to call eval() early -- though even then I'm not sure I'll have access to the proper namespace.
Anyway -- one more data point: PEP 563 changes the (semi-public?) API of dataclasses.
Though *maybe* that could be addressed with a dataclasses update -- again, I've only started to think about it -- there was some discussion of that in the BPO, though Eric didn't seem particularly interested.
I still think it's working as intended: it uses what's in
__annotations__ (or passed in to field()). As everyone who has
tried to call typing.get_type_hints() knows, it's hard to get
right, if it's even possible, because, as you say "when I get
around to inspecting the type of the Field objects, I have no idea
what namespace they are in". My opinion is that the person who
wants a real type object probably has a better idea of that
namespace than @dataclass does, but there's a very good chance
they don't know, either.
@dataclass goes out of its way to not call typing.get_type_hints(). The original reason for this is not wanting to force typing to be imported, if it wasn't already being used. That may have been addressed with PEP 560, but I've never really checked on the impact.
Another reason for not calling typing.get_type_hints(): there's
really only one thing [*] dataclasses wants to know, with regard
to the type/annotation of the field: is the type of this field
typing.ClassVar? It doesn't seem that the performance issues and
possible failures make it worth calling typing.get_type_hints()
just for this case. @dataclass uses other tricks (not described
here).
In any event, all of this mess is one reason I'd like to see PEP
649 get accepted: there would never be a reason to call
typing.get_type_hints(), and the values in the Field object would
again be type objects.
Back to my original point: If you ignore the test for ClassVar,
then dataclasses completely ignores the values in __annotations__
or Field.type. It's no different from typing.NamedTuple in that
regard.
I do have sympathy for users looking at Field.type and getting a
string instead of a type object: but that's really no different
from non-dataclass users looking at any occurrence of
__annotations__ and now getting a string: that's a result of PEP
563 across the board, not just with dataclasses. As I said in
bpo-39442:
Isn't that the entire point of "from __future__ import annotations"?
Eric
[*]: Actually two things: the other being "is the field of type
dataclasses.InitVar?". It has some of the same problems as
ClassVar, but we know that dataclasses has been imported, so it's
less of a big deal.
dataclasses may be the only part of the stdlib that uses annotations.
I have!I wonder if anyone has considered the impact of PEP 563 on dataclasses ?
In retrospect, that field probably should have been named "annotation". Regardless, the intent was always "store what's in __annotations__[field_name]", or what the user specified in field(..., type=whatever, ...).
In any event, all of this mess is one reason I'd like to see PEP 649 get accepted:
On Sat, Apr 17, 2021 at 6:12 AM Eric V. Smith <er...@trueblade.com> wrote:
I have!I wonder if anyone has considered the impact of PEP 563 on dataclasses ?
Thanks Eric.In retrospect, that field probably should have been named "annotation". Regardless, the intent was always "store what's in __annotations__[field_name]", or what the user specified in field(..., type=whatever, ...).
intent is all well and good, but what was the intent of __annotations__ In the first place. Static typing was certainly one of the intents, but as it DID store a value, not a string from the beginning, we can only assume that there was some intent that the value might be used.
As for dataclasses -- why store it at all? It seems that dataclasses use the fact that a class attribute has an annotation to determine what to add to the field -- which is a nifty use of teh syntax. But presumably the intent of storing the annotation in the Field object, and providing a public attribute for it, was so that it could be used.
I didn't want to predict what someone was using dataclasses for. Especially someone using field(..., metadata=something) might want access to any of the field() values, including .type. I supposed I could have said "for defaults, default_factory, repr, etc., look at the Field object, but for the type look at __annotations__[field_name]", but I decided it would be easier if everything about a field would be in the Field object. Not that it makes much difference: I believe that Field.type always agrees with __annotations__[field_name].
This allows someone to say (where some_dataclass_field_object is a Field):
process_field(some_dataclass_field_object)
instead of this, if the .type field weren't present:
process_field(some_dataclass_field_object,
SomeDataclass.__annotations__[some_dataclass_field_object.name])
I suppose your point is that the type attribute stored the annotation, and PEP 653 changes what the annotation will be so there's nothing specific at all about dataclasses here. Which is true. But users of dataclasses may have been less aware of all the implications as they didn't write that annotation etrating code themselves. I know I wasn't.In any event, all of this mess is one reason I'd like to see PEP 649 get accepted:
Indeed -- that is the title of this thread, after all :-)
Well, not everyone is not in support of the subject!
Eric
And see others' notes, there seems to be two other places in the stdlib that will be affected.
-CHB
--
Christopher Barker, PhD (Chris)
Python Language Consulting
- Teaching
- Scientific Software Development
- Desktop GUI and Web Development
- wxPython, numpy, scipy, Cython
-- Eric V. Smith
As far as I know, both Pydantic and marshmallow start using annotation
for runtime type after PEP 563 is accepted. Am I right?
When PEP 563 is accepted, there are some tools using runtime type in
annotation, but they are not adopted widely yet.