]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-119180: Documentation for PEP 649 and 749 (#122235)
authorJelle Zijlstra <jelle.zijlstra@gmail.com>
Wed, 11 Sep 2024 14:49:59 +0000 (07:49 -0700)
committerGitHub <noreply@github.com>
Wed, 11 Sep 2024 14:49:59 +0000 (07:49 -0700)
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
Co-authored-by: Carol Willing <carolcode@willingconsulting.com>
Doc/glossary.rst
Doc/howto/annotations.rst
Doc/library/__future__.rst
Doc/library/annotationlib.rst [new file with mode: 0644]
Doc/library/inspect.rst
Doc/library/python.rst
Doc/library/typing.rst
Doc/reference/compound_stmts.rst
Doc/reference/datamodel.rst
Doc/reference/executionmodel.rst
Doc/reference/simple_stmts.rst

index d9f9392c327f5cfb0bb744b9c7b62243dac85e57..ea2f4da093caa0f30b4b09670de6acc36042b692 100644 (file)
@@ -36,6 +36,12 @@ Glossary
       and loaders (in the :mod:`importlib.abc` module).  You can create your own
       ABCs with the :mod:`abc` module.
 
+   annotate function
+      A function that can be called to retrieve the :term:`annotations <annotation>`
+      of an object. This function is accessible as the :attr:`~object.__annotate__`
+      attribute of functions, classes, and modules. Annotate functions are a
+      subset of :term:`evaluate functions <evaluate function>`.
+
    annotation
       A label associated with a variable, a class
       attribute or a function parameter or return value,
@@ -43,12 +49,11 @@ Glossary
 
       Annotations of local variables cannot be accessed at runtime, but
       annotations of global variables, class attributes, and functions
-      are stored in the :attr:`__annotations__`
-      special attribute of modules, classes, and functions,
-      respectively.
+      can be retrieved by calling :func:`annotationlib.get_annotations`
+      on modules, classes, and functions, respectively.
 
-      See :term:`variable annotation`, :term:`function annotation`, :pep:`484`
-      and :pep:`526`, which describe this functionality.
+      See :term:`variable annotation`, :term:`function annotation`, :pep:`484`,
+      :pep:`526`, and :pep:`649`, which describe this functionality.
       Also see :ref:`annotations-howto`
       for best practices on working with annotations.
 
@@ -366,6 +371,11 @@ Glossary
       statements.  The technique contrasts with the :term:`LBYL` style
       common to many other languages such as C.
 
+   evaluate function
+      A function that can be called to evaluate a lazily evaluated attribute
+      of an object, such as the value of type aliases created with the :keyword:`type`
+      statement.
+
    expression
       A piece of syntax which can be evaluated to some value.  In other words,
       an expression is an accumulation of expression elements like literals,
index be8c7e6c827f57aef42791e7d6805d2cb2b6be96..e9fc563f1b5880ed6b30f43c4e70e90494419145 100644 (file)
@@ -34,11 +34,16 @@ Accessing The Annotations Dict Of An Object In Python 3.10 And Newer
 
 Python 3.10 adds a new function to the standard library:
 :func:`inspect.get_annotations`.  In Python versions 3.10
-and newer, calling this function is the best practice for
+through 3.13, calling this function is the best practice for
 accessing the annotations dict of any object that supports
 annotations.  This function can also "un-stringize"
 stringized annotations for you.
 
+In Python 3.14, there is a new :mod:`annotationlib` module
+with functionality for working with annotations. This
+includes a :func:`annotationlib.get_annotations` function,
+which supersedes :func:`inspect.get_annotations`.
+
 If for some reason :func:`inspect.get_annotations` isn't
 viable for your use case, you may access the
 ``__annotations__`` data member manually.  Best practice
@@ -184,7 +189,11 @@ Best Practices For ``__annotations__`` In Any Python Version
 * If you do assign directly to the ``__annotations__`` member
   of an object, you should always set it to a ``dict`` object.
 
-* If you directly access the ``__annotations__`` member
+* You should avoid accessing ``__annotations__`` directly on any object.
+  Instead, use :func:`annotationlib.get_annotations` (Python 3.14+)
+  or :func:`inspect.get_annotations` (Python 3.10+).
+
+* If you do directly access the ``__annotations__`` member
   of an object, you should ensure that it's a
   dictionary before attempting to examine its contents.
 
@@ -231,3 +240,11 @@ itself be quoted.  In effect the annotation is quoted
 
 This prints ``{'a': "'str'"}``.  This shouldn't really be considered
 a "quirk"; it's mentioned here simply because it might be surprising.
+
+If you use a class with a custom metaclass and access ``__annotations__``
+on the class, you may observe unexpected behavior; see
+:pep:`749 <749#pep749-metaclasses>` for some examples. You can avoid these
+quirks by using :func:`annotationlib.get_annotations` on Python 3.14+ or
+:func:`inspect.get_annotations` on Python 3.10+. On earlier versions of
+Python, you can avoid these bugs by accessing the annotations from the
+class's ``__dict__`` (e.g., ``cls.__dict__.get('__annotations__', None)``).
index 1ebff4409b1e95434152a219be217807358577fa..6a1179434acd5a6d9f5b0a4672c326973fab025d 100644 (file)
@@ -64,8 +64,10 @@ language using this mechanism:
 | generator_stop   | 3.5.0b1     | 3.7          | :pep:`479`:                                 |
 |                  |             |              | *StopIteration handling inside generators*  |
 +------------------+-------------+--------------+---------------------------------------------+
-| annotations      | 3.7.0b1     | TBD [1]_     | :pep:`563`:                                 |
-|                  |             |              | *Postponed evaluation of annotations*       |
+| annotations      | 3.7.0b1     | Never [1]_   | :pep:`563`:                                 |
+|                  |             |              | *Postponed evaluation of annotations*,      |
+|                  |             |              | :pep:`649`: *Deferred evalutation of        |
+|                  |             |              | annotations using descriptors*              |
 +------------------+-------------+--------------+---------------------------------------------+
 
 .. XXX Adding a new entry?  Remember to update simple_stmts.rst, too.
@@ -115,11 +117,9 @@ language using this mechanism:
 
 .. [1]
    ``from __future__ import annotations`` was previously scheduled to
-   become mandatory in Python 3.10, but the Python Steering Council
-   twice decided to delay the change
-   (`announcement for Python 3.10 <https://mail.python.org/archives/list/python-dev@python.org/message/CLVXXPQ2T2LQ5MP2Y53VVQFCXYWQJHKZ/>`__;
-   `announcement for Python 3.11 <https://mail.python.org/archives/list/python-dev@python.org/message/VIZEBX5EYMSYIJNDBF6DMUMZOCWHARSO/>`__).
-   No final decision has been made yet. See also :pep:`563` and :pep:`649`.
+   become mandatory in Python 3.10, but the change was delayed and ultimately
+   canceled. This feature will eventually be deprecated and removed. See
+   :pep:`649` and :pep:`749`.
 
 
 .. seealso::
diff --git a/Doc/library/annotationlib.rst b/Doc/library/annotationlib.rst
new file mode 100644 (file)
index 0000000..ecf56ed
--- /dev/null
@@ -0,0 +1,349 @@
+:mod:`!annotationlib` --- Functionality for introspecting annotations
+=====================================================================
+
+.. module:: annotationlib
+   :synopsis: Functionality for introspecting annotations
+
+
+**Source code:** :source:`Lib/annotationlib.py`
+
+.. testsetup:: default
+
+   import annotationlib
+   from annotationlib import *
+
+--------------
+
+The :mod:`!annotationlib` module provides tools for introspecting
+:term:`annotations <annotation>` on modules, classes, and functions.
+
+Annotations are :ref:`lazily evaluated <lazy-evaluation>` and often contain
+forward references to objects that are not yet defined when the annotation
+is created. This module provides a set of low-level tools that can be used to retrieve annotations in a reliable way, even
+in the presence of forward references and other edge cases.
+
+This module supports retrieving annotations in three main formats
+(see :class:`Format`), each of which works best for different use cases:
+
+* :attr:`~Format.VALUE` evaluates the annotations and returns their value.
+  This is most straightforward to work with, but it may raise errors,
+  for example if the annotations contain references to undefined names.
+* :attr:`~Format.FORWARDREF` returns :class:`ForwardRef` objects
+  for annotations that cannot be resolved, allowing you to inspect the
+  annotations without evaluating them. This is useful when you need to
+  work with annotations that may contain unresolved forward references.
+* :attr:`~Format.SOURCE` returns the annotations as a string, similar
+  to how it would appear in the source file. This is useful for documentation
+  generators that want to display annotations in a readable way.
+
+The :func:`get_annotations` function is the main entry point for
+retrieving annotations. Given a function, class, or module, it returns
+an annotations dictionary in the requested format. This module also provides
+functionality for working directly with the :term:`annotate function`
+that is used to evaluate annotations, such as :func:`get_annotate_function`
+and :func:`call_annotate_function`, as well as the
+:func:`call_evaluate_function` function for working with
+:term:`evaluate functions <evaluate function>`.
+
+
+.. seealso::
+
+   :pep:`649` proposed the current model for how annotations work in Python.
+
+   :pep:`749` expanded on various aspects of :pep:`649` and introduced the
+   :mod:`!annotationlib` module.
+
+   :ref:`annotations-howto` provides best practices for working with
+   annotations.
+
+   :pypi:`typing-extensions` provides a backport of :func:`get_annotations`
+   that works on earlier versions of Python.
+
+Annotation semantics
+--------------------
+
+The way annotations are evaluated has changed over the history of Python 3,
+and currently still depends on a :ref:`future import <future>`.
+There have been execution models for annotations:
+
+* *Stock semantics* (default in Python 3.0 through 3.13; see :pep:`3107`
+  and :pep:`526`): Annotations are evaluated eagerly, as they are
+  encountered in the source code.
+* *Stringified annotations* (used with ``from __future__ import annotations``
+  in Python 3.7 and newer; see :pep:`563`): Annotations are stored as
+  strings only.
+* *Deferred evaluation* (default in Python 3.14 and newer; see :pep:`649` and
+  :pep:`749`): Annotations are evaluated lazily, only when they are accessed.
+
+As an example, consider the following program::
+
+   def func(a: Cls) -> None:
+       print(a)
+
+   class Cls: pass
+
+   print(func.__annotations__)
+
+This will behave as follows:
+
+* Under stock semantics (Python 3.13 and earlier), it will throw a
+  :exc:`NameError` at the line where ``func`` is defined,
+  because ``Cls`` is an undefined name at that point.
+* Under stringified annotations (if ``from __future__ import annotations``
+  is used), it will print ``{'a': 'Cls', 'return': 'None'}``.
+* Under deferred evaluation (Python 3.14 and later), it will print
+  ``{'a': <class 'Cls'>, 'return': None}``.
+
+Stock semantics were used when function annotations were first introduced
+in Python 3.0 (by :pep:`3107`) because this was the simplest, most obvious
+way to implement annotations. The same execution model was used when variable
+annotations were introduced in Python 3.6 (by :pep:`526`). However,
+stock semantics caused problems when using annotations as type hints,
+such as a need to refer to names that are not yet defined when the
+annotation is encountered. In addition, there were performance problems
+with executing annotations at module import time. Therefore, in Python 3.7,
+:pep:`563` introduced the ability to store annotations as strings using the
+``from __future__ import annotations`` syntax. The plan at the time was to
+eventually make this behavior the default, but a problem appeared:
+stringified annotations are more difficult to process for those who
+introspect annotations at runtime. An alternative proposal, :pep:`649`,
+introduced the third execution model, deferred evaluation, and was implemented
+in Python 3.14. Stringified annotations are still used if
+``from __future__ import annotations`` is present, but this behavior will
+eventually be removed.
+
+Classes
+-------
+
+.. class:: Format
+
+   An :class:`~enum.IntEnum` describing the formats in which annotations
+   can be returned. Members of the enum, or their equivalent integer values,
+   can be passed to :func:`get_annotations` and other functions in this
+   module, as well as to :attr:`~object.__annotate__` functions.
+
+   .. attribute:: VALUE
+      :value: 1
+
+      Values are the result of evaluating the annotation expressions.
+
+   .. attribute:: FORWARDREF
+      :value: 2
+
+      Values are real annotation values (as per :attr:`Format.VALUE` format)
+      for defined values, and :class:`ForwardRef` proxies for undefined
+      values. Real objects may contain references to, :class:`ForwardRef`
+      proxy objects.
+
+   .. attribute:: SOURCE
+      :value: 3
+
+      Values are the text string of the annotation as it appears in the
+      source code, up to modifications including, but not restricted to,
+      whitespace normalizations and constant values optimizations.
+
+      The exact values of these strings may change in future versions of Python.
+
+   .. versionadded:: 3.14
+
+.. class:: ForwardRef
+
+   A proxy object for forward references in annotations.
+
+   Instances of this class are returned when the :attr:`~Format.FORWARDREF`
+   format is used and annotations contain a name that cannot be resolved.
+   This can happen when a forward reference is used in an annotation, such as
+   when a class is referenced before it is defined.
+
+   .. attribute:: __forward_arg__
+
+      A string containing the code that was evaluated to produce the
+      :class:`~ForwardRef`. The string may not be exactly equivalent
+      to the original source.
+
+   .. method:: evaluate(*, globals=None, locals=None, type_params=None, owner=None)
+
+      Evaluate the forward reference, returning its value.
+
+      This may throw an exception, such as :exc:`NameError`, if the forward
+      reference refers to names that do not exist. The arguments to this
+      method can be used to provide bindings for names that would otherwise
+      be undefined.
+
+      :class:`~ForwardRef` instances returned by :func:`get_annotations`
+      retain references to information about the scope they originated from,
+      so calling this method with no further arguments may be sufficient to
+      evaluate such objects. :class:`~ForwardRef` instances created by other
+      means may not have any information about their scope, so passing
+      arguments to this method may be necessary to evaluate them successfully.
+
+      *globals* and *locals* are passed to :func:`eval`, representing
+      the global and local namespaces in which the name is evaluated.
+      *type_params*, if given, must be a tuple of
+      :ref:`type parameters <type-params>` that are in scope while the forward
+      reference is being evaluated. *owner* is the object that owns the
+      annotation from which the forward reference derives, usually a function,
+      class, or module.
+
+      .. important::
+
+         Once a :class:`~ForwardRef` instance has been evaluated, it caches
+         the evaluated value, and future calls to :meth:`evaluate` will return
+         the cached value, regardless of the parameters passed in.
+
+   .. versionadded:: 3.14
+
+
+Functions
+---------
+
+.. function:: call_annotate_function(annotate, format, *, owner=None)
+
+   Call the :term:`annotate function` *annotate* with the given *format*,
+   a member of the :class:`Format` enum, and return the annotations
+   dictionary produced by the function.
+
+   This helper function is required because annotate functions generated by
+   the compiler for functions, classes, and modules only support
+   the :attr:`~Format.VALUE` format when called directly.
+   To support other formats, this function calls the annotate function
+   in a special environment that allows it to produce annotations in the
+   other formats. This is a useful building block when implementing
+   functionality that needs to partially evaluate annotations while a class
+   is being constructed.
+
+   *owner* is the object that owns the annotation function, usually
+   a function, class, or module. If provided, it is used in the
+   :attr:`~Format.FORWARDREF` format to produce a :class:`ForwardRef`
+   object that carries more information.
+
+   .. seealso::
+
+      :PEP:`PEP 649 <649#the-stringizer-and-the-fake-globals-environment>`
+      contains an explanation of the implementation technique used by this
+      function.
+
+   .. versionadded:: 3.14
+
+.. function:: call_evaluate_function(evaluate, format, *, owner=None)
+
+   Call the :term:`evaluate function` *evaluate* with the given *format*,
+   a member of the :class:`Format` enum, and return the value produced by
+   the function. This is similar to :func:`call_annotate_function`,
+   but the latter always returns a dictionary mapping strings to annotations,
+   while this function returns a single value.
+
+   This is intended for use with the evaluate functions generated for lazily
+   evaluated elements related to type aliases and type parameters:
+
+   * :meth:`typing.TypeAliasType.evaluate_value`, the value of type aliases
+   * :meth:`typing.TypeVar.evaluate_bound`, the bound of type variables
+   * :meth:`typing.TypeVar.evaluate_constraints`, the constraints of
+     type variables
+   * :meth:`typing.TypeVar.evaluate_default`, the default value of
+     type variables
+   * :meth:`typing.ParamSpec.evaluate_default`, the default value of
+     parameter specifications
+   * :meth:`typing.TypeVarTuple.evaluate_default`, the default value of
+     type variable tuples
+
+   *owner* is the object that owns the evaluate function, such as the type
+   alias or type variable object.
+
+   *format* can be used to control the format in which the value is returned:
+
+   .. doctest::
+
+      >>> type Alias = undefined
+      >>> call_evaluate_function(Alias.evaluate_value, Format.VALUE)
+      Traceback (most recent call last):
+      ...
+      NameError: name 'undefined' is not defined
+      >>> call_evaluate_function(Alias.evaluate_value, Format.FORWARDREF)
+      ForwardRef('undefined')
+      >>> call_evaluate_function(Alias.evaluate_value, Format.SOURCE)
+      'undefined'
+
+   .. versionadded:: 3.14
+
+.. function:: get_annotate_function(obj)
+
+   Retrieve the :term:`annotate function` for *obj*. Return :const:`!None`
+   if *obj* does not have an annotate function.
+
+   This is usually equivalent to accessing the :attr:`~object.__annotate__`
+   attribute of *obj*, but direct access to the attribute may return the wrong
+   object in certain situations involving metaclasses. This function should be
+   used instead of accessing the attribute directly.
+
+   .. versionadded:: 3.14
+
+.. function:: get_annotations(obj, *, globals=None, locals=None, eval_str=False, format=Format.VALUE)
+
+   Compute the annotations dict for an object.
+
+   *obj* may be a callable, class, module, or other object with
+   :attr:`~object.__annotate__` and :attr:`~object.__annotations__` attributes.
+   Passing in an object of any other type raises :exc:`TypeError`.
+
+   The *format* parameter controls the format in which annotations are returned,
+   and must be a member of the :class:`Format` enum or its integer equivalent.
+
+   Returns a dict. :func:`!get_annotations` returns a new dict every time
+   it's called; calling it twice on the same object will return two
+   different but equivalent dicts.
+
+   This function handles several details for you:
+
+   * If *eval_str* is true, values of type :class:`!str` will
+     be un-stringized using :func:`eval`. This is intended
+     for use with stringized annotations
+     (``from __future__ import annotations``). It is an error
+     to set *eval_str* to true with formats other than :attr:`Format.VALUE`.
+   * If *obj* doesn't have an annotations dict, returns an
+     empty dict. (Functions and methods always have an
+     annotations dict; classes, modules, and other types of
+     callables may not.)
+   * Ignores inherited annotations on classes, as well as annotations
+     on metaclasses. If a class
+     doesn't have its own annotations dict, returns an empty dict.
+   * All accesses to object members and dict values are done
+     using ``getattr()`` and ``dict.get()`` for safety.
+
+   *eval_str* controls whether or not values of type :class:`!str` are
+   replaced with the result of calling :func:`eval` on those values:
+
+   * If eval_str is true, :func:`eval` is called on values of type
+     :class:`!str`. (Note that :func:`!get_annotations` doesn't catch
+     exceptions; if :func:`eval()` raises an exception, it will unwind
+     the stack past the :func:`!get_annotations` call.)
+   * If *eval_str* is false (the default), values of type :class:`!str` are
+     unchanged.
+
+   *globals* and *locals* are passed in to :func:`eval`; see the documentation
+   for :func:`eval` for more information. If *globals* or *locals*
+   is :const:`!None`, this function may replace that value with a
+   context-specific default, contingent on ``type(obj)``:
+
+   * If *obj* is a module, *globals* defaults to ``obj.__dict__``.
+   * If *obj* is a class, *globals* defaults to
+     ``sys.modules[obj.__module__].__dict__`` and *locals* defaults
+     to the *obj* class namespace.
+   * If *obj* is a callable, *globals* defaults to
+     :attr:`obj.__globals__ <function.__globals__>`,
+     although if *obj* is a wrapped function (using
+     :func:`functools.update_wrapper`) or a :class:`functools.partial` object,
+     it is unwrapped until a non-wrapped function is found.
+
+   Calling :func:`!get_annotations` is best practice for accessing the
+   annotations dict of any object. See :ref:`annotations-howto` for
+   more information on annotations best practices.
+
+   .. doctest::
+
+      >>> def f(a: int, b: str) -> float:
+      ...     pass
+      >>> get_annotations(f)
+      {'a': <class 'int'>, 'b': <class 'str'>, 'return': <class 'float'>}
+
+   .. versionadded:: 3.14
index d19e779a52a6df4180fcbeda55c6ec954a6904cf..f55824ab5f6cd9965dfcfa8c3785a0549d042228 100644 (file)
@@ -718,19 +718,19 @@ function.
    Accepts a wide range of Python callables, from plain functions and classes to
    :func:`functools.partial` objects.
 
-   For objects defined in modules using stringized annotations
-   (``from __future__ import annotations``), :func:`signature` will
+   If some of the annotations are strings (e.g., because
+   ``from __future__ import annotations`` was used), :func:`signature` will
    attempt to automatically un-stringize the annotations using
-   :func:`get_annotations`.  The
+   :func:`annotationlib.get_annotations`.  The
    *globals*, *locals*, and *eval_str* parameters are passed
-   into :func:`get_annotations` when resolving the
-   annotations; see the documentation for :func:`get_annotations`
+   into :func:`!annotationlib.get_annotations` when resolving the
+   annotations; see the documentation for :func:`!annotationlib.get_annotations`
    for instructions on how to use these parameters.
 
    Raises :exc:`ValueError` if no signature can be provided, and
    :exc:`TypeError` if that type of object is not supported.  Also,
    if the annotations are stringized, and *eval_str* is not false,
-   the ``eval()`` call(s) to un-stringize the annotations in :func:`get_annotations`
+   the ``eval()`` call(s) to un-stringize the annotations in :func:`annotationlib.get_annotations`
    could potentially raise any kind of exception.
 
    A slash(/) in the signature of a function denotes that the parameters prior
@@ -1247,62 +1247,19 @@ Classes and functions
    .. versionadded:: 3.4
 
 
-.. function:: get_annotations(obj, *, globals=None, locals=None, eval_str=False)
+.. function:: get_annotations(obj, *, globals=None, locals=None, eval_str=False, format=annotationlib.Format.VALUE)
 
    Compute the annotations dict for an object.
 
-   ``obj`` may be a callable, class, or module.
-   Passing in an object of any other type raises :exc:`TypeError`.
-
-   Returns a dict.  ``get_annotations()`` returns a new dict every time
-   it's called; calling it twice on the same object will return two
-   different but equivalent dicts.
-
-   This function handles several details for you:
-
-   * If ``eval_str`` is true, values of type ``str`` will
-     be un-stringized using :func:`eval`.  This is intended
-     for use with stringized annotations
-     (``from __future__ import annotations``).
-   * If ``obj`` doesn't have an annotations dict, returns an
-     empty dict.  (Functions and methods always have an
-     annotations dict; classes, modules, and other types of
-     callables may not.)
-   * Ignores inherited annotations on classes.  If a class
-     doesn't have its own annotations dict, returns an empty dict.
-   * All accesses to object members and dict values are done
-     using ``getattr()`` and ``dict.get()`` for safety.
-   * Always, always, always returns a freshly created dict.
-
-   ``eval_str`` controls whether or not values of type ``str`` are replaced
-   with the result of calling :func:`eval` on those values:
-
-   * If eval_str is true, :func:`eval` is called on values of type ``str``.
-     (Note that ``get_annotations`` doesn't catch exceptions; if :func:`eval`
-     raises an exception, it will unwind the stack past the ``get_annotations``
-     call.)
-   * If eval_str is false (the default), values of type ``str`` are unchanged.
-
-   ``globals`` and ``locals`` are passed in to :func:`eval`; see the documentation
-   for :func:`eval` for more information.  If ``globals`` or ``locals``
-   is ``None``, this function may replace that value with a context-specific
-   default, contingent on ``type(obj)``:
-
-   * If ``obj`` is a module, ``globals`` defaults to ``obj.__dict__``.
-   * If ``obj`` is a class, ``globals`` defaults to
-     ``sys.modules[obj.__module__].__dict__`` and ``locals`` defaults
-     to the ``obj`` class namespace.
-   * If ``obj`` is a callable, ``globals`` defaults to
-     :attr:`obj.__globals__ <function.__globals__>`,
-     although if ``obj`` is a wrapped function (using
-     :func:`functools.update_wrapper`) it is first unwrapped.
-
-   Calling ``get_annotations`` is best practice for accessing the
-   annotations dict of any object.  See :ref:`annotations-howto` for
-   more information on annotations best practices.
+   This is an alias for :func:`annotationlib.get_annotations`; see the documentation
+   of that function for more information.
 
    .. versionadded:: 3.10
 
+   .. versionchanged:: 3.14
+      This function is now an alias for :func:`annotationlib.get_annotations`.
+      Calling it as ``inspect.get_annotations`` will continue to work.
+
 
 .. _inspect-stack:
 
index 610435999d9f48c848fa550a0bb61d7aca45a8a1..c2c231af7c3033031cc200aa83e588664792ff0f 100644 (file)
@@ -25,4 +25,5 @@ overview:
    __future__.rst
    gc.rst
    inspect.rst
+   annotationlib.rst
    site.rst
index f8b533a5fc87aa27ce1e08b784a05fbd382a3b7b..cb5b46f7167376d09378603f05f30ed4f8b93d86 100644 (file)
@@ -1825,6 +1825,16 @@ without the dedicated syntax, as documented below.
          the bound is evaluated only when the attribute is accessed, not when
          the type variable is created (see :ref:`lazy-evaluation`).
 
+   .. method:: evaluate_bound
+
+      An :term:`evaluate function` corresponding to the :attr:`~TypeVar.__bound__` attribute.
+      When called directly, this method supports only the :attr:`~annotationlib.Format.VALUE`
+      format, which is equivalent to accessing the :attr:`~TypeVar.__bound__` attribute directly,
+      but the method object can be passed to :func:`annotationlib.call_evaluate_function`
+      to evaluate the value in a different format.
+
+      .. versionadded:: 3.14
+
    .. attribute:: __constraints__
 
       A tuple containing the constraints of the type variable, if any.
@@ -1835,6 +1845,16 @@ without the dedicated syntax, as documented below.
          the constraints are evaluated only when the attribute is accessed, not when
          the type variable is created (see :ref:`lazy-evaluation`).
 
+   .. method:: evaluate_constraints
+
+      An :term:`evaluate function` corresponding to the :attr:`~TypeVar.__constraints__` attribute.
+      When called directly, this method supports only the :attr:`~annotationlib.Format.VALUE`
+      format, which is equivalent to accessing the :attr:`~TypeVar.__constraints__` attribute directly,
+      but the method object can be passed to :func:`annotationlib.call_evaluate_function`
+      to evaluate the value in a different format.
+
+      .. versionadded:: 3.14
+
    .. attribute:: __default__
 
       The default value of the type variable, or :data:`typing.NoDefault` if it
@@ -1842,6 +1862,16 @@ without the dedicated syntax, as documented below.
 
       .. versionadded:: 3.13
 
+   .. method:: evaluate_default
+
+      An :term:`evaluate function` corresponding to the :attr:`~TypeVar.__default__` attribute.
+      When called directly, this method supports only the :attr:`~annotationlib.Format.VALUE`
+      format, which is equivalent to accessing the :attr:`~TypeVar.__default__` attribute directly,
+      but the method object can be passed to :func:`annotationlib.call_evaluate_function`
+      to evaluate the value in a different format.
+
+      .. versionadded:: 3.14
+
    .. method:: has_default()
 
       Return whether or not the type variable has a default value. This is equivalent
@@ -1980,6 +2010,16 @@ without the dedicated syntax, as documented below.
 
       .. versionadded:: 3.13
 
+   .. method:: evaluate_default
+
+      An :term:`evaluate function` corresponding to the :attr:`~TypeVarTuple.__default__` attribute.
+      When called directly, this method supports only the :attr:`~annotationlib.Format.VALUE`
+      format, which is equivalent to accessing the :attr:`~TypeVarTuple.__default__` attribute directly,
+      but the method object can be passed to :func:`annotationlib.call_evaluate_function`
+      to evaluate the value in a different format.
+
+      .. versionadded:: 3.14
+
    .. method:: has_default()
 
       Return whether or not the type variable tuple has a default value. This is equivalent
@@ -2076,6 +2116,16 @@ without the dedicated syntax, as documented below.
 
       .. versionadded:: 3.13
 
+   .. method:: evaluate_default
+
+      An :term:`evaluate function` corresponding to the :attr:`~ParamSpec.__default__` attribute.
+      When called directly, this method supports only the :attr:`~annotationlib.Format.VALUE`
+      format, which is equivalent to accessing the :attr:`~ParamSpec.__default__` attribute directly,
+      but the method object can be passed to :func:`annotationlib.call_evaluate_function`
+      to evaluate the value in a different format.
+
+      .. versionadded:: 3.14
+
    .. method:: has_default()
 
       Return whether or not the parameter specification has a default value. This is equivalent
@@ -2200,6 +2250,32 @@ without the dedicated syntax, as documented below.
          >>> Recursive.__value__
          Mutually
 
+   .. method:: evaluate_value
+
+      An :term:`evaluate function` corresponding to the :attr:`__value__` attribute.
+      When called directly, this method supports only the :attr:`~annotationlib.Format.VALUE`
+      format, which is equivalent to accessing the :attr:`__value__` attribute directly,
+      but the method object can be passed to :func:`annotationlib.call_evaluate_function`
+      to evaluate the value in a different format:
+
+      .. doctest::
+
+         >>> type Alias = undefined
+         >>> Alias.__value__
+         Traceback (most recent call last):
+         ...
+         NameError: name 'undefined' is not defined
+         >>> from annotationlib import Format, call_evaluate_function
+         >>> Alias.evaluate_value(Format.VALUE)
+         Traceback (most recent call last):
+         ...
+         NameError: name 'undefined' is not defined
+         >>> call_evaluate_function(Alias.evaluate_value, Format.FORWARDREF)
+         ForwardRef('undefined')
+
+      .. versionadded:: 3.14
+
+
 Other special directives
 """"""""""""""""""""""""
 
@@ -3306,7 +3382,7 @@ Introspection helpers
    Class used for internal typing representation of string forward references.
 
    For example, ``List["SomeClass"]`` is implicitly transformed into
-   ``List[ForwardRef("SomeClass")]``.  ``ForwardRef`` should not be instantiated by
+   ``List[ForwardRef("SomeClass")]``.  :class:`!ForwardRef` should not be instantiated by
    a user, but may be used by introspection tools.
 
    .. note::
@@ -3316,6 +3392,39 @@ Introspection helpers
 
    .. versionadded:: 3.7.4
 
+   .. versionchanged:: 3.14
+      This is now an alias for :class:`annotationlib.ForwardRef`.
+
+.. function:: evaluate_forward_ref(forward_ref, *, owner=None, globals=None, locals=None, type_params=None, format=annotationlib.Format.VALUE)
+
+   Evaluate an :class:`annotationlib.ForwardRef` as a :term:`type hint`.
+
+   This is similar to calling :meth:`annotationlib.ForwardRef.evaluate`,
+   but unlike that method, :func:`!evaluate_forward_ref` also:
+
+   * Recursively evaluates forward references nested within the type hint.
+   * Raises :exc:`TypeError` when it encounters certain objects that are
+     not valid type hints.
+   * Replaces type hints that evaluate to :const:`!None` with
+     :class:`types.NoneType`.
+   * Supports the :attr:`~annotationlib.Format.FORWARDREF` and
+     :attr:`~annotationlib.Format.SOURCE` formats.
+
+   *forward_ref* must be an instance of :class:`~annotationlib.ForwardRef`.
+   *owner*, if given, should be the object that holds the annotations that
+   the forward reference derived from, such as a module, class object, or function.
+   It is used to infer the namespaces to use for looking up names.
+   *globals* and *locals* can also be explicitly given to provide
+   the global and local namespaces.
+   *type_params* is a tuple of :ref:`type parameters <type-params>` that
+   are in scope when evaluating the forward reference.
+   This parameter must be provided (though it may be an empty tuple) if *owner*
+   is not given and the forward reference does not already have an owner set.
+   *format* specifies the format of the annotation and is a member of
+   the :class:`annotationlib.Format` enum.
+
+   .. versionadded:: 3.14
+
 .. data:: NoDefault
 
    A sentinel object used to indicate that a type parameter has no default
index 46ee3a174f3d0f8beec2329d82cb6c79b5ad87a4..d31fbf87b739dc33b511b605d9afa4e0948736af 100644 (file)
@@ -1329,13 +1329,7 @@ following the parameter name.  Any parameter may have an annotation, even those
 ``*identifier`` or ``**identifier``.  Functions may have "return" annotation of
 the form "``-> expression``" after the parameter list.  These annotations can be
 any valid Python expression.  The presence of annotations does not change the
-semantics of a function.  The annotation values are available as values of
-a dictionary keyed by the parameters' names in the :attr:`__annotations__`
-attribute of the function object.  If the ``annotations`` import from
-:mod:`__future__` is used, annotations are preserved as strings at runtime which
-enables postponed evaluation.  Otherwise, they are evaluated when the function
-definition is executed.  In this case annotations may be evaluated in
-a different order than they appear in the source code.
+semantics of a function. See :ref:`annotations` for more information on annotations.
 
 .. index:: pair: lambda; expression
 
@@ -1852,6 +1846,44 @@ Here, ``annotation-def`` (not a real keyword) indicates an
 :ref:`annotation scope <annotation-scopes>`. The capitalized names
 like ``TYPE_PARAMS_OF_ListOrSet`` are not actually bound at runtime.
 
+.. _annotations:
+
+Annotations
+===========
+
+.. versionchanged:: 3.14
+   Annotations are now lazily evaluated by default.
+
+Variables and function parameters may carry :term:`annotations <annotation>`,
+created by adding a colon after the name, followed by an expression::
+
+   x: annotation = 1
+   def f(param: annotation): ...
+
+Functions may also carry a return annotation following an arrow::
+
+   def f() -> annotation: ...
+
+Annotations are conventionally used for :term:`type hints <type hint>`, but this
+is not enforced by the language, and in general annotations may contain arbitrary
+expressions. The presence of annotations does not change the runtime semantics of
+the code, except if some mechanism is used that introspects and uses the annotations
+(such as :mod:`dataclasses` or :func:`functools.singledispatch`).
+
+By default, annotations are lazily evaluated in a :ref:`annotation scope <annotation-scopes>`.
+This means that they are not evaluated when the code containing the annotation is evaluated.
+Instead, the interpreter saves information that can be used to evaluate the annotation later
+if requested. The :mod:`annotationlib` module provides tools for evaluating annotations.
+
+If the :ref:`future statement <future>` ``from __future__ import annotations`` is present,
+all annotations are instead stored as strings::
+
+   >>> from __future__ import annotations
+   >>> def f(param: annotation): ...
+   >>> f.__annotations__
+   {'param': 'annotation'}
+
+
 .. rubric:: Footnotes
 
 .. [#] The exception is propagated to the invocation stack unless
index ee9703819e2674cb45405fa3440e22f7d9dcc0d0..21aee0b6d0e3c5a6b703b5fa83fb30ac712b318f 100644 (file)
@@ -581,6 +581,7 @@ Special writable attributes
    single: __defaults__ (function attribute)
    single: __code__ (function attribute)
    single: __annotations__ (function attribute)
+   single: __annotate__ (function attribute)
    single: __kwdefaults__ (function attribute)
    single: __type_params__ (function attribute)
 
@@ -628,7 +629,17 @@ Most of these attributes check the type of the assigned value:
        :term:`parameters <parameter>`.
        The keys of the dictionary are the parameter names,
        and ``'return'`` for the return annotation, if provided.
-       See also: :ref:`annotations-howto`.
+       See also: :attr:`object.__annotations__`.
+
+       .. versionchanged:: 3.14
+          Annotations are now :ref:`lazily evaluated <lazy-evaluation>`.
+          See :pep:`649`.
+
+   * - .. attribute:: function.__annotate__
+     - The :term:`annotate function` for this function, or ``None``
+       if the function has no annotations. See :attr:`object.__annotate__`.
+
+       .. versionadded:: 3.14
 
    * - .. attribute:: function.__kwdefaults__
      - A :class:`dictionary <dict>` containing defaults for keyword-only
@@ -881,6 +892,7 @@ Attribute assignment updates the module's namespace dictionary, e.g.,
    single: __doc__ (module attribute)
    single: __file__ (module attribute)
    single: __annotations__ (module attribute)
+   single: __annotate__ (module attribute)
    pair: module; namespace
 
 Predefined (writable) attributes:
@@ -901,11 +913,21 @@ Predefined (writable) attributes:
       loaded dynamically from a shared library, it's the pathname of the shared
       library file.
 
-   :attr:`__annotations__`
+   :attr:`~object.__annotations__`
       A dictionary containing
       :term:`variable annotations <variable annotation>` collected during
       module body execution.  For best practices on working
-      with :attr:`__annotations__`, please see :ref:`annotations-howto`.
+      with :attr:`!__annotations__`, see :mod:`annotationlib`.
+
+      .. versionchanged:: 3.14
+         Annotations are now :ref:`lazily evaluated <lazy-evaluation>`.
+         See :pep:`649`.
+
+   :attr:`~object.__annotate__`
+      The :term:`annotate function` for this module, or ``None``
+      if the module has no annotations. See :attr:`object.__annotate__`.
+
+      .. versionadded:: 3.14
 
 .. index:: single: __dict__ (module attribute)
 
@@ -969,6 +991,7 @@ A class object can be called (see above) to yield a class instance (see below).
    single: __bases__ (class attribute)
    single: __doc__ (class attribute)
    single: __annotations__ (class attribute)
+   single: __annotate__ (class attribute)
    single: __type_params__ (class attribute)
    single: __static_attributes__ (class attribute)
    single: __firstlineno__ (class attribute)
@@ -991,12 +1014,36 @@ Special attributes:
    :attr:`__doc__`
       The class's documentation string, or ``None`` if undefined.
 
-   :attr:`__annotations__`
+   :attr:`~object.__annotations__`
       A dictionary containing
       :term:`variable annotations <variable annotation>`
       collected during class body execution.  For best practices on
-      working with :attr:`__annotations__`, please see
-      :ref:`annotations-howto`.
+      working with :attr:`~object.__annotations__`, please see
+      :mod:`annotationlib`.
+
+      .. warning::
+
+         Accessing the :attr:`~object.__annotations__` attribute of a class
+         object directly may yield incorrect results in the presence of
+         metaclasses. Use :func:`annotationlib.get_annotations` to
+         retrieve class annotations safely.
+
+      .. versionchanged:: 3.14
+         Annotations are now :ref:`lazily evaluated <lazy-evaluation>`.
+         See :pep:`649`.
+
+   :attr:`~object.__annotate__`
+      The :term:`annotate function` for this class, or ``None``
+      if the class has no annotations. See :attr:`object.__annotate__`.
+
+      .. warning::
+
+         Accessing the :attr:`~object.__annotate__` attribute of a class
+         object directly may yield incorrect results in the presence of
+         metaclasses. Use :func:`annotationlib.get_annotate_function` to
+         retrieve the annotate function safely.
+
+      .. versionadded:: 3.14
 
    :attr:`__type_params__`
       A tuple containing the :ref:`type parameters <type-params>` of
@@ -3253,6 +3300,51 @@ implement the protocol in Python.
    :class:`collections.abc.Buffer`
       ABC for buffer types.
 
+Annotations
+-----------
+
+Functions, classes, and modules may contain :term:`annotations <annotation>`,
+which are a way to associate information (usually :term:`type hints <type hint>`)
+with a symbol.
+
+.. attribute:: object.__annotations__
+
+   This attribute contains the annotations for an object. It is
+   :ref:`lazily evaluated <lazy-evaluation>`, so accessing the attribute may
+   execute arbitrary code and raise exceptions. If evaluation is successful, the
+   attribute is set to a dictionary mapping from variable names to annotations.
+
+   .. versionchanged:: 3.14
+      Annotations are now lazily evaluated.
+
+.. method:: object.__annotate__(format)
+
+   An :term:`annotate function`.
+   Returns a new dictionary object mapping attribute/parameter names to their annotation values.
+
+   Takes a format parameter specifying the format in which annotations values should be provided.
+   It must be a member of the :class:`annotationlib.Format` enum, or an integer with
+   a value corresponding to a member of the enum.
+
+   If an annotate function doesn't support the requested format, it must raise
+   :exc:`NotImplementedError`. Annotate functions must always support
+   :attr:`~annotationlib.Format.VALUE` format; they must not raise
+   :exc:`NotImplementedError()` when called with this format.
+
+   When called with  :attr:`~annotationlib.Format.VALUE` format, an annotate function may raise
+   :exc:`NameError`; it must not raise :exc:`!NameError` when called requesting any other format.
+
+   If an object does not have any annotations, :attr:`~object.__annotate__` should preferably be set
+   to ``None`` (it can’t be deleted), rather than set to a function that returns an empty dict.
+
+   .. versionadded:: 3.14
+
+.. seealso::
+
+   :pep:`649` --- Deferred evaluation of annotation using descriptors
+      Introduces lazy evaluation of annotations and the ``__annotate__`` function.
+
+
 .. _special-lookup:
 
 Special method lookup
index f24e1537af39ed54149b6c6096b761f43c06cb67..a02b5153ef0620314cdca53f70b931ecd713b80c 100644 (file)
@@ -190,14 +190,15 @@ However, the following will succeed::
 Annotation scopes
 -----------------
 
-:ref:`Type parameter lists <type-params>` and :keyword:`type` statements
+:term:`Annotations <annotation>`, :ref:`type parameter lists <type-params>`
+and :keyword:`type` statements
 introduce *annotation scopes*, which behave mostly like function scopes,
-but with some exceptions discussed below. :term:`Annotations <annotation>`
-currently do not use annotation scopes, but they are expected to use
-annotation scopes in Python 3.13 when :pep:`649` is implemented.
+but with some exceptions discussed below.
 
 Annotation scopes are used in the following contexts:
 
+* :term:`Function annotations <function annotation>`.
+* :term:`Variable annotations <variable annotation>`.
 * Type parameter lists for :ref:`generic type aliases <generic-type-aliases>`.
 * Type parameter lists for :ref:`generic functions <generic-functions>`.
   A generic function's annotations are
@@ -236,17 +237,23 @@ Annotation scopes differ from function scopes in the following ways:
    Annotation scopes are also used for type parameter defaults, as
    introduced by :pep:`696`.
 
+.. versionchanged:: 3.14
+   Annotation scopes are now also used for annotations, as specified in
+   :pep:`649` and :pep:`749`.
+
 .. _lazy-evaluation:
 
 Lazy evaluation
 ---------------
 
-The values of type aliases created through the :keyword:`type` statement are
-*lazily evaluated*. The same applies to the bounds, constraints, and default values of type
+Most annotation scopes are *lazily evaluated*. This includes annotations,
+the values of type aliases created through the :keyword:`type` statement, and
+the bounds, constraints, and default values of type
 variables created through the :ref:`type parameter syntax <type-params>`.
 This means that they are not evaluated when the type alias or type variable is
-created. Instead, they are only evaluated when doing so is necessary to resolve
-an attribute access.
+created, or when the object carrying annotations is created. Instead, they
+are only evaluated when necessary, for example when the ``__value__``
+attribute on a type alias is accessed.
 
 Example:
 
index 618664b23f06806b92db420525d415fefcb3fbda..24df4a6ba7b67847d9a0d2ba661ae943a5589877 100644 (file)
@@ -336,23 +336,21 @@ The difference from normal :ref:`assignment` is that only a single target is all
 The assignment target is considered "simple" if it consists of a single
 name that is not enclosed in parentheses.
 For simple assignment targets, if in class or module scope,
-the annotations are evaluated and stored in a special class or module
-attribute :attr:`__annotations__`
-that is a dictionary mapping from variable names (mangled if private) to
-evaluated annotations. This attribute is writable and is automatically
-created at the start of class or module body execution, if annotations
-are found statically.
+the annotations are gathered in a lazily evaluated
+:ref:`annotation scope <annotation-scopes>`. The annotations can be
+evaluated using the :attr:`~object.__annotations__` attribute of a
+class or module, or using the facilities in the :mod:`annotationlib`
+module.
 
 If the assignment target is not simple (an attribute, subscript node, or
-parenthesized name), the annotation is evaluated if
-in class or module scope, but not stored.
+parenthesized name), the annotation is never evaluated.
 
 If a name is annotated in a function scope, then this name is local for
 that scope. Annotations are never evaluated and stored in function scopes.
 
 If the right hand side is present, an annotated
-assignment performs the actual assignment before evaluating annotations
-(where applicable). If the right hand side is not present for an expression
+assignment performs the actual assignment as if there was no annotation
+present. If the right hand side is not present for an expression
 target, then the interpreter evaluates the target except for the last
 :meth:`~object.__setitem__` or :meth:`~object.__setattr__` call.
 
@@ -373,6 +371,10 @@ target, then the interpreter evaluates the target except for the last
    regular assignments. Previously, some expressions (like un-parenthesized
    tuple expressions) caused a syntax error.
 
+.. versionchanged:: 3.14
+   Annotations are now lazily evaluated in a separate :ref:`annotation scope <annotation-scopes>`.
+   If the assignment target is not simple, annotations are never evaluated.
+
 
 .. _assert:
 
@@ -975,8 +977,8 @@ block textually preceding that :keyword:`!global` statement.
 
 Names listed in a :keyword:`global` statement must not be defined as formal
 parameters, or as targets in :keyword:`with` statements or :keyword:`except` clauses, or in a :keyword:`for` target list, :keyword:`class`
-definition, function definition, :keyword:`import` statement, or variable
-annotation.
+definition, function definition, :keyword:`import` statement, or
+:term:`variable annotations <variable annotation>`.
 
 .. impl-detail::