I like! I really appreciate the work you've put into this to get it this far.
Questions and comments:
PEP 563 also requires using ``eval()`` or ``typing.get_type_hints()`` to examine annotations. Code updated to work with PEP 563 that calls ``eval()`` directly would have to be updated simply to remove the ``eval()`` call. Code using ``typing.get_type_hints()`` would continue to work unchanged, though future use of that function would become optional in most cases.
I think it is worth noting somewhere that string annotations are still valid, and should still be evaluated if so.
Because this PEP makes semantic changes to how annotations are evaluated, this PEP will be initially gated with a per-module ``from __future__ import co_annotations`` before it eventually becomes the default behavior.
Is it safe to assume that a module that does not import co_annotations, but imports a module that does, will exhibit PEP 649 behavior when the former accesses an annotation defined in the latter?
- *Code that sets annotations on module or class attributes
from inside any kind of flow control statement.* It's currently possible to set module and class attributes with annotations inside an ``if`` or ``try`` statement, and it works as one would expect. It's untenable to support this behavior when this PEP is active.
Is the following an example of the above?
@dataclass class Foo: if some_condition: x: int else: x: float
If so, would the following still be valid?
if some_condition: type_ = int else: type_ = float
@dataclass class Foo: x: type_
- *Code in module or class scope that references or modifies the
local* ``__annotations__`` *dict directly.* Currently, when setting annotations on module or class attributes, the generated code simply creates a local ``__annotations__`` dict, then sets mappings in it as needed. It's also possible for user code to directly modify this dict, though this doesn't seem like it's an intentional feature. Although it would be possible to support this after a fashion when this PEP was active, the semantics would likely be surprising and wouldn't make anyone happy.
I recognize the point you make later about its impact on static type checkers. Setting that aside, I'm wondering about caes where annotations can be dynamically generated, such as dataclasses.make_dataclass(...). And, I could see reasons for overwriting values in __annotations__, especially in the case where it may be stored as a string and one wants to later affix its evaluated value. These are considerations specific to runtime (dynamic) type checking.
I wonder if it would make sense for each item in __annotations__ to be evaluated separately on first access of each key, rather than all __annotations__ on first access to the dict. Basically the dict would act as a LazyDict. It could also provide the benefit of lessening the expense of evaluating complex but otherwise unused annotations.
On Sun, 2021-04-11 at 18:55 -0700, Larry Hastings wrote:
Attached is my second draft of PEP 649. The PEP and the prototype have both seen a marked improvement since round 1 in January; PEP 649 now allows annotations to refer to any variable they could see under stock semantics:
- Local variables in the current function scope or in enclosing function scopes become closures and use LOAD_DEFER.
- Class variables in the current class scope are made available using a new mechanism, in which the class dict is attached to the bound annotation function, then loaded into f_locals when the annotation function is run. Thus permitting LOAD_NAME opcodes to function normally.
I look forward to your comments,
/arry _______________________________________________ Python-Dev mailing list -- firstname.lastname@example.org To unsubscribe send an email to email@example.com https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://firstname.lastname@example.org/message/QSASX6PZ... Code of Conduct: http://python.org/psf/codeofconduct/