@@ -198,10 +198,11 @@ The module will contain the following functionality:
198198 module, or class. This will replace :py:func: `inspect.get_annotations `. The latter
199199 will delegate to the new function. It may eventually be deprecated, but to
200200 minimize disruption, we do not propose an immediate deprecation.
201- * ``get_annotate_function() ``: A function that returns the ``__annotate__ `` function
202- of an object, if it has one, or ``None `` if it does not. This is usually equivalent
203- to accessing the ``.__annotate__ `` attribute, except in the presence of metaclasses
204- (see :ref: `below <pep749-metaclasses >`).
201+ * ``get_annotate_from_class_namespace(namespace: Mapping[str, Any]) ``: A function that
202+ returns the ``__annotate__ `` function from a class namespace dictionary, or ``None ``
203+ if there is none. This is useful in metaclasses during class construction. It is
204+ a separate function to avoid exposing implementation details about the internal storage
205+ for the ``__annotate__ `` function (see :ref: `below <pep749-metaclasses >`).
205206* ``Format ``: an enum that contains the possible formats of annotations. This will
206207 replace the ``VALUE ``, ``FORWARDREF ``, and ``SOURCE `` formats in :pep: `649 `.
207208 PEP 649 proposed to make these values global members of the :py:mod: `inspect `
@@ -238,7 +239,7 @@ The module will contain the following functionality:
238239 This is useful for
239240 implementing the ``SOURCE `` format in cases where the original source is not available,
240241 such as in the functional syntax for :py:class: `typing.TypedDict `.
241- * ``value_to_string (value: object) -> str ``: a function that converts a single value to a
242+ * ``type_repr (value: object) -> str ``: a function that converts a single value to a
242243 string representation. This is used by ``annotations_to_string ``.
243244 It uses ``repr() `` for most values, but for types it returns the fully qualified name.
244245 It is also useful as a helper for the ``repr() `` of a number of objects in the
@@ -501,45 +502,64 @@ attribute lookup is used, this approach breaks down in the presence of
501502metaclasses, because entries in the metaclass's own class dictionary can render
502503the descriptors invisible.
503504
504- While we considered several approaches that would allow ``cls.__annotations__ ``
505- and ``cls.__annotate__ `` to work reliably when ``cls `` is a type with a custom
506- metaclass, any such approach would expose significant complexity to advanced users.
507- Instead, we recommend a simpler approach that confines the complexity to the
508- ``annotationlib `` module: in ``annotationlib.get_annotations ``, we bypass normal
509- attribute lookup by using the ``type.__annotations__ `` descriptor directly.
505+ We considered several solutions but landed on one where we store the ``__annotate__ ``
506+ and ``__annotations__ `` objects in the class dictionary, but under a different,
507+ internal-only name. This means that the class dictionary entries will not interfere
508+ with the descriptors defined on :py:class: `type `.
509+
510+ This approach means that the ``.__annotate__ `` and ``.__annotations__ `` objects in class
511+ objects will behave mostly intuitively, but there are a few downsides.
512+
513+ One concerns the interaction with classes defined under ``from __future__ import annotations ``.
514+ Those will continue to have the ``__annotations__ `` entry in the class dictionary, meaning
515+ that they will continue to display some buggy behavior. For example, if a metaclass is defined
516+ with the ``__future__ `` import enabled and has annotations, and a class using that metaclass is
517+ defined without the ``__future__ `` import, accessing ``.__annotations__ `` on that class will yield
518+ the wrong results. However, this bug already exists in previous versions of Python. It could be
519+ fixed by setting the annotations at a different key in the class dict in this case too, but that
520+ would break users who directly access the class dictionary (e.g., during class construction).
521+ We prefer to keep the behavior under the ``__future__ `` import unchanged as much as possible.
522+
523+ Second, in previous versions of Python it was possible to access the ``__annotations__ `` attribute
524+ on instances of user-defined classes with annotations. However, this behavior was undocumented
525+ and not supported by :func: `inspect.get_annotations `, and it cannot be preserved under the
526+ :pep: `649 ` framework without bigger changes, such as a new ``object.__annotations__ `` descriptor.
527+ This behavior change should be called out in porting guides.
510528
511529Specification
512530-------------
513531
514- Users should always use ``annotationlib.get_annotations `` to access the
515- annotations of a class object, and ``annotationlib.get_annotate_function ``
516- to access the ``__annotate__ `` function. These functions will return only
517- the class's own annotations, even when metaclasses are involved.
532+ The ``.__annotate__ `` and ``.__annotations__ `` attributes on class objects
533+ should reliably return the annotate function and the annotations dictionary,
534+ respectively, even in the presence of custom metaclasses.
518535
519- The behavior of accessing the ``__annotations__ `` and ``__annotate__ ``
520- attributes on classes with a metaclass other than ``builtins.type `` is
521- unspecified. The documentation should warn against direct use of these
522- attributes and recommend using the ``annotationlib `` module instead.
523-
524- Similarly, the presence of ``__annotations__ `` and ``__annotate__ `` keys
525- in the class dictionary is an implementation detail and should not be relied
526- upon.
536+ Users should not access the class dictionary directly for accessing annotations
537+ or the annotate function; the data stored in the class dictionary is an implementation
538+ detail and its format may change in the future. If only the class namespace
539+ dictionary is available (e.g., while the class is being constructed),
540+ ``annotationlib.get_annotate_function `` may be used to retrieve the annotate function
541+ from the class dictionary.
527542
528543Rejected alternatives
529544---------------------
530545
531- We considered two broad approaches for dealing with the behavior
546+ We considered three broad approaches for dealing with the behavior
532547of the ``__annotations__ `` and ``__annotate__ `` entries in classes:
533548
534549* Ensure that the entry is *always * present in the class dictionary, even if it
535550 is empty or has not yet been evaluated. This means we do not have to rely on
536551 the descriptors defined on :py:class: `type ` to fill in the field, and
537552 therefore the metaclass's attributes will not interfere. (Prototype
538553 in `gh-120719 <https://github.com/python/cpython/pull/120719 >`__.)
554+ * Warn users against using the ``__annotations__ `` and ``__annotate__ `` attributes
555+ directly. Instead, users should call function in ``annotationlib `` that
556+ invoke the :class: `type ` descriptors directly. (Implemented in
557+ `gh-122074 <https://github.com/python/cpython/pull/122074 >`__.)
539558* Ensure that the entry is *never * present in the class dictionary, or at least
540559 never added by logic in the language core. This means that the descriptors
541560 on :py:class: `type ` will always be used, without interference from the metaclass.
542- (Prototype in `gh-120816 <https://github.com/python/cpython/pull/120816 >`__.)
561+ (Initial prototype in `gh-120816 <https://github.com/python/cpython/pull/120816 >`__;
562+ later implemented in `gh-132345 <https://github.com/python/cpython/pull/132345 >`__.)
543563
544564Alex Waygood suggested an implementation using the first approach. When a
545565heap type (such as a class created through the ``class `` statement) is created,
@@ -561,19 +581,8 @@ While this approach would fix the known edge cases with metaclasses, it
561581introduces significant complexity to all classes, including a new built-in type
562582(for the annotations descriptor) with unusual behavior.
563583
564- The alternative approach would be to never set ``__dict__["__annotations__"] ``
565- and use some other storage to store the cached annotations. This behavior
566- change would have to apply even to classes defined under
567- ``from __future__ import annotations ``, because otherwise there could be buggy
568- behavior if a class is defined without ``from __future__ import annotations ``
569- but its metaclass does have the future enabled. As :pep: `649 ` previously noted,
570- removing ``__annotations__ `` from class dictionaries also has backwards compatibility
571- implications: ``cls.__dict__.get("__annotations__") `` is a common idiom to
572- retrieve annotations.
573-
574- This approach would also mean that accessing ``.__annotations__ `` on an instance
575- of an annotated class no longer works. While this behavior is not documented,
576- it is a long-standing feature of Python and is relied upon by some users.
584+ The second approach is simple to implement, but has the downside that direct
585+ access to ``cls.__annotations__ `` remains prone to erratic behavior.
577586
578587Adding the ``VALUE_WITH_FAKE_GLOBALS `` format
579588=============================================
@@ -611,10 +620,17 @@ the ``VALUE_WITH_FAKE_GLOBALS`` format is requested, so the standard
611620library will not call the manually written annotate function with
612621"fake globals", which could have unpredictable results.
613622
623+ The names of annotation formats indicate what kind of objects an
624+ ``__annotate__ `` function should return: with the ``STRING `` format, it
625+ should return strings; with the ``FORWARDREF `` format, it should return
626+ forward references; and with the ``VALUE `` format, it should return values.
627+ The name ``VALUE_WITH_FAKE_GLOBALS `` indicates that the function should
628+ still return values, but is being executed in an unusual "fake globals" environment.
629+
614630Specification
615631-------------
616632
617- An additional format, ``FAKE_GLOBALS_VALUE ``, is added to the ``Format `` enum in the
633+ An additional format, ``VALUE_WITH_FAKE_GLOBALS ``, is added to the ``Format `` enum in the
618634``annotationlib `` module, with value equal to 2. (As a result, the values of the
619635other formats will shift relative to PEP 649: ``FORWARDREF `` will be 3 and ``SOURCE ``
620636will be 4.)
@@ -625,10 +641,10 @@ they would return for the ``VALUE`` format. The standard library will pass
625641this format to the ``__annotate__ `` function when it is called in a "fake globals"
626642environment, as used to implement the ``FORWARDREF `` and ``SOURCE `` formats.
627643All public functions in the ``annotationlib `` module that accept a format
628- argument will raise :py:exc: `NotImplementedError ` if the format is ``FAKE_GLOBALS_VALUE ``.
644+ argument will raise :py:exc: `NotImplementedError ` if the format is ``VALUE_WITH_FAKE_GLOBALS ``.
629645
630646Third-party code that implements ``__annotate__ `` functions should raise
631- :py:exc: `NotImplementedError ` if the ``FAKE_GLOBALS_VALUE `` format is passed
647+ :py:exc: `NotImplementedError ` if the ``VALUE_WITH_FAKE_GLOBALS `` format is passed
632648and the function is not prepared to be run in a "fake globals" environment.
633649This should be mentioned in the data model documentation for ``__annotate__ ``.
634650
0 commit comments