446 lines
23 KiB
ReStructuredText
446 lines
23 KiB
ReStructuredText
PEP: 729
|
|
Title: Typing governance process
|
|
Author: Jelle Zijlstra <jelle.zijlstra@gmail.com>, Shantanu Jain <hauntsaninja at gmail.com>
|
|
Discussions-To: https://discuss.python.org/t/pep-729-typing-governance-process/35362
|
|
Status: Active
|
|
Type: Process
|
|
Topic: Governance, Typing
|
|
Created: 19-Sep-2023
|
|
Post-History: `04-Oct-2023 <https://discuss.python.org/t/pep-729-typing-governance-process/35362>`__,
|
|
`20-Sep-2023 <https://discuss.python.org/t/proposed-new-typing-governance-process/34244>`__
|
|
Resolution: https://discuss.python.org/t/pep-729-typing-governance-process/35362/12
|
|
|
|
Abstract
|
|
========
|
|
|
|
This PEP proposes a new way to govern the Python type system: a council that is responsible
|
|
for maintaining and developing the Python type system. The council will maintain a
|
|
specification and conformance test suite and will initially be appointed by the Python Steering Council.
|
|
|
|
Motivation
|
|
==========
|
|
|
|
The Python type system was created by :pep:`484`, almost ten years ago. The type
|
|
system is now widely used, and typing has become an important tool for writing
|
|
good, maintainable Python code. Many changes have been made to the type system to cover
|
|
more use cases and improve usability. Several type checkers have been created, each
|
|
with their own strengths. The type annotation syntax has driven several major innovations
|
|
in the Python ecosystem, such as the popular :mod:`dataclasses` module, runtime type
|
|
checking and validation by packages such as `Pydantic <https://docs.pydantic.dev/latest/>`__,
|
|
and static compilation by tools such as `mypyc <https://mypyc.readthedocs.io/en/latest/>`__.
|
|
|
|
However, as the type system has grown, several interrelated problems with the current
|
|
way to manage the type system have become apparent.
|
|
|
|
PEPs are the only specification
|
|
--------------------------------
|
|
|
|
The Python type system was initially created by a PEP (:pep:`484`), and
|
|
changes to the type system are still made by PEPs. The specification for
|
|
the Python type system, to the extent there is one, consists of this series
|
|
of PEPs. But Standards Track PEPs aren't meant to be living documents
|
|
or specifications; they are change proposals.
|
|
|
|
An example may illustrate the problem here. Around the same time
|
|
as the introduction of the :mod:`typing` module by :pep:`484`, :pep:`3156`
|
|
introduced the :mod:`asyncio` module, another major new feature that has
|
|
been instrumental to the success of Python 3. Both modules
|
|
have evolved greatly since their initial creation and inspired changes to the
|
|
core language.
|
|
|
|
However, :mod:`asyncio` and :mod:`typing` are different in an essential aspect:
|
|
a user who uses :mod:`asyncio` interacts only with the standard library itself,
|
|
while a user of :mod:`typing` has to also think about an external tool, the type
|
|
checker. The Python language reference covers the symbols in the typing module, but does
|
|
not (and should not) go into detail on how the full type system should be
|
|
interpreted by type checkers. That material currently exists only in the PEPs.
|
|
|
|
This problem is shared by the packaging ecosystem, which attempts to solve it
|
|
by maintaining a separate set of `PyPA specifications <https://packaging.python.org/en/latest/specifications/>`_.
|
|
|
|
It's hard to evolve the specification
|
|
-------------------------------------
|
|
|
|
Because the PEPs are the only specification we have, anything that could be seen
|
|
as a change to the specification would theoretically require a new PEP. But that
|
|
is often too heavy a process for a small change. Sometimes changes are made
|
|
directly to old PEPs instead, but that goes against the idea that accepted and
|
|
implemented PEPs become historical documents that should no longer be changed.
|
|
|
|
Some concrete examples include:
|
|
|
|
* :pep:`484` explicitly says that :data:`typing.NoReturn` cannot be used in
|
|
argument annotations. Nevertheless, type checkers have long accepted such
|
|
usage.
|
|
* A `2023 discussion <https://discuss.python.org/t/pep-561-clarification-regarding-n/32875>`_
|
|
noted that :pep:`561`'s description of partial stubs is unclear, and
|
|
major type checkers did not implement it exactly as specified.
|
|
* The widely used third-party ``typing_extensions`` package provides backports of new
|
|
type system features. Type checkers are expected to treat symbols in this
|
|
module the same as symbols in :mod:`typing`, but this is not explicitly
|
|
specified in any of the PEPs.
|
|
|
|
The type system is underspecified
|
|
---------------------------------
|
|
|
|
While the PEPs provide a specification, they are often not sufficiently precise
|
|
(sometimes intentionally so). This is especially true as the combinatorial
|
|
complexity of the type system has grown.
|
|
|
|
It ends up falling to individual type checkers to decide how to navigate
|
|
underspecified areas. In cases where type checkers informally coordinate, this
|
|
results in de facto standards that aren't clearly recorded anywhere, making
|
|
the type system less accessible to newcomers. For example:
|
|
|
|
* How ``@overload`` matching works
|
|
* How ``ParamSpec`` `should work <https://github.com/python/typing/discussions/946>`_ `with methods <https://github.com/microsoft/pyright/issues/3954#issuecomment-1250098464>`_
|
|
* The concept of `recursive aliases <https://github.com/python/typing/issues/182>`_
|
|
* Semantics of `variable initialization <https://mail.python.org/archives/list/typing-sig@python.org/thread/GYVM5KEE6URE6PAH7UTK6324M7GWSFQS/#SY3KPJCAW4UTOOCH3XRJYROSGDEGOTWI>`_
|
|
* `Reachability semantics <https://github.com/python/mypy/issues/15158#issuecomment-1677915108>`__
|
|
of annotations on ``__exit__``
|
|
* `Symbol visibility <https://mail.python.org/archives/list/typing-sig@python.org/thread/YLJPWECBNPD2K4TRIBRIPISNUZJCRREY/#OX4GLBQOOCMRE5YPZEY3R3XNV6DD7XLW>`_
|
|
* Use of `NoReturn for exhaustiveness checking <https://github.com/python/mypy/issues/5818>`_
|
|
|
|
The Steering Council is not well-placed to solve the above problems
|
|
-------------------------------------------------------------------
|
|
|
|
The SC has the entire language in its remit, and is not well-placed to make
|
|
decisions that are purely about the type system -- if only because they don't have
|
|
the time to deal with type system arcana alongside their other responsibilities.
|
|
This is similar in spirit to the reasons why the Steering Council sometimes uses
|
|
PEP delegation.
|
|
|
|
Endorsements
|
|
------------
|
|
|
|
This PEP was endorsed by maintainers of all major
|
|
type checkers, including `Rebecca Chen (pytype) <https://discuss.python.org/t/pep-729-typing-governance-process/35362/3>`__,
|
|
`Eric Traut (Pyright) <https://discuss.python.org/t/pep-729-typing-governance-process/35362/4>`__,
|
|
and privately by maintainers of mypy and Pyre.
|
|
|
|
Specification
|
|
=============
|
|
|
|
We propose the creation of a new group, the Typing Council. This group will
|
|
be responsible for developing and maintaining the Python type system, and
|
|
for solving the above problems.
|
|
|
|
The "operations and process" section describes how this group would operate and
|
|
be governed.
|
|
|
|
The more exciting "projects" section describes solutions to the above problems
|
|
that the Typing Council could shepherd.
|
|
|
|
Mandate
|
|
-------
|
|
|
|
The Typing Council's mandate is to ensure that the Python type system is:
|
|
|
|
* **Useful**: The type system should serve common use cases. As identified
|
|
by :pep:`484`, the primary use case is static analysis, but there are others,
|
|
such as runtime type checking, static compilation, IDE support, and documentation.
|
|
The Typing Council should consider all of these use cases when making decisions,
|
|
and be open to supporting additional use cases as they come up.
|
|
* **Usable**: The type system should be easy to use for Python developers. It
|
|
should be ergonomic to write well-typed Python code that is accepted by type
|
|
checkers. There should be good documentation for the type system.
|
|
* **Stable**: As the type system matures, users should be able to rely on their
|
|
typed code continuing to work and be able to trust their mental model for the
|
|
type system. Changes should be made with care and in a way
|
|
that minimizes disruption. Nevertheless, the type system should be able to
|
|
evolve, and it does not make sense to use the same compatibility guidelines
|
|
for type checker behavior as for Python itself. Of course, the existence
|
|
and runtime behavior of objects in the :mod:`typing` module does follow
|
|
Python's standard compatibility policy in :pep:`387`.
|
|
|
|
Operations and process
|
|
----------------------
|
|
|
|
The council would have three to five members, comprised of prominent community members,
|
|
such as Python core developers and maintainers of major type checkers. The members
|
|
should include people affiliated with a variety of projects related to type checking,
|
|
which may include type checkers, CPython, typeshed, or other projects.
|
|
|
|
The initial members of the council are:
|
|
|
|
- Eric Traut (Pyright; author of :pep:`647`, :pep:`681`, and :pep:`695`)
|
|
- Guido van Rossum (core developer; author of :pep:`484` and :pep:`526`)
|
|
- Jelle Zijlstra (core developer; typeshed; pyanalyze; author of :pep:`688` and :pep:`702`)
|
|
- Rebecca Chen (pytype)
|
|
- Shantanu Jain (core developer; typeshed; mypy)
|
|
|
|
There is no term
|
|
limit for council members. Council members may resign their position at any time.
|
|
There is an expectation that each member serves at most five consecutive years
|
|
before resigning.
|
|
|
|
If there is a vacancy and there are three or more remaining members, it is up
|
|
to the Council to decide whether to appoint a new member.
|
|
To determine replacements, nominations will be collected from the typing
|
|
community. Self-nominations are allowed. The existing Typing Council will then decide
|
|
the replacement member(s) from the nominees. The expectation is that this would
|
|
be done by fiat, but the Typing Council can choose a replacement by any means
|
|
they see fit, including a vote.
|
|
|
|
The Typing Council remains accountable to the Steering Council. At any point,
|
|
for any reason, the Steering Council could (publicly or privately) make a
|
|
specific change or request a non-specific change to the composition of the
|
|
Typing Council.
|
|
|
|
We acknowledge that this is a not particularly democratic structure and puts
|
|
a lot of faith in the Typing Council. However, the Python community has a long
|
|
history of success with not particularly democratic structures! We believe
|
|
self-governance, cycling of membership, and accountability to the
|
|
Steering Council will be sufficient to ensure that the Typing Council is meeting
|
|
the needs of the community.
|
|
|
|
The council would operate primarily through reviews of GitHub PRs. Regular
|
|
meetings are likely not necessary, but the council may set up video calls, a
|
|
private chat, or whatever other mechanism they decide upon internally.
|
|
|
|
The council should aim for transparency, posting all decisions publicly on
|
|
`discuss.python.org <https://discuss.python.org/c/typing/32>`__, with a
|
|
rationale if possible. Before making a decision, the council should give
|
|
all interested community members a chance to weigh in. There should be at
|
|
least a week between the start of a discussion and the council's decision.
|
|
|
|
Members of the council will be eligible to sponsor PEPs. If this PEP is accepted,
|
|
:pep:`1` should be amended to note this fact.
|
|
|
|
Relationship with the Steering Council
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Just like today, the Python Steering Council would remain responsible for the
|
|
overall direction of the Python language and would continue to decide on
|
|
typing-related PEPs. The Typing Council would provide written opinions and
|
|
recommendations to the Steering Council on typing-related PEPs.
|
|
|
|
However, smaller changes to the type system could be made
|
|
by the Typing Council directly. The Steering Council could also choose
|
|
to delegate decisions on some PEPs to the Typing Council (exactly as any other
|
|
PEP delegation).
|
|
|
|
Some examples of how past and recent issues could have been handled under this model:
|
|
|
|
- A PEP like :pep:`695` (type parameter syntax), which changes the language
|
|
syntax, would need to be decided upon by the Steering Council; the Typing
|
|
Council would merely provide opinion or endorsement. Similarly, PEPs
|
|
like :pep:`702` (deprecations) would be decided upon by the Steering
|
|
Council, because it concerns runtime behaviour beyond pure typing. Other examples
|
|
that would need to be decided by the SC include :pep:`718` (subscriptable
|
|
functions) and :pep:`727` (documentation metadata).
|
|
- A PEP like :pep:`698` (``@override``), which affects only users of type
|
|
checkers and does not change the overall language, would also by default
|
|
be decided upon by the Steering Council. However, such PEPs could be
|
|
delegated to the Typing Council for a decision (like any other PEP delegation).
|
|
Other examples of PEPs that could potentially be delegated include
|
|
:pep:`647` (type guards), :pep:`655` (individual required ``TypedDict`` items),
|
|
:pep:`673` (``Self``), and :pep:`675` (``Literal``).
|
|
- Adding a smaller feature, such as :data:`typing.Never` as an alias for
|
|
:data:`typing.NoReturn`, would be done by means of a PR to the spec and
|
|
conformance test suite. The Typing
|
|
Council would then decide whether or not to merge the PR. They may ask for the
|
|
feature to be specified and discussed in a PEP if they feel that is warranted.
|
|
- If there is confusion about the interpretation of some part of the spec, like
|
|
happened recently with `partial stubs in PEP
|
|
561 <https://discuss.python.org/t/pep-561-clarification-regarding-n/32875/27>`_,
|
|
somebody would make a PR to the typing specification to clarify the
|
|
spec, and then the Typing Council would decide on the spec change.
|
|
|
|
The runtime :mod:`typing` module will continue to be maintained by the
|
|
CPython core developer team. However, any changes to the runtime module that
|
|
affect type checker behavior should be made in conjunction with a change
|
|
to the specification (see below) and should be approved by the Typing Council.
|
|
For example, in Python 3.11 the core developers added the new function
|
|
:func:`typing.assert_type`. If the Typing Council had been in place, this
|
|
change would require a matching change to the specification and approval
|
|
by the Typing Council. On the other hand, Python 3.11 also added the
|
|
:func:`typing.get_overloads` introspection helper. As this function does not
|
|
affect type checker behavior, it would not require approval by the Typing
|
|
Council. However, as support for runtime type checkers is within the remit
|
|
of the Council, they should monitor such changes and provide feedback when
|
|
appropriate.
|
|
|
|
Relationship with type checkers
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
The Typing Council has no direct authority over type checkers; it cannot
|
|
force them to implement particular features or make behavior changes. Type
|
|
checkers are incentivized to follow the specification set out by the Council
|
|
because it allows them to take advantage of shared resources, such as
|
|
libraries that expose typing information that follows the specification,
|
|
the stub files in typeshed, the ``typing`` standard library module, and
|
|
user documentation that covers the standard type system.
|
|
Type checkers are free to extend the type system or deviate from the
|
|
specification, but they should document such differences clearly.
|
|
|
|
The fact that type checkers need to implement any decisions made by the
|
|
Typing Council acts as a useful brake on the Council, ensuring that its
|
|
decisions are conservative and well-considered. Individual type checkers
|
|
remain free to innovate as they see fit, and successful innovations can
|
|
be incorporated into the standard type system.
|
|
|
|
Projects
|
|
--------
|
|
|
|
Here are some efforts a Typing Council would be responsible for.
|
|
|
|
Conformance test suite
|
|
^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
A conformance test suite would provide machine checkable documentation for how
|
|
type checkers should check Python code, accompanied by the results of major type
|
|
checker implementations on the test suite. A rough sketch for what this could
|
|
look like was `created by Shantanu <https://github.com/hauntsaninja/type_checker_consistency>`_.
|
|
|
|
This would contain prescriptive tests from behavior prescribed by previous PEPs
|
|
and descriptive tests that let us document behavior of existing implementations
|
|
in areas that are not prescribed by any standard. These descriptions would be
|
|
useful to inform efforts below and to identify areas of focus for
|
|
standardization.
|
|
|
|
Specification for the type system
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
A specification would initially be created by stitching together the
|
|
specification sections from the existing PEPs, and then gradually improved to
|
|
clarify points of confusion and cover more areas. A draft of such a
|
|
stitched-together spec was `created by Jelle <https://github.com/JelleZijlstra/typing-spec>`_.
|
|
|
|
The specification has a few audiences:
|
|
|
|
* For type checkers, it provides a description of how an idealized type checker
|
|
should behave. Individual type checkers have different goals and technical
|
|
constraints and they are free to deviate from the spec if they do not have the
|
|
resources to fully implement it or if they believe a different behavior better
|
|
serves their users. However, they should document such deviations from the
|
|
spec.
|
|
* For projects such as typeshed, or libraries that want to be compatible with
|
|
multiple type checkers, it provides a set of rules that they can follow to
|
|
make their code understood by type checkers.
|
|
* For people who want to propose changes to the type system, it provides a
|
|
foundation for any new proposals.
|
|
|
|
Notably, the specification is not aimed at application developers who use
|
|
typing. Such users typically do not
|
|
need to worry about compatibility across type checkers. They
|
|
are better served by a more informal user-facing reference, which is discussed
|
|
in the next section.
|
|
|
|
There are different opinions within the community about how formal such a
|
|
specification should be. While this document recommends an incremental
|
|
approach that builds off existing specification, it does not aim to
|
|
prescribe a final state. The Typing Council would provide a mechanism
|
|
to allow the specification to evolve to meet the level of formality that
|
|
the community desires, for instance, by incorporating parts of
|
|
Kevin Millikin's `document on "Python Static Types" <https://docs.google.com/document/d/1mVCU-nVPT_zVfqivVdMY1aOOZqJ9lsgOLweO1U3uwUM/edit>`_
|
|
as a means to achieve a better formalisation of the spec.
|
|
|
|
Proposed changes to the specification, including PEPs, should
|
|
generally be accompanied by the following:
|
|
|
|
* Buy-in from type checker maintainers to confirm that the
|
|
change can be implemented and maintained within their type
|
|
checkers.
|
|
* For changes to existing features, a survey of the behavior
|
|
of existing type checkers. If existing type checkers
|
|
behave roughly similarly, that is evidence that their shared
|
|
behavior should be made part of the specification.
|
|
* Changes to the conformance test suite that demonstrate the
|
|
specified behavior.
|
|
|
|
User-facing reference for the type system
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Documentation is important for the success of the Python type system, so
|
|
the Typing Council should ensure that there is good documentation for the
|
|
type system.
|
|
|
|
As mentioned previously, PEPs are point in time change proposals aimed at
|
|
multiple audiences that are hard to clarify. This makes them ill-suited as user
|
|
documentation. The specification discussed in the previous section would
|
|
be a living document, but it would likely be too technical to serve as
|
|
documentation for normal usage.
|
|
|
|
Therefore, a separate user-facing reference for the type system would be
|
|
useful. Such an effort could expand the documentation on
|
|
`typing.readthedocs.io <https://typing.readthedocs.io/en/latest/>`_ and
|
|
reuse material from the documentation sections of individual type checkers
|
|
and the CPython documentation.
|
|
|
|
Amendments
|
|
----------
|
|
|
|
This PEP serves as a charter for the Typing Council. Changes to its operation
|
|
can be made either through a new PEP or through a change to this PEP. In either
|
|
case, the change would be decided upon by the Steering Council after discussion
|
|
in the community.
|
|
|
|
Rejected ideas
|
|
==============
|
|
|
|
Writing the specification from scratch
|
|
--------------------------------------
|
|
|
|
This PEP proposes creating the typing specification by starting from the
|
|
existing PEPs, then clarifying and improving the specification as necessary.
|
|
Some members of the community prefer to start from scratch, writing a new,
|
|
more formal specification covering the entire type system. This could
|
|
provide a more solid basis for the specification.
|
|
|
|
However, this would be a much larger undertaking. The existing formalization
|
|
effort by Kevin Millikin is a good start, but so far covers only a subset of
|
|
PEP 484. Covering the rest of the type system would likely require several
|
|
times more effort when we consider that major type system features such
|
|
as :class:`typing.Protocol`, :class:`typing.Literal`, and :class:`typing.TypedDict`
|
|
were introduced only after PEP 484. It is not clear that there is even energy
|
|
in the community for such a huge undertaking. Even if someone steps up to
|
|
do all the work of putting together a specification, lots of effort would be
|
|
required from community members and type checker maintainers to consider
|
|
whether the specification accurately reflects current behavior, and if not,
|
|
whether the specification or the type checkers should change.
|
|
|
|
Starting with the existing PEPs creates a lower-quality specification,
|
|
but it means that the Typing Council can immediately start making a difference
|
|
anywhere in the type system by improving and clarifying the specification.
|
|
A formalization effort can still proceed by gradually replacing sections of the
|
|
specification.
|
|
|
|
Alternate governance mechanisms
|
|
-------------------------------
|
|
|
|
An earlier draft of this PEP suggested that the Steering Council appoint
|
|
members of the Typing Council each year. The current Steering Council suggested
|
|
that it would be better to have the Typing Council self-organise and avoid
|
|
the need for the Steering Council to continuously supervise the Typing Council.
|
|
|
|
Alternate governance mechanisms are possible, including more democratic ones,
|
|
but these typically raise several thorny questions, require much heavier
|
|
amounts of process and are potentially more divisive. For example, see the PEP
|
|
8000 series, or recent discussions about alternative governance in other Python
|
|
subcommunities. Ultimately, the Typing Council exists under the authority of the
|
|
Steering Council, and so can rely on it to bootstrap governance and serve as an
|
|
accountability mechanism.
|
|
|
|
Do nothing
|
|
----------
|
|
|
|
We are hopeful substantial progress will be made on projects that improve the
|
|
type system regardless of whether this PEP is accepted. We anticipate projects
|
|
like specification or the potential for PEP delegation would benefit more from a
|
|
Typing Council, and projects like end user documentation would benefit less.
|
|
Certainly the bottleneck is likely to be contributor effort, not governance.
|
|
|
|
However, currently the tools available to the community to resolve potential
|
|
contention are either establishment of approximate consensus or the exercise of
|
|
power by individual projects or contributors. While very valuable, the former is
|
|
a slow process that can often end in inaction. The latter can result in a less
|
|
consistent ecosystem. Finally, easily legible governance structures make the
|
|
community more accessible and equitable.
|
|
|
|
Copyright
|
|
=========
|
|
|
|
This document is placed in the public domain or under the
|
|
CC0-1.0-Universal license, whichever is more permissive.
|