Skip to content

Commit 44afe0d

Browse files
committed
More updates
1 parent 84916e3 commit 44afe0d

File tree

1 file changed

+28
-17
lines changed

1 file changed

+28
-17
lines changed

peps/pep-0749.rst

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ specification:
3636
* The ``SOURCE`` format is renamed to ``STRING`` to improve clarity and reduce the risk of
3737
user confusion.
3838
* Conditionally defined class and module annotations are handled correctly.
39-
* Accessing annotations on a partially executed module will raise :py:exc:`RuntimeError`.
39+
* If annotations are accessed a partially executed module, the annotations executed so far
40+
are returned, but not cached.
4041

4142
Motivation
4243
==========
@@ -793,8 +794,8 @@ circumstances:
793794
* Module and class bodies are only executed once.
794795
* The annotations of a class are not externally visible until execution of the
795796
class body is complete. For modules, this is not quite true, because a partially
796-
executed module can be visible to other imported modules, but this is an
797-
unusual case that is problematic for other reasons (see the next section).
797+
executed module can be visible to other imported modules, but this case is
798+
problematic for other reasons (see the next section).
798799

799800
This allows the following implementation strategy:
800801

@@ -842,7 +843,7 @@ Consider this example:
842843
from . import a
843844
print("in b:", a.__annotations__)
844845
845-
Note that while ``.py`` executes, the ``recmod.a`` module is defined,
846+
Note that while ``recmod/b.py`` executes, the ``recmod.a`` module is defined,
846847
but has not yet finished execution.
847848

848849
On 3.13, this produces:
@@ -866,14 +867,12 @@ Specification
866867
-------------
867868

868869
Accessing ``__annotations__`` on a partially executed module will
869-
raise :py:exc:`RuntimeError`. After module execution is complete,
870-
accessing ``__annotations__`` will execute and cache the annotations as
871-
normal.
872-
873-
This is technically a compatibility break for code that introspects
874-
annotations on partially executed modules, but that should be a rare
875-
case. It is better to couple this compatibility break with the other
876-
changes in annotations behavior introduced by this PEP and :pep:`649`.
870+
continue to return the annotations that have been executed so far,
871+
similar to the behavior in earlier versions in Python. However, in this
872+
case the ``__annotations__`` dictionary will not be cached, so later
873+
accesses to the ``__annotations__`` attribute will return a fresh dictionary.
874+
This is necessary because ``__annotate__`` must be called again in order to
875+
incorporate additional annotations.
877876

878877

879878
Miscellaneous implementation details
@@ -964,16 +963,28 @@ to be supported by third-party libraries. Nevertheless, it is a serious issue fo
964963
that perform introspection, and it is important that we make it as easy as possible for
965964
libraries to support the new semantics in a straightforward, user-friendly way.
966965

967-
We will update those parts of the standard library that are affected by this problem,
968-
and we propose to add commonly useful functionality to the new ``annotationlib`` module,
969-
so third-party tools can use the same set of tools.
966+
Several pieces of functionality in the standard library are affected by this issue,
967+
including :mod:`dataclasses`, :class:`typing.TypedDict` and :class:`typing.NamedTuple`.
968+
These have been updated to support this pattern using the functionality in the new
969+
``annotationlib`` module.
970970

971971

972972
Security Implications
973973
=====================
974974

975-
None.
976-
975+
One consequence of :pep:`649` is that accessing annotations on an object, even if
976+
the object is a function or a module, may now execute arbitrary code. This is true
977+
even if the STRING format is used, because the stringifier mechanism only overrides
978+
the global namespace, and that is not enough to sandbox Python code completely.
979+
980+
In previous Python versions, accessing the annotations of functions or modules
981+
could not execute arbitrary code, but classes and other objects could already
982+
execute arbitrary code on access of the ``__annotations__`` attribute.
983+
Similarly, almost any further introspection on the annotations (e.g.,
984+
using ``isinstance()``, calling functions like ``typing.get_origin``, or even
985+
displaying the annotations with ``repr()``) could already execute arbitrary code.
986+
And of course, accessing annotations from untrusted code implies that the untrusted
987+
code has already been imported.
977988

978989
How to Teach This
979990
=================

0 commit comments

Comments
 (0)