Skip to content

gh-119180: Add discussion of annotations to the 3.14 What's New #124393

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
merged 5 commits into from
Sep 24, 2024
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 75 additions & 1 deletion Doc/whatsnew/3.14.rst
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,78 @@ Summary -- Release highlights
New Features
============

.. _whatsnew-314-pep649:

PEP 649: Deferred Evaluation of Annotations
-------------------------------------------

The :term:`annotations <annotation>` on functions, classes, and modules are no
longer evaluated eagerly. Instead, annotations are stored in special-purpose
:term:`annotate functions <annotate function>` and evaluated only when
necessary. This is specified in :pep:`649` and :pep:`749`.

The new :mod:`annotationlib` module provides tools for inspecting deferred
annotations. Annotations may be evaluated in the :attr:`~annotationlib.Format.VALUE`
format (which evaluates annotations to runtime values, similar to the behavior in
earlier Python versions), the :attr:`~annotationlib.Format.FORWARDREF` format
(which replaces undefined names with special markers), and the
:attr:`~annotationlib.Format.SOURCE` format (which returns annotations as strings).
Comment on lines +90 to +94
Copy link
Member

Choose a reason for hiding this comment

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

These will render as VALUE, FORWARDREF, SOURCE. Is that what we want, or would Format.VALUE, Format.FORWARDREF and Format.SOURCE be better?

Copy link
Member Author

Choose a reason for hiding this comment

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

I did intend these to render as VALUE etc. Do you think adding Format is better?

Copy link
Member

Choose a reason for hiding this comment

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

I think I'd weakly prefer Format.VALUE, but it might make the markup quite verbose, and I don't have a strong opinion :-)


This example shows how these formats behave::

from annotationlib import get_annotations, Format

def func(arg: Undefined):
pass

print(get_annotations(func, format=Format.VALUE)) # raises NameError
print(get_annotations(func, format=Format.FORWARDREF)) # {'arg': ForwardRef('Undefined')}
print(get_annotations(func, format=Format.SOURCE)) # {'arg': 'Undefined'}

Implications if you write annotations in your code
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

If you write annotations in your code (for example, for use with a static type
checker), then this change probably does not affect you: you can keep
writing annotations the same way you did in previous versions of Python.

You will likely be able to remove quoted strings in annotations, which are frequently
used for forward references. Similarly, if you use ``from __future__ import annotations``
to avoid having to write strings in annotations, you may well be able to
remove it. However, if you rely on third-party libraries that read annotations,
those libraries may need changes to support unquoted annotations.

Implications if you read ``__annotations__``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

If your code reads the ``__annotations__`` attribute on objects, you may want
to make changes in order to support code that relies on deferred evaluation of
annotations. For example, you may want to use the :func:`annotationlib.get_annotations`
with the :attr:`~annotationlib.Format.FORWARDREF` format, as the :mod:`dataclasses`
module now does.

Related changes
^^^^^^^^^^^^^^^

The changes in Python 3.14 are designed to minimize changes to code that contains
annotations in source code and to code that reads ``__annotations__``. However,
there are many changes to the supporting code, and if you rely on undocumented
details of the annotation behavior or on private functions in the standard library,
your code may not work in Python 3.14. To safeguard your code against future changes,
use only the documented functionality of the :mod:`annotationlib` module.

``from __future__ import annotations``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

In Python 3.7, :pep:`563` introduced the ``from __future__ import annotations``
directive, which turns all annotations into strings. This directive is now
considered deprecated and it is expected to be removed in a future version of Python.
However, this removal will not happen until after Python 3.13, the last version of
Python without deferred evaluation of annotations, loses support.
In Python 3.14, the behavior of code using ``from __future__ import annotations``
does not change.


Improved Error Messages
-----------------------

Expand Down Expand Up @@ -109,7 +181,9 @@ Other Language Changes
New Modules
===========

* None yet.
* :mod:`annotationlib`: For introspecting :term:`annotations <annotation>`.
See :pep:`749` for more details.
(Contributed by Jelle Zijlstra in :gh:`119180`.)


Improved Modules
Expand Down
Loading