PEP 649: Deferred evaluation of annotations, tentatively accepted

I’m starting to look into implementing the PEP for Python 3.14 (since it didn’t make it into 3.13), and I’d like some clarity on what the __future__ will look like. The current PEP says very little about __future__; I believe a previous version proposed from __future__ import co_annotations, but the current version does not.

I’m happy to implement whatever the Steering Council and the broader community think best, but here’s a concrete proposal so we have something concrete to think about:

  • The default semantics in Python 3.14 will be PEP 649 semantics (lazily evaluated annotations).
  • If from __future__ import annotations is added, Python 3.14 will also use PEP 649 semantics, instead of the current PEP 563 semantics (stringified annotations).
  • from __future__ import annotations therefore will now do nothing. We will keep it around indefinitely, just like any other future that has arrived.

This approach has the advantage that we get into the end state we want (PEP 649 semantics) immediately and we don’t have to deal with any more future changes. The flip side, of course, is that any migration pain will be felt at once.

For the most part, code currently using annotations, either with or without from __future__ import annotations, should continue to work the same with PEP 649 semantics. That is certainly true for code that uses annotations purely statically, and it should also mostly be true for code that introspects annotations at runtime. There will certainly be exceptions where introspection code needs to change. Speaking as the maintainer of one tool that relies heavily on introspecting annotations (pyanalyze), I’d rather have to deal with the semantic change once, instead of having to support multiple variations of annotation semantics for several more years.

However, we can consider alternatives:

  • We could put PEP 649 semantics behind a future import and gain more insight into how it works in practice.
  • We could maintain PEP 563 (stringification) semantics for from __future__ import annotations, and eventually deprecate the future. However, this means we’d have to maintain this path until the last release without PEP 649 semantics (3.13) reaches its end of life, which would be in around 2029.
9 Likes