From ca5df27e5fac19be3308b659beb2d38cac8b803e Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Mon, 26 May 2025 08:35:04 -0700 Subject: [PATCH] gh-119180: Updates to PEP 649/749 docs (GH-134640) - Mention (again) that `type.__annotations__` is unsafe. It is now safe when using only classes defined under PEP 649 semantics, but not with classes defined using `from __future__ import annotations`. - Mention that annotations on instances no longer work. There was already an issue about this. - Mention the general changes in the "Porting to Python 3.14" section. - `annotationlib` was proposed by PEP-749, not PEP-649. (cherry picked from commit 7291eaba8b20b19e7971d43d88286d5820e5eb56) Co-authored-by: Jelle Zijlstra Co-authored-by: Emma Smith Co-authored-by: Carol Willing --- Doc/reference/datamodel.rst | 14 +++++++++++++- Doc/whatsnew/3.14.rst | 11 ++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 005a768f684e2c..32a2e266262c52 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1228,10 +1228,22 @@ Special attributes :attr:`__annotations__ attributes `. For best practices on working with :attr:`~object.__annotations__`, - please see :mod:`annotationlib`. Where possible, use + please see :mod:`annotationlib`. Use :func:`annotationlib.get_annotations` instead of accessing this attribute directly. + .. warning:: + + Accessing the :attr:`!__annotations__` attribute directly + on a class object may return annotations for the wrong class, specifically + in certain cases where the class, its base class, or a metaclass + is defined under ``from __future__ import annotations``. + See :pep:`749 <749#pep749-metaclasses>` for details. + + This attribute does not exist on certain builtin classes. On + user-defined classes without ``__annotations__``, it is an + empty dictionary. + .. versionchanged:: 3.14 Annotations are now :ref:`lazily evaluated `. See :pep:`649`. diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 88e52015bdc2b1..561d1a8914b50c 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -74,7 +74,7 @@ deferred evaluation of annotations (:pep:`649`), and a new type of interpreter that uses tail calls. The library changes include the addition of a new :mod:`!annotationlib` module -for introspecting and wrapping annotations (:pep:`649`), +for introspecting and wrapping annotations (:pep:`749`), a new :mod:`!compression.zstd` module for Zstandard support (:pep:`784`), plus syntax highlighting in the REPL, as well as the usual deprecations and removals, @@ -444,6 +444,10 @@ In particular, do not read annotations directly from the namespace dictionary attribute of type objects. Use :func:`annotationlib.get_annotate_from_class_namespace` during class construction and :func:`annotationlib.get_annotations` afterwards. +In previous releases, it was sometimes possible to access class annotations from +an instance of an annotated class. This behavior was undocumented and accidental, +and will no longer work in Python 3.14. + ``from __future__ import annotations`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -2501,6 +2505,11 @@ Changes in the Python API See :ref:`above ` for more details. (Contributed by Jelle Zijlstra in :gh:`105499`.) +* The runtime behavior of annotations has changed in various ways; see + :ref:`above ` for details. While most code that interacts + with annotations should continue to work, some undocumented details may behave + differently. + Build changes =============