-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
PEP 649: Improve description of semantics and mark as accepted #3138
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
Merged
larryhastings
merged 19 commits into
python:main
from
larryhastings:nail_down_annotation_expression_semantics
May 16, 2023
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
d9a17ff
Improve PEP 649's description of its semantics.
larryhastings 23148f6
Fix lint.
larryhastings 9ace095
PEP 693: Postpone 3.12.0b1 by two weeks (#3139)
hugovk 108f275
PEP 695: Lazy evaluation, concrete scoping semantics, other changes (…
JelleZijlstra 8989c52
Incorporate changes from feedback, mark Accepted.
larryhastings af3aa36
Fix PEP 12 header *order compliance*. Wow.
larryhastings 7af54df
Fix Sphinx complaints.
larryhastings 0034059
Merge branch 'main' into nail_down_annotation_expression_semantics
JelleZijlstra 3d34d84
Make enum consistent, flesh out observed semantics.
larryhastings 06d53a4
Add "Resolution" header, as pointed out by Hugo.
larryhastings 1a316cc
Switch to other URL for Resolution header.
larryhastings 08485e9
Apply ``global_enum`` to ``inspect.AnnotationFormat``
AA-Turner 72b8183
Final? text / semantics cleanup pass.
larryhastings ade4a90
"accept" -> "accepts". Bettering my Englishes.
larryhastings 0503ca1
Add new "post history" reflecting the updates.
larryhastings 7da747a
Update post history with all conversations, courtesy CAM!
larryhastings c9b0773
Fix typo. Thanks, Emily!
larryhastings c36b491
Add "Discussions-To" header. Thanks, CAM!
larryhastings 7896e98
Attempt to satisfy "validate-post-history" hook.
larryhastings File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,25 @@ | ||
| PEP: 649 | ||
| Title: Deferred Evaluation Of Annotations Using Descriptors | ||
| Author: Larry Hastings <[email protected]> | ||
| Status: Draft | ||
| Discussions-To: https://discuss.python.org/t/pep-649-deferred-evaluation-of-annotations-tentatively-accepted/21331/ | ||
| Status: Accepted | ||
larryhastings marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| Type: Standards Track | ||
| Topic: Typing | ||
| Content-Type: text/x-rst | ||
| Created: 11-Jan-2021 | ||
| Post-History: 11-Jan-2021, 11-Apr-2021, 19-Apr-2023 | ||
|
|
||
| Python-Version: 3.13 | ||
| Post-History: `11-Jan-2021 <https://mail.python.org/archives/list/[email protected]/thread/5QMMCRF4HTRRNJV56CGHVI5GRHVBDGQO/>`__, | ||
| `12-Apr-2021 <https://mail.python.org/archives/list/[email protected]/thread/QSASX6PZ3LIIFIANHQQFS752BJYFUFPY/>`__, | ||
| `18-Apr-2021 <https://mail.python.org/archives/list/[email protected]/thread/WUZGTGE43T7XV3EUGT6AN2N52OD3U7AE/>`__, | ||
| `09-Aug-2021 <https://mail.python.org/archives/list/[email protected]/thread/2MEOWHCVDLPABOBLYUGRXVOOOBYOLLU6/>`__, | ||
| `20-Oct-2021 <https://mail.python.org/archives/list/[email protected]/thread/SZLWVYV2HPLU6AH7DOUD7DWFUGBJGQAY/>`__, | ||
| `20-Oct-2021 <https://discuss.python.org/t/type-annotations-pep-649-and-pep-563/11363>`__, | ||
| `17-Nov-2021 <https://mail.python.org/archives/list/[email protected]/thread/VIZEBX5EYMSYIJNDBF6DMUMZOCWHARSO/>`__, | ||
| `15-Mar-2022 <https://discuss.python.org/t/finding-edge-cases-for-peps-484-563-and-649-type-annotations/14314>`__, | ||
| `23-Nov-2022 <https://discuss.python.org/t/pep-649-deferred-evaluation-of-annotations-tentatively-accepted/21331>`__, | ||
| `07-Feb-2023 <https://discuss.python.org/t/two-polls-on-how-to-revise-pep-649/23628>`__, | ||
| `11-Apr-2023 <https://discuss.python.org/t/a-massive-pep-649-update-with-some-major-course-corrections/25672>`__, | ||
| Resolution: https://discuss.python.org/t/pep-649-deferred-evaluation-of-annotations-tentatively-accepted/21331/43 | ||
|
|
||
| ******** | ||
| Abstract | ||
|
|
@@ -75,6 +87,7 @@ in a specific format. | |
| Format identifiers are always predefined integer values. | ||
| The formats defined by this PEP are: | ||
|
|
||
|
|
||
| * ``inspect.VALUE = 1`` | ||
|
|
||
| The default value. | ||
|
|
@@ -528,6 +541,31 @@ resulting in this PEP. | |
| Implementation | ||
| ************** | ||
|
|
||
| Observed semantics for annotations expressions | ||
| ============================================== | ||
|
|
||
| For any object ``o`` that supports annotations, | ||
| provided that all names evaluated in the annotations expressions | ||
| are bound before ``o`` is defined and never subsequently rebound, | ||
| ``o.__annotations__`` will produce an identical annotations dict both | ||
| when "stock" semantics are active and when this PEP is active. | ||
| In particular, name resolution will be performed identically in | ||
| both scenarios. | ||
|
|
||
| When this PEP is active, the value of ``o.__annotations__`` | ||
| won't be calculated until the first time ``o.__annotations__`` | ||
| itself is evaluated. All evaluation of the annotation expressions | ||
| is delayed until this moment, which also means that | ||
|
|
||
| * names referenced in the annotations expressions will use their | ||
| *current* value at this moment, and | ||
| * if evaluating the annotations expressions raises an exception, | ||
| that exception will be raised at this moment. | ||
|
|
||
| Once ``o.__annotations__`` is successfully calculated for the | ||
| first time, this value is cached and will be returned by future | ||
| requests for ``o.__annotations__``. | ||
|
|
||
| __annotate__ and __annotations__ | ||
| ================================ | ||
|
|
||
|
|
@@ -556,9 +594,9 @@ code should prefer to interact with it only via the | |
|
|
||
| The callable stored in ``__annotate__`` must accept a | ||
| single required positional argument called ``format``, | ||
| which will always be an ``int``. It must either return | ||
| a dict (or subclass of dict) or raise | ||
| ``NotImplementedError()``. | ||
| which will always be an ``int`` (or a subclass of ``int``). | ||
| It must either return a dict (or subclass of dict) or | ||
| raise ``NotImplementedError()``. | ||
|
|
||
| Here's a formal definition of ``__annotate__``, as it will | ||
| appear in the "Magic methods" section of the Python | ||
|
|
@@ -573,25 +611,25 @@ Language Reference: | |
| annotations values should be provided. Must be one of the | ||
| following: | ||
|
|
||
| ``1`` (exported as ``inspect.VALUE``) | ||
| ``inspect.VALUE`` (equivalent to the ``int`` constant ``1``) | ||
larryhastings marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| Values are the result of evaluating the annotation expressions. | ||
|
|
||
| ``2`` (exported as ``inspect.SOURCE``) | ||
| ``inspect.FORWARDREF`` (equivalent to the ``int`` constant ``2``) | ||
|
|
||
| Values are real annotation values (as per ``inspect.VALUE`` format) | ||
| for defined values, and ``ForwardRef`` proxies for undefined values. | ||
| Real objects may be exposed to, or contain references to, | ||
| ``ForwardRef`` proxy objects. | ||
|
|
||
| ``inspect.SOURCE`` (equivalent to the ``int`` constant ``3``) | ||
|
|
||
| Values are the text string of the annotation as it | ||
| appears in the source code. May only be approximate; | ||
| whitespace may be normalized, and constant values may | ||
| be optimized. It's possible the exact values of these | ||
| strings could change in future version of Python. | ||
|
|
||
| ``3`` (exported as ``inspect.FORWARDREF``) | ||
|
|
||
| Values are real annotation values (as per ``inspect.VALUE`` format) | ||
| for defined values, and ``ForwardRef`` proxies for undefined values. | ||
| Real objects may be exposed to, or contain references to, | ||
| ``ForwardRef`` proxy objects. | ||
|
|
||
| If an ``__annotate__`` function doesn't support the requested | ||
| format, it must raise ``NotImplementedError()``. | ||
| ``__annotate__`` functions must always support ``1`` (``inspect.VALUE``) | ||
|
|
@@ -713,25 +751,12 @@ makes some modifications to the annotations before it returns them. | |
| This PEP adds a new keyword-only parameter to these two functions, | ||
| ``format``. ``format`` specifies what format the values in the | ||
| annotations dict should be returned in. | ||
| ``format`` accepts the following values, defined as attributes on the | ||
| ``inspect`` module:: | ||
|
|
||
| VALUE = 1 | ||
| FORWARDREF = 2 | ||
| SOURCE = 3 | ||
| The ``format`` parameter on these two functions accepts the same values | ||
| as the ``format`` parameter on the ``__annotate__`` magic method | ||
| defined above; however, these ``format`` parameters also have a default | ||
| value of ``inspect.VALUE``. | ||
|
|
||
| The default value for the ``format`` parameter is ``1``, | ||
| which is ``VALUE`` format. | ||
|
|
||
| The defined ``format`` values are guaranteed to be contiguous, | ||
| and the ``inspect`` module also publishes attributes representing | ||
| the minimum and maximum supported ``format`` values:: | ||
|
|
||
| FORMAT_MIN = VALUE | ||
| FORMAT_MAX = SOURCE | ||
|
|
||
|
|
||
| Also, when either ``__annotations__`` or ``__annotate__`` is updated on an | ||
| When either ``__annotations__`` or ``__annotate__`` is updated on an | ||
| object, the other of those two attributes is now out-of-date and should also | ||
| either be updated or deleted (set to ``None``, in the case of ``__annotate__`` | ||
| which cannot be deleted). In general, the semantics established in the previous | ||
|
|
@@ -1017,40 +1042,29 @@ the wrapped callable, which for simplicity must be named | |
| return ann | ||
|
|
||
|
|
||
| Other modifications to existing objects | ||
| ======================================= | ||
| Other modifications to the Python runtime | ||
| ========================================= | ||
|
|
||
| This PEP adds two more attributes to existing Python objects: | ||
| a ``__locals__`` attribute to function objects, and | ||
| an optional ``__globals__`` attribute to class objects. | ||
|
|
||
| In Python, the bytecode interpreter can reference both a | ||
| "globals" and a "locals" dictionary. However, the current | ||
| function object can only be bound to a globals dictionary, | ||
| via the ``__globals__`` attribute. Traditionally the | ||
| "locals" dictionary is only set when executing a class. | ||
| This PEP needs to set the "locals" dictionary to the class dict | ||
| when evaluating annotations defined inside a class namespace. | ||
| So this PEP defines a new ``__locals__`` attribute on | ||
| functions. By default it is uninitialized, or rather is set | ||
| to an internal value that indicates it hasn't been explicitly set. | ||
| It can be set to either ``None`` or a dictionary. If it's set to | ||
| a dictionary, the interpreter will use that dictionary as | ||
| the "locals" dictionary when running the function. | ||
|
|
||
| In Python, function objects contain a reference to their own | ||
| ``__globals__``. However, class objects aren't currently | ||
| defined as doing so in Python. The implementation of | ||
| ``__annotate__`` in CPython needs a reference to the module | ||
| globals in order to bind the unbound code object. So this PEP | ||
| defines a new ``__globals__`` attribute on class objects, | ||
| which stores a reference to the globals for the module where | ||
| the class was defined. Note that this attribute is optional, | ||
| but was useful for the CPython implementation. | ||
|
|
||
| (The class ``__globals__`` attribute does create a new reference | ||
| cycle, between a class and its module. However, any class that | ||
| contains a method already participates in at least one such cycle.) | ||
| This PEP does not dictate exactly how it should be | ||
| implemented; that is left up to the language implementation | ||
| maintainers. However, the best implementation of this | ||
| PEP may require adding additional information to existing | ||
| Python objects, which is implicitly condoned by the acceptance | ||
| of this PEP. | ||
|
|
||
| For example, it may be necessary to add a | ||
| ``__globals__`` attribute to class objects, so that the | ||
| ``__annotate__`` function for that class can be lazily | ||
| bound, only on demand. Also, ``__annotate__`` functions | ||
| defined on methods defined in a class may need to retain | ||
| a reference to the class's ``__dict__``, in order to | ||
| correctly evaluate names bound in that class. It's expected | ||
| that the CPython implementation of this PEP will include | ||
| both those new attributes. | ||
|
|
||
| All such new information added to existing Python objects | ||
| should be done with "dunder" attributes, as they will of | ||
| course be implementation details. | ||
|
|
||
|
|
||
| Interactive REPL Shell | ||
|
|
||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.