Following system colour scheme - Python 增强提案 Selected dark colour scheme - Python 增强提案 Selected light colour scheme - Python 增强提案

Python 增强提案

PEP 729 – 类型治理流程

作者:
Jelle Zijlstra <jelle.zijlstra at gmail.com>, Shantanu Jain <hauntsaninja at gmail.com>
讨论地址:
Discourse 线程
状态:
活跃
类型:
流程
主题:
治理, 类型
创建日期:
2023-09-19
发布历史:
2023-10-04, 2023-09-20
决议:
Discourse 消息

目录

摘要

本 PEP 提出了一种新的 Python 类型系统治理方式:由一个委员会负责维护和发展 Python 类型系统。该委员会将维护规范和一致性测试套件,并最初由 Python 指导委员会任命。

动机

Python 类型系统是由 PEP 484 创建的,距今已有近十年。类型系统现已广泛使用,类型提示已成为编写良好、可维护 Python 代码的重要工具。类型系统已经过多次修改,以涵盖更多用例并提高可用性。已经创建了几个类型检查器,每个检查器都有其自身的优势。类型注释语法推动了 Python 生态系统中几个重大创新,例如流行的 dataclasses 模块、由 Pydantic 等包提供的运行时类型检查和验证,以及由 mypyc 等工具提供的静态编译。

然而,随着类型系统的不断发展,当前管理类型系统的方式出现了一些相互关联的问题。

PEPs 是唯一的规范

Python 类型系统最初是由 PEP (PEP 484) 创建的,对类型系统的更改仍然通过 PEP 进行。Python 类型系统的规范(如果存在)包含一系列 PEP。但标准跟踪 PEP 不应是活文档或规范;它们是变更提案。

以下示例说明了这个问题。大约在 PEP 484 引入 typing 模块的同时,PEP 3156 引入了 asyncio 模块,这是另一个重大新功能,对 Python 3 的成功起着至关重要的作用。这两个模块自创建以来都得到了很大的发展,并激发了对核心语言的修改。

然而,asynciotyping 在一个重要方面有所不同:使用 asyncio 的用户只与标准库本身进行交互,而使用 typing 的用户还必须考虑外部工具,即类型检查器。Python 语言参考涵盖了 typing 模块中的符号,但没有(也不应该)详细说明类型检查器应该如何解释完整的类型系统。这些材料目前仅存在于 PEP 中。

打包生态系统也存在此问题,它试图通过维护一组独立的 PyPA 规范 来解决此问题。

难以改进规范

由于 PEP 是我们唯一的规范,因此任何被视为对规范的更改都理论上需要一个新的 PEP。但这对于小更改来说通常是一个过于繁重的流程。有时会直接对旧的 PEP 进行更改,但这违背了已接受和已实施的 PEP 应成为不再更改的历史文档的理念。

一些具体的例子包括

  • PEP 484 明确指出,typing.NoReturn 不能用于参数注释。然而,类型检查器长期以来一直接受这种用法。
  • 一项 2023 年讨论 指出,PEP 561 对部分存根的描述并不清晰,主要类型检查器并没有完全按照规范进行实施。
  • 广泛使用的第三方 typing_extensions 包提供了新类型系统功能的移植。预计类型检查器会将此模块中的符号与 typing 中的符号相同对待,但这在任何 PEP 中都没有明确规定。

类型系统未完全定义

尽管 PEP 提供了规范,但它们通常不够精确(有时是故意这样做的)。随着类型系统的组合复杂度不断提高,这一点尤其明显。

最终,由各个类型检查器来决定如何处理未完全定义的区域。在类型检查器非正式协调的情况下,这会导致事实上的标准,这些标准在任何地方都没有明确记录,从而使类型系统对新手来说难以理解。例如

指导委员会不适合解决上述问题

指导委员会负责整个语言,并不适合做出纯粹关于类型系统的决策——仅因他们没有时间处理类型系统的深奥内容以及其他责任。这与指导委员会有时使用 PEP 委托的原因类似。

认可

本 PEP 已获得所有主要类型检查器维护人员的认可,包括 Rebecca Chen (pytype)Eric Traut (Pyright),以及 mypy 和 Pyre 维护人员私下认可。

规范

我们建议创建一个新的小组,称为类型委员会。该小组将负责开发和维护 Python 类型系统,并解决上述问题。

“操作和流程”部分描述了该小组的运作方式和治理方式。

更令人兴奋的“项目”部分描述了类型委员会可以领导的解决上述问题的方案。

授权

类型委员会的授权是确保 Python 类型系统

  • 有用:类型系统应服务于常见用例。正如 PEP 484 所述,主要用例是静态分析,但还包括其他用例,例如运行时类型检查、静态编译、IDE 支持和文档。类型委员会在做出决策时应考虑所有这些用例,并对支持新出现的用例持开放态度。
  • 可用:类型系统应易于 Python 开发人员使用。编写经过类型检查器验证的良好类型的 Python 代码应该是简单易行的。类型系统应有完善的文档。
  • 稳定:随着类型系统的不断成熟,用户应能够依赖其类型代码继续工作,并能够信任其对类型系统的理解。更改应谨慎进行,并以尽量减少中断的方式进行。但是,类型系统应能够发展,对类型检查器行为使用与 Python 本身相同的兼容性准则毫无意义。当然,typing 模块中对象的存在和运行时行为遵循 PEP 387 中的标准兼容性策略。

操作和流程

该委员会将由三到五名成员组成,由社区中的知名人士组成,例如 Python 核心开发人员和主要类型检查器的维护人员。成员应包括与类型检查相关项目的成员,这些项目可能包括类型检查器、CPython、typeshed 或其他项目。

委员会的初始成员为

  • Eric Traut (Pyright;PEP 647PEP 681PEP 695 的作者)
  • Guido van Rossum (核心开发人员;PEP 484PEP 526 的作者)
  • Jelle Zijlstra(核心开发人员;typeshed;pyanalyze;PEP 688PEP 702 作者)
  • Rebecca Chen(pytype)
  • Shantanu Jain(核心开发人员;typeshed;mypy)

委员会的现任成员记录在 python/typing-council 仓库中。

委员会成员没有任期限制。委员会成员可以随时辞职。预期每位成员在辞职之前最多连续任职五年。

如果有空缺并且剩余三名或更多成员,由委员会决定是否任命新成员。为了确定替代者,将从类型社区收集提名。允许自荐。现有的类型委员会将从被提名人中决定替代成员。预期这将由法令完成,但类型委员会可以通过他们认为合适的方式选择替代者,包括投票。

类型委员会对指导委员会负责。在任何时候,出于任何原因,指导委员会可以(公开或私下)对类型委员会的组成做出具体更改或请求非具体更改。

我们认识到,这是一种不太民主的结构,对类型委员会寄予了很大希望。然而,Python 社区在非民主结构方面有着悠久的成功历史!我们相信自我治理、成员轮换和对指导委员会的负责将足以确保类型委员会满足社区的需求。

委员会主要通过 GitHub PR 审查来运作。定期会议可能不需要,但委员会可以建立视频通话、私人聊天或他们内部决定的任何其他机制。

委员会应努力做到透明,在 discuss.python.org 上公开发布所有决定,并在可能的情况下提供理由。在做出决定之前,委员会应让所有感兴趣的社区成员有机会发表意见。从讨论开始到委员会做出决定,至少应有一周时间。

委员会成员有资格赞助 PEP。如果此 PEP 被接受,应修改 PEP 1 以记录此事实。

与指导委员会的关系

就像今天一样,Python 指导委员会将继续负责 Python 语言的总体方向,并将继续决定与类型相关的 PEP。类型委员会将向指导委员会提供关于与类型相关的 PEP 的书面意见和建议。

但是,类型委员会可以直接对类型系统进行较小的更改。指导委员会也可以选择将某些 PEP 的决定委托给类型委员会(与任何其他 PEP 委托完全相同)。

一些例子说明了在过去和最近的问题下如何处理

  • 类似于 PEP 695(类型参数语法)的 PEP,它会更改语言语法,需要由指导委员会决定;类型委员会仅提供意见或认可。类似地,类似于 PEP 702(弃用)的 PEP 将由指导委员会决定,因为它涉及纯类型以外的运行时行为。需要由 SC 决定的其他示例包括 PEP 718(可下标函数)和 PEP 727(文档元数据)。
  • 类似于 PEP 698 (@override) 的 PEP,它只影响类型检查器的用户,并且不会改变整个语言,默认情况下也将由指导委员会决定。但是,此类 PEP 可以委托给类型委员会做出决定(就像任何其他 PEP 委托一样)。可能被委托的其他 PEP 示例包括 PEP 647(类型守卫)、PEP 655(单个必需的 TypedDict 项目)、PEP 673 (Self) 和 PEP 675 (Literal)。
  • 添加较小的功能,例如 typing.Never 作为 typing.NoReturn 的别名,将通过对规范和一致性测试套件进行 PR 来完成。然后,类型委员会将决定是否合并 PR。如果他们认为有必要,他们可能会要求对该功能进行说明并在 PEP 中进行讨论。
  • 如果对规范的某些部分的解释存在混淆,就像最近在 PEP 561 中的局部存根 中发生的那样,有人会对类型规范进行 PR 以澄清规范,然后类型委员会将决定规范更改。

运行时 typing 模块将继续由 CPython 核心开发人员团队维护。但是,对运行时模块的任何更改,只要这些更改会影响类型检查器的行为,都应与对规范的更改(见下文)一起进行,并应得到类型委员会的批准。例如,在 Python 3.11 中,核心开发人员添加了新函数 typing.assert_type()。如果类型委员会已经到位,则此更改将需要对规范进行相应的更改并获得类型委员会的批准。另一方面,Python 3.11 还添加了 typing.get_overloads() 自省助手。由于此函数不会影响类型检查器的行为,因此不需要类型委员会的批准。但是,由于对运行时类型检查器的支持属于委员会的职权范围,因此他们应监控此类更改并在适当的时候提供反馈。

与类型检查器的关系

类型委员会对类型检查器没有直接权力;它不能强迫它们实施特定功能或进行行为更改。类型检查器被激励遵循委员会设定的规范,因为这使他们能够利用共享资源,例如公开遵循规范的类型信息的库、typeshed 中的存根文件、typing 标准库模块以及涵盖标准类型系统的用户文档。类型检查器可以自由扩展类型系统或偏离规范,但他们应该清楚地记录这些差异。

类型检查器需要实施类型委员会做出的任何决定这一事实,对委员会起到了有用的制约作用,确保委员会的决定是保守的和经过深思熟虑的。单个类型检查器仍然可以自由地按照他们认为合适的方式进行创新,成功的创新可以合并到标准类型系统中。

项目

以下是一些类型委员会负责的努力。

一致性测试套件

一致性测试套件将为类型检查器应如何检查 Python 代码提供机器可检查的文档,并附有主要类型检查器实现对测试套件的结果。Shantanu 创建 了一个关于它可能是什么样子的粗略草图。

这将包含来自先前 PEP 规定的行为的规范性测试以及描述性测试,使我们能够记录现有实现的行为,这些行为是在任何标准中都没有规定的领域。这些描述将有助于以下努力并确定标准化重点领域。

类型系统的规范

规范将最初通过将现有 PEP 的规范部分拼凑在一起创建,然后逐渐改进,以澄清困惑点并涵盖更多领域。Jelle 创建 了这样一个拼凑规范的草案。

规范有一些受众

  • 对于类型检查器,它提供了关于理想化类型检查器应如何运行的描述。单个类型检查器具有不同的目标和技术约束,如果他们没有资源完全实施规范,或者他们认为不同的行为更能满足他们的用户需求,他们可以自由地偏离规范。但是,他们应该记录这些与规范的偏差。
  • 对于 typeshed 之类的项目或希望与多个类型检查器兼容的库,它提供了一套规则,他们可以遵循这些规则来使他们的代码被类型检查器理解。
  • 对于希望提出对类型系统更改的人来说,它为任何新的提案提供了基础。

值得注意的是,规范并非针对使用类型的应用程序开发人员。这些用户通常不需要担心跨类型检查器的兼容性。他们更好地服务于更非正式的用户面向参考,这将在下一节讨论。

社区内部对规范应该多么正式存在不同的意见。虽然本文档建议采用一种从现有规范中构建的增量方法,但它并不旨在规定最终状态。类型委员会将提供一种机制,使规范能够随着社区期望的正式程度而发展,例如,通过将 Kevin Millikin 的 “Python 静态类型”文档 的部分内容作为实现规范更好的形式化的一种方式。

规范的拟议更改,包括 PEP,通常应附带以下内容

  • 来自类型检查器维护者的支持,以确认更改可以在其类型检查器中实现和维护。
  • 对于对现有功能的更改,对现有类型检查器行为的调查。如果现有类型检查器的行为大致相似,这表明他们的共享行为应该成为规范的一部分。
  • 对一致性测试套件的更改,以证明指定的行为。

面向用户的类型系统参考

文档对于 Python 类型系统的成功至关重要,因此类型委员会应确保类型系统具有良好的文档。

如前所述,PEP 是面向多个受众的、旨在实现点对点更改的提议,难以澄清。这使得它们不适合作为用户文档。上一节中讨论的规范将是一个活文档,但它可能过于技术性而无法作为正常使用的文档。

因此,为类型系统提供单独的用户面向参考将很有用。这样的努力可以扩展 typing.readthedocs.io 上的文档,并重复使用来自单个类型检查器文档部分和 CPython 文档的材料。

修订

本 PEP 作为类型委员会的章程。对它操作的更改可以通过新的 PEP 或对本 PEP 的更改来进行。无论哪种情况,更改都将在社区讨论后由指导委员会决定。

被拒绝的想法

从头开始编写规范

本 PEP 建议从现有 PEP 开始创建类型规范,然后根据需要澄清和改进规范。社区中的一些成员更愿意从头开始,编写一个新的、更正式的规范,涵盖整个类型系统。这可以为规范提供更坚实的基础。

然而,这将是一项更大的任务。Kevin Millikin 的现有形式化工作是一个良好的开端,但到目前为止只涵盖了 PEP 484 的一部分。考虑到像 typing.Protocoltyping.Literaltyping.TypedDict 这样的主要类型系统功能是在 PEP 484 之后才引入的,涵盖类型系统的其余部分可能需要多出几倍的努力。目前还不清楚社区是否有足够的力量来完成这样一项巨大的任务。即使有人站出来完成所有编写规范的工作,也需要社区成员和类型检查器维护人员付出大量努力来考虑规范是否准确地反映了当前的行为,如果没有,那么是规范还是类型检查器应该改变。

从现有的 PEP 开始创建了一个质量较低的规范,但它意味着类型委员会可以立即通过改进和澄清规范来对类型系统中的任何地方产生影响。形式化工作仍然可以通过逐渐替换规范的部分来进行。

替代治理机制

本 PEP 的早期草案建议指导委员会每年任命类型委员会成员。目前的指导委员会建议,最好让类型委员会自行组织,避免指导委员会需要不断监督类型委员会。

其他治理机制是可能的,包括更民主的机制,但这些机制通常会引发一些棘手的问题,需要更多的流程,并且可能更具争议性。例如,请参阅 PEP 8000 系列,或最近关于 Python 其他子社区中替代治理的讨论。最终,类型委员会受指导委员会的授权,因此可以依靠它来启动治理并作为问责机制。

不做任何事

我们希望无论本 PEP 是否被接受,在改进类型系统的项目上都会取得实质性进展。我们预计像规范或 PEP 委托的可能性这样的项目将从类型委员会中获益更多,而像最终用户文档这样的项目将获益更少。当然,瓶颈可能是贡献者的努力,而不是治理。

然而,目前社区可用的解决潜在争端的工具要么是建立近似共识,要么是个人项目或贡献者行使权力。虽然非常宝贵,但前者是一个缓慢的过程,最终可能导致无所作为。后者会导致生态系统缺乏一致性。最后,清晰易懂的治理结构使社区更容易获得和更加公平。

联系方式

要向类型委员会请求决定,社区成员可以在 python/typing-council 存储库中打开一个问题。


来源:https://github.com/python/peps/blob/main/peps/pep-0729.rst

上次修改:2024-05-28 13:07:09 GMT