PDEP-1:目的和指导方针
- 创建日期:2022 年 8 月 3 日
- 状态:已接受
- 讨论:#47444, #51417
- 作者:Marc Garcia, Noa Tamir
- 修订:3
PDEP 定义、目的和范围
PDEP(pandas 增强提案)是对 pandas 中某个重大变更的提案,类似于 Python 的 PEP 或 NumPy 的 NEP。
错误修复和概念上的次要变更(例如,为函数添加一个参数)不在 PDEP 的范围之内。PDEP 应用于那些不立即且不显而易见的变更,当 pandas 社区中的每个人都需要了解即将可能发生的变更时。这类变更在实施前需要详细的文档,并且通常会导致社区内部进行大量讨论。
PDEP 适用于面向用户的变更、内部变更和重要的讨论。值得使用 PDEP 的议题示例包括实质性的 API 变更、破坏性行为变更、将模块从 pandas 移至单独的代码库,或对 pandas 块管理器进行重构。确定哪个议题的范围足够大到需要完整的 PDEP 流程并不总是那么容易。一些简单的 API 变更在核心团队成员中已有足够的共识,并且对社区的影响最小。另一方面,如果某个议题变得有争议,即引起了重要的讨论,则可以建议发起一个 PDEP 来正式化和记录讨论,从而让更广泛的社区更容易参与。有关背景信息,请参阅可能已成为 PDEP 的议题列表。
PDEP 指导方针
目标受众
PDEP 是一份对任何人公开的文档,但在撰写 PDEP 时需要考虑的主要利益相关者包括
- 核心开发团队,他们将最终决定 PDEP 是否被批准
- pandas 和其他相关项目的贡献者以及经验丰富的用户。强烈鼓励和赞赏他们的反馈,以确保所有观点都得到考虑
- 更广泛的 pandas 社区,特别是用户,他们可能对提案有或没有反馈,但应该了解并能够理解项目的未来方向
PDEP 作者
任何人都可以提出 PDEP,但应请一位核心成员参与,就非核心贡献者提出的提案提供建议。作为社区成员提交 PDEP,请在议题上提出 PDEP 概念,并找一位 pandas 团队成员合作。他们可以就 PDEP 流程向您提供建议,并且在 PDEP 提交到 PDEP 代码库时应被列为 PDEP 的顾问。
工作流程
基本原理
我们的工作流程旨在支持和促进共识寻求过程,并为当前和未来的作者以及有投票权的成员提供清晰度。这不是一项严格的政策,我们不鼓励任何试图利用它以某种方式“强迫”或“暗渡陈仓”地做出决定的解释。我们期望并鼓励所有社区成员保持透明、积极讨论、提供反馈和做出妥协。
PDEP 状态
PDEP 可能的状态包括
- 草案
- 讨论中
- 已接受
- 已实施
- 已拒绝
- 已撤回
接下来描述的是 PDEP 可以遵循的工作流程。
提交 PDEP
提交 PDEP 的方式是创建一个 PR,将一个新文件添加到 web/pandas/pdeps/
中。该文件是一个 Markdown 文件,您可以使用 web/pandas/pdeps/0001-purpose-and-guidelines.md
作为预期格式的参考。
PDEP 的初始状态将是 Status: Draft
。作者准备好进入决策流程时,会将其更改为 Status: Under discussion
。
PDEP 讨论时间表
PDEP 讨论将保持开放,最多持续 60 天。此期间旨在让志愿者参与,他们可能并非总能快速回应,同时也提供充足的时间根据参与者提出的建议和考虑进行更改。类似地,随后的投票期将开放 15 天。
为了促成和鼓励对 PDEP 的讨论,我们遵循一个通知计划。在以下每个步骤中,pandas 团队和 pandas-dev 邮件列表会通过 GitHub 和电子邮件收到通知
- 一旦 PDEP 准备好进行讨论。
- 30 天后,附注最多还有 30 天的讨论时间,如果在接下来的 15 天内没有发生讨论,则将发起投票。
- 45 天后,附注最多还有 15 天的讨论时间,并将在 15 天后发起投票。
- 投票期开始时,即 60 天后或提前投票的情况下,附注还有 15 天的投票时间。
- 投票开始 10 天后,附注还有 5 天的投票时间。
讨论开始 30 天后,如果在 15 天内没有任何新的、未解决的评论,作者可以提前结束讨论期,发送提前提醒,说明距离投票期开始还有 15 天。
投票
投票期开始时,会创建一个 VOTE 议题,该议题链接到 PDEP 讨论的拉取请求。每位有投票权的成员(包括有投票权的作者)可以通过添加以下评论之一来投票
- +1:批准。
- 0:弃权。
- 原因:需要一个单句的原因。
- -1:不批准
- 原因:需要一个单句的原因。
不批准票要求事先参与了 PDEP 讨论议题。
非投票成员在公开 VOTE 议题上发表的评论将被删除。
投票期结束后,任何投票人可以在评论中统计投票结果,格式为:w-x-y-z,其中 w 表示批准票总数,x 表示弃权票总数,y 表示不批准票总数,z 表示未对 VOTE 议题做出回应的有投票权成员人数。投票统计结果将说明是否达到了法定人数。
法定人数和多数票
PDEP 投票要接受提案,需要达到法定人数。所有投票(包括弃权票)都计入法定人数。法定人数计算为以下两个值中较低的一个
- 11 位有投票权成员。
- 有投票权成员的 50%。
在达到法定人数的情况下,还需要非弃权票的 70% 支持,即批准票和不批准票中必须有 70% 是赞成票。
因此,弃权票计入法定人数,但不计入多数票。有投票权成员可以选择弃权,如果他们参与了讨论,对提案有一些异议,但又不希望阻止提案推进,也不表示完全支持。
如果在投票期结束时未达到法定人数,则 PDEP 不被接受。其状态将变为“已拒绝”。
已接受的 PDEP
一旦 PDEP 被接受,就可以对其进行任何贡献以实现 PDEP,完成时间没有具体限制。pandas 的开发难以理解和预测,因为 pandas 的贡献者是志愿者和来自不同来源、具有不同优先级的付费开发人员的混合体。对于有兴趣看到 PDEP 被实施,或者总体上看到 pandas 路线图进展的公司、机构或个人,请查阅贡献页面,了解如何提供帮助。
已实施的 PDEP
一旦 PDEP 被实施并在 pandas 的主分支中可用,其状态将更改为 Status: Implemented
,以便明确 PDEP 不是路线图和未来计划的一部分,而是已经发生的变更。实施 PDEP 的第一个 pandas 版本也将包含在 PDEP 头部,例如 Implemented: v2.0.0
。
已拒绝的 PDEP
当最终决定认为实施某项 PDEP 不符合项目的最佳利益时,该 PDEP 可能会被拒绝。已拒绝的 PDEP 与已接受的 PDEP 一样有用,因为其中包含值得进行的讨论以及关于 pandas 变更的决策。它们将被合并并标记为 Status: Rejected
,以便明确讨论的内容和讨论的结果。PDEP 被拒绝的原因有很多,例如虽然是好主意但不向后兼容,且破坏性变更被认为不值得实施。
PDEP 作者也可以在做出最终决定前决定撤回 PDEP (Status: Withdrawn
),这可能是当 PDEP 作者自己认为该 PDEP 实际上是一个坏主意,或者已经接受它并未得到广泛支持,或者存在更好的竞争提案时。
作者可以选择重新提交被拒绝或已撤回的 PDEP。我们期望作者在这种情况下运用他们的判断,判断是否认为更多的讨论或修改后的提案有可能导致不同的结果。然后会创建一个新的 PDEP,其中包含指向先前被拒绝的 PDEP 的链接。
无效的 PDEP
对于提交的、不包含适当文档、超出范围或出于任何其他原因对社区无用的 PDEP,将在与作者讨论后关闭 PR,而不是将其合并为已拒绝。这是为了避免给已拒绝的 PDEP 列表增加噪音,该列表应包含与已接受的 PDEP 同样良好的文档,只是最终决定是不实施变更。
PDEP 的演变
大多数 PDEP 在被接受后预计不会再更改。一旦就变更达成一致并实施完成,PDEP 将仅用于理解开发为何发生以及讨论的详细信息。
但在某些情况下,PDEP 可以更新。例如,定义程序或政策的 PDEP,就像这个 PDEP-1。或者在尝试实施后,获得新的知识,使得原 PDEP 过时,需要进行变更。当需要对原 PDEP 进行具体变更时,会进行编辑,其 Revision: X
标签会增加一,并在 PDEP-N history
部分添加说明。这将让读者了解 PDEP 已发生变化,避免混淆。
可能已成为 PDEP 的议题列表作为背景
潜在 PDEP 的明确示例
- 向许多现有方法添加新参数,或在多处弃用某个参数。例如
numeric_only
弃用 (GH-28900) 影响了许多方法,本可以是一个 PDEP。- 添加新数据类型会影响需要处理该数据类型的许多地方。这种广泛的影响需要一个 PDEP。例如
Categorical
(GH-7217, GH-8074),StringDtype
(GH-8640),ArrowDtype
- 现有行为的重大(破坏性)变更。例如
- 复制/视图变更 (GH-36195)
- 支持对项目产生广泛影响的新 Python 特性。例如
- 支持 pandas 内部的类型检查与创建
pandas-stubs
(GH-43197, GH-45253) - 新增必需依赖。
- 从项目中移除模块或将其拆分到单独的代码库
- 将很少使用的 I/O 连接器移至单独的代码库 GH-28409
- 对贡献者流程的重大变更不会对用户产生影响,但它们受益于贡献者之间的结构化讨论。例如
- 将构建系统更改为 meson (GH-49115)
边缘示例
对核心功能(如 DataFrame
和 Series
)的微小更改应始终视为 PDEP 候选,因为它很可能对用户产生重大影响。但对其他功能的相同类型更改则不是好的 PDEP 候选。也就是说,任何讨论,无论变更多小,一旦引起争议,就是一个 PDEP 候选。考虑是否需要更多关注和/或正式的决策过程会有所帮助。以下是一些示例,希望能帮助澄清此处含义
- API 破坏性变更或相关讨论,可能是一个 PDEP。例如
value_counts
结果重命名 (GH-49497)。最初,范围并不足以证明需要 PDEP,但后来出现了关于是否应作为破坏性变更还是通过弃用执行的讨论,这可能会受益于 PDEP 过程。- 为现有方法添加新方法或参数通常不需要非核心功能的 PDEP。例如
dropna(percentage)
(GH-35299) 和Timestamp.normalize()
(GH-8794) 都不需要 PDEP。- 另一方面,
DataFrame.assign()
可能需要。虽然它是一个没有向后兼容性问题的方法,但它也是一个核心功能,讨论应该具有高度可见性。 - 弃用或删除单个方法在大多数情况下不需要 PDEP。
- 尽管如此,
DataFrame.append
(GH-35407) 是核心功能弃用的一个例子,这将是 PDEP 的一个好候选。 - 更改核心 pandas 方法中参数的默认值是另一个边缘情况。例如
DataFrame.groupby
和Series.groupby
中dropna
的此类更改可能是一个 PDEP。- 新的顶级模块和/或公开内部类。例如
- 添加
pandas.api.typing
(GH-48577) 相对较小,不一定需要 PDEP。