At the Core Dev sprint in Bellevue we had a brief [1] discussion about static type annotations in CPython. I want to encapsulate what was discussed and see if the wider core dev community agrees before trying to commit some of this to the devguide.
When static type annotations became a thing, the clear decision was made that they should not, for the time being, go into the standard library. There’s a separate project, typeshed
, that provides type annotations for the stdlib instead. This provides more flexibility for the evolving static typing space to adjust annotations that doesn’t involve waiting for Python releases (not to mention awkward backward compatibility concerns). The recommendation to type checkers and other tooling wanting type annotations has always been to use typeshed
, not annotations that are part of the stdlib.
Where we are now, though, is that we have several bits and pieces of CPython that do use type annotations, and to good effect. Build-time tools like Argument Clinic use them. The test runner, regrtest
and libregrtest
, uses them. The private implementation of the new REPL in 3.13 uses them. A few third-party imports into the stdlib (like tomllib
, importlib.resources
and importlib.metadata
) use them. Also, a few type annotations have snuck into other parts of the stdlib by accident (e.g. cpython/Lib/multiprocessing/connection.py at main · python/cpython · GitHub). For the build tools that use them, as well as regrtest
and PyREPL, we have CI set up so mypy tests them. I believe we don’t have it set up for importlib.resources
and importlib.metadata
, but those are concurrently maintained outside of our repo and tested there. tomllib
had annotations when we pulled it into the stdlib, but the annotations are not currently checked by anything.
Consensus in the room (which included maintainers of typeshed
and several people working on actual type checkers) seemed to be that there’s still not much to be gained from having type annotations in more of the standard library. The typeshed
setup is working well, and avoids some difficult problems (e.g. type checkers supporting different syntax and features, and thus needing slightly different annotations in a forked/vendored copy of typeshed
). Given that typeshed
is supposed to override the stdlib, having the same annotations in the stdlib itself wouldn’t gain us anything, and having different annotations might be confusing to users.
Type annotations on the tooling we use is valuable, and we should keep it. If we pull modules into the stdlib with type annotations, we should keep them. We should take care to actually validate the type annotations, though. Right now we do that for some of the type annotated code, with mypy. Whether we should keep using mypy longer term (or switch to another type checker), and what configuration to use for mypy, is a bit uncertain. Effectively, mypy wins by default for now, but we should be open to re-evaluate. There’s a small pain point when the type-checked code uses features of the stdlib that haven’t been reflected in typeshed
yet, but according to the typeshed
maintainers they’re happy to take PRs for unreleased features, even if it means potentially rolling them back.
The actual type checking is currently done by CI but not from the Makefile. We should probably make it easier to run the type checker of choice during development, with a suitable make target. We should also document this state in the devguide, along with instructions on how to add new things that should be tested with the type checker.
There’s also the question of how type annotations (in particular in the stdlib) should show up in the documentation. Sphinx has the ability to display them (which we don’t currently do), but especially for complex types it might not produce the most readable output. It is probably a good idea for well-annotated libraries with simple enough types, though.
Are there any other concerns people want to bring up? (Or, for people who were at the Core Dev sprint, did I miss anything we discussed?) Do people generally agree with the status quo, or are there strong arguments to change something (like getting rid of annotations where we currently have them, or having more annotations)?
The list of action items so far, based on the consensus in the room:
- Clean up the type checking we currently do, making it easier to run outside of CI and to add new things to type-check.
- Revisit type annotations outside of the things currently being type-checked (e.g. the type annotations that snuck into a few places). Maybe we should remove them, maybe we should actively type-check them, instead. Unchecked type annotations are a bad idea.
- Figure out whether we should include type annotations in generated docs, and how.
- Document all this in the devguide.
Other thoughts on things we should improve around static type annotations in CPython?
by some standards ↩︎