pandas 维护#

本指南适用于 pandas 的维护者。对于希望了解 pandas 开发过程以及成为维护者所需步骤的贡献者来说,也可能很有趣。

主要贡献指南可在 为 Pandas 做贡献 找到。

角色#

pandas 使用两个级别的权限:**triage**(分类)和 **core**(核心)团队成员。

Triage 成员可以为 issue 和 pull request 添加标签和关闭。

Core 团队成员可以为 issue 和 pull request 添加标签和关闭,并且可以合并 pull request。

GitHub 公布了完整的 list of permissions

任务#

pandas 在很大程度上是一个志愿者项目,因此这些任务不应被读作对 triage 和维护者的“预期”。相反,它们是对成为维护者意味着什么的通用描述。

  • 对新提交的 issue 进行分类(参见 Issue 分类

  • 评审新打开的 pull request

  • 响应现有 issue 和 pull request 的更新

  • 推动停滞的 issue 和 pull request 的讨论和决策

  • 在 API 设计问题上提供经验/智慧,以确保一致性和可维护性

  • 项目组织(主持/参加开发者会议,代表 pandas)

https://matthewrocklin.com/blog/2019/05/18/maintainer 可能是有趣的背景阅读材料。

Issue 分类#

分类是处理社区报告 issue 的重要第一步,即使是部分贡献也是帮助维护 pandas 的绝佳方式。只有在完成以下所有步骤后,才能删除“Needs Triage”标签。

以下是分类新打开 issue 的典型工作流程。

  1. 感谢报告者提交 issue

    Issue 跟踪器是许多人除了使用库本身之外,与 pandas 项目的第一次互动。因此,我们希望它是一个受欢迎、愉快的体验。

  2. 是否提供了必要的信息?

    理想情况下,报告者会填写 issue 模板,但许多人没有。如果缺少关键信息(例如他们使用的 pandas 版本),可以随时要求提供该信息,并将 issue 标记为“Needs info”(需要信息)。报告应遵循 错误报告和功能增强请求 中的指南。如果他们没有遵循模板,您可能需要链接到该指南。

    请确保标题准确反映问题。如果标题不清楚,请自行编辑。

  3. 这是一个重复的问题吗?

    我们有很多未关闭的问题。如果一个新问题明显是重复的,请将新问题标记为“Duplicate”(重复),并关闭该问题,附上指向原始问题的链接。请务必感谢报告者,并鼓励他们在原始问题中发表意见,或许尝试修复它。

    如果新问题提供了相关信息,例如一个更好或略有不同的示例,请将其添加为原始问题的评论,或编辑原始帖子。

  4. 这个问题是最小化且可重现的吗?

    对于 Bug 报告,我们要求报告者提供一个最小化可重现示例。请参阅 https://matthewrocklin.com/blog/work/2018/02/28/minimal-bug-reports 以获得良好解释。如果示例不可重现,或者*明显*不是最小化的,请随时要求报告者提供示例或简化已提供的示例。请承认编写最小化可重现示例是一项艰巨的工作。如果报告者遇到困难,您可以尝试自己编写一个,然后我们会编辑原始帖子以包含它。

    如果无法提供可重现示例,请添加“Needs info”(需要信息)标签。

    如果提供了可重现示例,但您看到了简化的可能性,请用您更简单的可重现示例编辑原始帖子。

    确保问题存在于主分支上,并且已添加“Needs Triage”(需要分类)标签,直到所有步骤都已完成。在您验证问题存在于主分支后,请向该问题添加评论,以便其他人知道已确认。

  5. 这是一个明确定义的功能请求吗?

    通常,pandas 倾向于在提交拉取请求之前,在 issues 中讨论和设计新功能。鼓励提交者包括新功能的建议 API。让他们编写完整的文档字符串是明确具体细节的好方法。

    请在新的功能请求中添加“Needs Discussion”(需要讨论)标签,因为在决定该提议是否在 pandas 的范围内之前,我们需要多位 pandas 维护者的讨论。

  6. 这是一个用法问题吗?

    我们倾向于在 StackOverflow 上使用 pandas 标签提出用法问题。https://stackoverflow.com/questions/tagged/pandas

    如果问题很容易回答,请随意链接到相关文档部分,告知他们将来此类问题应在该平台提出,然后关闭该 issue。

  7. 应该添加哪些标签和里程碑?

    应用相关的标签。这需要一些技巧,并且随着经验的积累会逐渐掌握。查看类似的问题以了解事物的标记方式。

    如果问题定义明确且修复似乎相对简单,请将问题标记为“Good first issue”(新手友好问题)。

    完成上述操作后,请确保删除“needs triage”标签。

调查回归 (Investigating regressions)#

Regressions are bugs that unintentionally break previously working code. The common way to investigate regressions is by using git bisect, which finds the first commit that introduced the bug.

例如:一位用户报告 pd.Series([1, 1]).sum() 在 pandas 版本 1.5.0 中返回 3,而在版本 1.4.0 中返回 2 . 要开始,请在您的 pandas 目录中创建一个名为 t.py 的文件,其中包含

import pandas as pd
assert pd.Series([1, 1]).sum() == 2

然后运行:

git bisect start
git bisect good v1.4.0
git bisect bad v1.5.0
git bisect run bash -c "python setup.py build_ext -j 4; python t.py"

这将找到改变行为的第一个提交。C 扩展必须在每一步重新构建,因此搜索可能需要一段时间。

退出 bisect 并重新构建当前版本:

git bisect reset
python setup.py build_ext -j 4

在对应的 issue 下报告您的发现,并 ping 提交作者以获取他们的意见。

备注

在上面的 bisect run 命令中,当 t.py 退出时返回 0 时,commit 被认为是好的,否则被认为是坏的。当引发异常是期望的行为时,请使用适当的 try/except 语句将代码包装起来。有关更多示例,请参阅 GH 35685

关闭 issues#

请谨慎操作:许多人认为关闭 issue 意味着我们结束了对话。通常最好给报告者一些时间来回应,或者如果确定行为不是 Bug,或者功能不在范围内,则自行关闭 issue。有时报告者只是消失了,在对话平息后我们会关闭 issue。如果您认为某个 issue 应该被关闭但不太确定,请应用“closing candidate”(关闭候选)标签,然后等待其他维护者查看。

Reviewing pull requests#

任何人都可以审查pull request:常规贡献者、分类协调员或核心团队成员。但只有核心团队成员才能在pull request准备好时将其合并。

以下是审查pull request时需要检查的一些事项。

  • 测试应放置在合理的位置:与最相关的测试位于同一文件中。

  • 新的公共API应包含在 doc/source/reference/ 的某个位置。

  • 新/更改的API应在其文档字符串中使用 versionaddedversionchanged 指令。

  • 面向用户的更改应在相应文件中包含一个 whatsnew。

  • 回归测试应引用原始GitHub issue编号,如 # GH-1234

  • Pull request应被标记并分配适当的里程碑(回归修复和小型bug修复是下一个补丁版本,否则是下一个次要版本)。

  • 更改应符合我们的 版本策略

Backporting#

pandas支持发布点版本(例如 1.4.3),其目标是:

  1. 修复在第一个次要版本发布的第一个版本中引入的新功能的bug。

  • 例如:如果 1.4 中添加了一个新功能并存在bug,则可以在 1.4.3 中应用修复。

  1. 修复在之前几个次要版本中曾正常工作但现在出现bug的问题。核心团队成员之间应就backport是否合适达成一致。

  • 例如:如果一个功能在 1.2 中能正常工作,但在 1.3 之后停止工作,则可以在 1.4.3 中应用修复。

由于pandas的次要版本基于GitHub分支(例如,1.4 的发布点基于 1.4.x 分支),因此“backporting”意味着将pull request的修复合并到 main 分支,并合并到与下一个发布点相关的正确次要版本分支。

默认情况下,如果在GitHub界面中将pull request分配给下一个发布点里程碑,则backporting过程应由 @meeseeksdev 机器人自动完成,一旦pull request被合并。它将创建一个新的pull request,将该pr backport到正确的版本分支。有时由于合并冲突,需要手动创建一个pr来解决代码冲突。

如果机器人没有自动启动backporting过程,您也可以在已合并的pull request中输入GitHub评论来触发backport:

@meeseeksdev backport version-branch

这将触发一个工作流,将给定的更改backport到分支(例如 @meeseeksdev backport 1.4.x)。

Cleaning up old issues#

pandas中的每一个开放issue都有成本。开放的issue使得查找重复项更加困难,并且可能难以了解pandas中需要完成的工作。尽管如此,关闭issue本身并非目标。我们的目标是让pandas成为最好的,并通过确保我们开放issue的质量来最好地实现这一目标。

偶尔,bug被修复但issue未在Pull Request中链接。在这种情况下,评论“This has been fixed, but could use a test.”,并将issue标记为“Good First Issue”和“Needs Test”。

如果旧issue不符合我们的issue模板,请编辑原始帖子以包含一个最小示例、实际输出和预期输出。issue报告的一致性很有价值。

如果旧issue缺少可复现的示例,请将其标记为“Needs Info”,并要求提供一个(如果可能,请自己编写一个)。如果一段时间后仍未提供,请根据 关闭 issues 中的策略将其关闭。

Cleaning up old pull requests#

偶尔,贡献者无法完成pull request。如果自上次请求更改的审查以来已经过了一段时间(例如两周),请委婉地询问他们是否仍有兴趣继续处理。如果又过了大约两周,仍无回应,感谢他们的工作,然后执行以下操作之一:

  • 关闭pull request;

  • 将提交推送到贡献者的分支,以完成他们的工作(如果您是 pandas-core 的一员)。这有助于将重要的PR推向终点,或修复小的合并冲突。

如果关闭pull request,请在原始issue上评论“There’s a stalled PR at #1234 that may be helpful.”,并且如果PR已接近被接受,则可能将其标记为“Good first issue”。

成为 Pandas 的维护者#

完整的流程在我们的 governance documents 中概述。总之,我们很乐意向任何在 issue tracker 上表现出兴趣并通过提供帮助来展示自己的人授予 triage 权限。

添加维护者所需的步骤是:

  1. 联系贡献者并询问他们是否有兴趣加入。

  2. 如果接受邀请,请将贡献者添加到相应的 GitHub Team

  • pandas-core 适用于核心团队成员

  • pandas-triage 适用于 Pandas triage 成员

如果添加到 pandas-core,还有两个额外的步骤:

  1. 将贡献者添加到 pandas Google group。

  2. 创建一个 pull request,将贡献者的 GitHub handle 添加到 pandas-dev/pandas/web/pandas/config.yml

当前核心团队成员列表位于 pandas-dev/pandas

合并 pull requests#

只有核心团队成员可以合并 pull requests。我们有一些指导方针。

  1. 通常情况下,您不应该在未经批准的情况下自行合并自己的 pull requests。例外情况包括一些小的更改以修复 CI(例如,固定包版本)。如果更改是您非常有信心的,那么在获得其他核心团队成员的批准后自行合并是可以的。

  2. 您不应该合并有活跃讨论的 pull requests,或者得到核心维护者 -1 投票的 pull requests。Pandas 的运作是基于共识的。

  3. 对于较大的更改,最好能得到至少两位核心团队成员的 +1。

除了 关闭 issues 中列出的项目外,您还应验证 pull request 是否分配了正确的里程碑。

合并到 patch-release 里程碑的 Pull requests 通常会由我们的机器人回溯移植。验证机器人是否注意到了合并(它通常会在一分钟内留下评论)。如果需要手动回溯移植,请进行操作,并在完成后删除“Needs backport”标签。如果您忘记在标记之前分配里程碑,您可以通过以下方式请求机器人回溯移植:

@Meeseeksdev backport <branch>

基准测试机器#

该团队目前拥有专用硬件,用于托管 Pandas 的 ASV 性能基准测试网站。结果发布在 https://asv-runner.github.io/asv-collection/pandas/

配置#

可以使用 tomaugspurger/asv-runner 中的 Ansible playbook 来配置此机器。

发布#

结果发布到另一个 GitHub 仓库,tomaugspurger/asv-collection。最后,我们的文档服务器上有一个 cron 作业,用于从 tomaugspurger/asv-collection 拉取,并从 /speed 提供它们。请向 Tom 或 Joris 询问访问 Web 服务器的权限。

调试#

基准测试由 Airflow 调度。它有一个用于查看和调试结果的仪表板。您需要设置 SSH 隧道才能查看它们。

ssh -L 8080:localhost:8080 pandas@panda.likescandy.com

发布流程#

发布流程会将 Pandas 的一个快照(一个 git commit)以特定版本号提供给用户。发布后,新版本的 Pandas 将在以下位置可用:

发布新版本 Pandas 的过程在下一节中有详细说明。

说明中包含 <version>,需要替换为要发布的版本(例如 1.5.2)。还有要发布的 branch <branch>,这取决于正在发布的版本是新版本的发布候选版本,还是任何其他版本。发布候选版本从 main 发布,而其他版本则从它们的特定分支(例如 1.5.x)发布。

先决条件#

为了能够发布新版本的 Pandas,需要具备以下权限:

  • pandaspandas-feedstock 仓库的合并权限。对于后者,请打开一个 PR 将您的 GitHub 用户名添加到 conda-forge recipe 中。

  • 向 pandas 存储库的 main 分支推送的权限,用于推送新标签。

  • Write permissions to PyPI

  • 访问我们的网站/文档服务器。与基础设施委员会分享您的公钥,以便将其添加到主服务器用户的 authorized_keys 文件中。

  • 访问社交媒体账号,用于发布公告。

预发布#

  1. 与核心团队就以下主题达成一致:

    • 发布日期(主要/次要版本通常每 6 个月发布一次,补丁版本每月发布一次,直到 x.x.5,就在下一个主要/次要版本发布之前)

    • 障碍(必须包含在发布中的问题和 PR)

    • 发布版本之后的下一个版本

  2. 更新并清理要发布的版本的发布说明,包括:

    • 设定发布的最终日期

    • 移除任何未使用的项目符号点

    • 确保没有格式问题、拼写错误等。

  3. 确保要发布的合并分支的最新提交的 CI 是绿色的。

  4. 如果不是发布候选版本,请确保所有 backport 到正在发布的合并分支的 pull request 都已合并。

  5. 为要发布的版本之后的版本创建一个新的 issue 和 milestone。如果发布的是发布候选版本,我们通常会为下一个主要/次要版本和下一个补丁版本创建 issue 和 milestone。在补丁版本的 milestone 中,我们添加描述 on-merge: backport to <branch>,以便我们的机器人自动将标记的 PR backport 到发布分支。

  6. 将正在发布的 milestone 中的所有 issue 和 PR 的 milestone 更改为下一个 milestone。

发布#

  1. 在要发布的合并分支的最后一个提交中创建一个空的提交和标签::

    git checkout <branch>
    git pull --ff-only upstream <branch>
    git clean -xdf
    git commit --allow-empty --author="Pandas Development Team <pandas-dev@python.org>" -m "RLS: <version>"
    git tag -a v<version> -m "Version <version>"  # NOTE that the tag is v1.5.2 with "v" not 1.5.2
    git push upstream <branch> --follow-tags
    

新版本的文档将通过 CI 中的 docs 作业自动构建和发布,当标签被推送时,该作业将被触发。

  1. 仅当发布是发布候选版本时,我们才想在其之后创建一个新分支。例如,如果我们正在发布 pandas 1.4.0rc0,我们希望创建 1.4.x 分支以将提交 backport 到 1.4 版本。以及创建一个标签来标记 1.5.0(假设它是下一个版本)的开发开始::

    git checkout -b 1.4.x
    git push upstream 1.4.x
    git checkout main
    git commit --allow-empty -m "Start 1.5.0"
    git tag -a v1.5.0.dev0 -m "DEV: Start 1.5.0"
    git push upstream main --follow-tags
    
  2. wheel staging area 下载源分发包和 wheel。请务必确保没有 missing 的 wheel(例如,由于构建失败)。

    运行脚本 scripts/download_wheels.sh 并提供您想要下载 wheel/sdist 的版本,应该就可以了。此脚本将在 pandas 的克隆中创建一个 dist 文件夹,并将下载的 wheel 和 sdist 放在其中::

    scripts/download_wheels.sh <VERSION>
    
  3. 创建一个 new GitHub release

    • 标签:<version>

    • 标题:Pandas <version>

    • 描述:复制相同类型(发布候选版本、主要/次要版本或补丁版本)的最后一个版本的描述

    • 文件:刚刚生成的 pandas-<version>.tar.gz 源分发包

    • 设置为预发布:仅勾选发布候选版本

    • 设置为最新发布:保持勾选状态,除非是为旧版本发布的补丁版本(例如,在发布 1.5 之后发布 1.4.5)

  4. Verify wheels are uploaded automatically by GitHub Actions via **Trusted Publishing** when the GitHub *Release* is published. Do not run twine upload manually.

  5. GitHub release 将在几小时后触发一个 automated conda-forge PR 。(如果您不想等待,可以打开一个标题为 @conda-forge-admin, please update version 的 issue 来触发机器人。)在 CI 变绿后合并它,它将生成 conda-forge 包。

    如果需要手动 PR,通常需要更改的是 version、sha256 和 build 字段。如果 recipe 的其他部分自上次发布以来发生更改,则这些更改应在 ci/meta.yaml 中提供。

发布后#

  1. 通过登录我们的 Web 服务器更新指向稳定文档的符号链接,并将 /var/www/html/pandas-docs/stable 编辑为指向 version/<latest-version>``(对于主要和次要版本),或对于补丁版本,将 ``version/<minor> 指向 version/<patch>。具体说明如下(将示例版本号替换为要发布的版本相对应的版本):

    • 登录服务器并使用正确的用户。

    • cd /var/www/html/pandas-docs/

    • ln -sfn version/2.1 stable (对于主版本或次版本发布)

    • ln -sfn version/2.0.3 version/2.0 (对于补丁版本发布)

  2. 如果发布主版本或次版本,请在我们源代码中打开一个 PR 来更新 web/pandas/versions.json,以便在文档下拉菜单中包含所需的版本。

  3. 关闭已发布版本的里程碑和问题。

  4. 为下一个版本创建一个新问题,并附上预计的发布日期。

  5. 打开一个 PR 来为下一个版本的发布说明创建占位符。例如,请参见 the PR for 1.5.3 。请注意,要使用的模板取决于它是主版本、次版本还是补丁版本。

  6. 在官方渠道宣布新版本(参考之前的公告):

    • pandas-dev 和 pydata 邮件列表

    • Twitter、Mastodon、Telegram 和 LinkedIn

  7. 更新此发布说明,以修复任何不正确之处,并更新自上次发布以来的任何更改。