PEP 729 – 类型化治理过程
- 作者:
- Jelle Zijlstra <jelle.zijlstra at gmail.com>,Shantanu Jain <hauntsaninja at gmail.com>
- 讨论至:
- Discourse 帖子
- 状态:
- 活跃
- 类型:
- 流程
- 主题:
- 治理, 类型化
- 创建日期:
- 2023年9月19日
- 发布历史:
- 2023年10月4日, 2023年9月20日
- 决议:
- 2023年11月20日
摘要
本 PEP 提出了一种管理 Python 类型系统的新方法:一个负责维护和开发 Python 类型系统的委员会。该委员会将维护一个规范和一致性测试套件,并最初由 Python 指导委员会任命。
动机
Python 类型系统由PEP 484创建,至今已有近十年。类型系统现已广泛使用,类型化已成为编写良好、可维护 Python 代码的重要工具。类型系统已进行了多项更改,以覆盖更多用例并提高可用性。已创建了多个类型检查器,每个都有其独特的优势。类型注解语法推动了 Python 生态系统中的多项重大创新,例如流行的dataclasses模块、由 Pydantic 等包实现的运行时类型检查和验证,以及由 mypyc 等工具实现的静态编译。
然而,随着类型系统的发展,当前管理类型系统的方式出现了几个相互关联的问题。
PEP 是唯一的规范
Python 类型系统最初由一个 PEP (PEP 484) 创建,对类型系统的更改仍通过 PEP 进行。Python 类型系统的规范(如果存在的话)由这一系列 PEP 组成。但标准轨道 PEP 并非旨在作为活文档或规范;它们是变更提案。
一个例子可能说明这里的问题。在typing模块由PEP 484引入的同时,PEP 3156引入了asyncio模块,这是另一个对 Python 3 的成功至关重要的主要新功能。这两个模块自最初创建以来都发展迅速,并激发了对核心语言的更改。
然而,asyncio和typing在一个基本方面有所不同:使用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 维护者的私下认可。
规范
我们提议成立一个新的小组,即类型化委员会 (Typing Council)。该小组将负责开发和维护 Python 类型系统,并解决上述问题。
“运营和流程”部分描述了该小组将如何运作和治理。
更令人兴奋的“项目”部分描述了类型化委员会可以指导解决上述问题的方案。
授权
类型化委员会的职责是确保 Python 类型系统
- 有用:类型系统应服务于常见用例。如PEP 484所指出的,主要用例是静态分析,但还有其他用例,例如运行时类型检查、静态编译、IDE 支持和文档。类型化委员会在做出决策时应考虑所有这些用例,并乐于在出现时支持其他用例。
- 可用:类型系统应易于 Python 开发者使用。编写良好类型化并被类型检查器接受的 Python 代码应符合人体工程学。应有关于类型系统的良好文档。
- 稳定:随着类型系统日趋成熟,用户应能够依靠其类型化代码继续工作,并信任其对类型系统的心智模型。应谨慎进行更改,并以最大限度减少中断的方式进行。然而,类型系统应能够演进,并且对类型检查器行为使用与 Python 本身相同的兼容性准则没有意义。当然,
typing模块中对象的存在和运行时行为确实遵循PEP 387中的 Python 标准兼容性策略。
运营和流程
该委员会将由三到五名成员组成,其中包括著名的社区成员,例如 Python 核心开发者和主要类型检查器的维护者。成员应包括与各种类型检查相关项目(可能包括类型检查器、CPython、typeshed 或其他项目)有联系的人员。
委员会的初始成员是
- Eric Traut (Pyright;PEP 647、PEP 681 和 PEP 695 的作者)
- Guido van Rossum (核心开发者;PEP 484 和 PEP 526 的作者)
- Jelle Zijlstra (核心开发者;typeshed;pyanalyze;PEP 688 和 PEP 702 的作者)
- Rebecca Chen (pytype)
- Shantanu Jain (核心开发者;typeshed;mypy)
委员会的当前成员记录在 python/typing-council 仓库中。
委员会成员没有任期限制。委员会成员可随时辞职。预期每位成员连续任职不超过五年后辞职。
如果出现空缺且剩余成员有三名或更多,则由委员会决定是否任命新成员。为确定替补成员,将从类型化社区收集提名。允许自荐。现有类型化委员会将从被提名者中决定替补成员。预期这将通过命令进行,但类型化委员会可以根据他们认为合适的方式选择替补成员,包括投票。
类型化委员会对指导委员会负责。指导委员会可随时以任何理由(公开或私下)对类型化委员会的组成进行具体更改或请求非具体更改。
我们承认这是一种不太民主的结构,并且对类型化委员会寄予了很大的信任。然而,Python 社区在不太民主的结构方面有着悠久的成功历史!我们相信自治、成员轮换以及对指导委员会的问责制将足以确保类型化委员会满足社区的需求。
委员会将主要通过审查 GitHub PRs 运作。定期会议可能没有必要,但委员会可以建立视频通话、私人聊天或他们内部决定的任何其他机制。
委员会应力求透明,将所有决定公开发布在 discuss.python.org 上,并尽可能附上理由。在做出决定之前,委员会应给所有感兴趣的社区成员发表意见的机会。从讨论开始到委员会做出决定之间应至少有一周的时间。
委员会成员将有资格赞助 PEP。如果本 PEP 被接受,则应修改 PEP 1 以记录此事实。
与指导委员会的关系
与今天一样,Python 指导委员会将继续负责 Python 语言的整体方向,并将继续就与类型化相关的 PEP 做出决定。类型化委员会将就与类型化相关的 PEP 向指导委员会提供书面意见和建议。
然而,对类型系统的较小更改可以直接由类型化委员会做出。指导委员会还可以选择将某些 PEP 的决定委托给类型化委员会(与任何其他 PEP 委托完全相同)。
以下是一些在此模型下如何处理过去和近期问题的示例
- 像 PEP 695(类型参数语法)这样更改语言语法的 PEP,需要由指导委员会决定;类型化委员会只会提供意见或认可。类似地,像 PEP 702(弃用)这样的 PEP 将由指导委员会决定,因为它涉及纯类型化之外的运行时行为。其他需要由指导委员会决定的例子包括 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.python.org 上的文档,并重用来自单个类型检查器和 CPython 文档的文档部分中的材料。
修订
本 PEP 充当类型化委员会的章程。其运作方式的更改可以通过新的 PEP 或对本 PEP 的更改进行。无论哪种情况,更改都将在社区讨论后由指导委员会决定。
被拒绝的想法
从头编写规范
本 PEP 建议从现有 PEP 开始创建类型规范,然后根据需要澄清和改进规范。社区中一些成员倾向于从头开始,编写一个涵盖整个类型系统的新的、更正式的规范。这可以为规范提供更坚实的基础。
然而,这将是一项更为庞大的任务。Kevin Millikin 现有的形式化工作是一个良好的开端,但到目前为止只涵盖了 PEP 484 的一个子集。考虑到 typing.Protocol、typing.Literal 和 typing.TypedDict 等主要的类型系统功能仅在 PEP 484 之后才引入,涵盖类型系统的其余部分可能需要多倍的努力。目前尚不清楚社区是否有精力承担如此巨大的任务。即使有人站出来完成所有构建规范的工作,社区成员和类型检查器维护者也需要付出大量努力来考虑规范是否准确反映了当前行为,如果不是,则需要决定是更改规范还是更改类型检查器。
从现有 PEP 开始会创建一个质量较低的规范,但这意味着类型化委员会可以立即通过改进和澄清规范在类型系统的任何地方发挥作用。形式化工作仍然可以通过逐步替换规范的各个部分来推进。
替代治理机制
本 PEP 的早期草案建议指导委员会每年任命类型化委员会成员。当前的指导委员会建议最好由类型化委员会自行组织,避免指导委员会持续监督类型化委员会的需要。
其他治理机制是可能的,包括更民主的机制,但这些通常会引发一些棘手的问题,需要更繁重的流程,并可能更具分裂性。例如,参见 PEP 8000 系列,或最近关于其他 Python 子社区替代治理的讨论。最终,类型化委员会在指导委员会的权威下存在,因此可以依靠指导委员会来启动治理并作为问责机制。
不作为
我们希望无论本 PEP 是否被接受,类型系统改进项目都将取得实质性进展。我们预计像规范或 PEP 授权潜力这样的项目将从类型化委员会中受益更多,而像最终用户文档这样的项目受益较少。当然,瓶颈很可能是贡献者的努力,而不是治理。
然而,目前社区可用于解决潜在争议的工具要么是建立近似共识,要么是个别项目或贡献者行使权力。虽然非常有价值,但前者是一个缓慢的过程,往往会导致不作为。后者可能导致生态系统缺乏一致性。最后,易于理解的治理结构使社区更具可访问性和公平性。
联系
要向类型化委员会提出决定请求,社区成员可以在 python/typing-council 仓库中提出一个 issue。
版权
本文档置于公共领域或 CC0-1.0-Universal 许可证下,以更宽松者为准。
来源: https://github.com/python/peps/blob/main/peps/pep-0729.rst
最后修改: 2025-03-05 16:28:34 GMT