发布版本#

以下指南包含有关如何准备 NumPy 发行的详细信息。

如何准备发行版#

这些说明概述了构建 NumPy 二进制发行版所需的步骤。

当前构建和发行信息#

可在以下位置找到有用的信息

支持的平台和版本#

NEP 29概述了支持哪些 Python 版本;2020 年上半年,这将是 Python >= 3.6。每次我们将代码合并到主分支时,我们都会针对所有这些版本测试 NumPy。这些版本的子集可能提供二进制安装程序(见下文)。

  • OS X

    支持 OS X 版本 >= 10.9,有关 Python 版本支持,请参见 NEP 29。我们为 OSX 构建与 Python.org Python、系统 Python、homebrew 和 macports 兼容的二进制轮子 - 详情请参见此 OSX 轮子构建摘要

  • Windows

    我们在 Windows 上构建 32 位和 64 位轮子。支持 Windows 7、8 和 10。我们使用 mingw-w64 工具链cibuildwheels 和 GitHub Actions 构建 NumPy。

  • Linux

    我们构建并发布 NumPy 的 manylinux2014 轮子。许多 Linux 发行版包含它们自己 NumPy 的二进制版本。

  • BSD / Solaris

    不提供二进制文件,但已报告在 Solaris 和 BSD 上成功构建。

工具链#

我们在云基础设施上构建所有轮子 - 因此此编译器列表用于信息和本地调试构建。有关使用 multibuild 的构建方法的过时来源,请参见 numpy wheels 存储库中的 .travis.yml 脚本。

编译器#

使用与在每个平台上构建 Python 本身相同的 gcc 版本。目前这意味着

  • Travis 上的 OS X 构建当前使用 clang。当针对 Python.org 安装程序中的 Python 构建时,似乎可以从 travis-ci OSX 10.9 VM 安全地构建 OSX >= 10.6 的二进制轮子;

  • Windows 构建使用 mingw-w64 工具链

  • Manylinux2014 轮子使用 Manylinux docker 镜像中提供的 gcc。

构建二进制文件需要 Cython。Cython 将 NumPy 发行版中的 .pyx 文件编译为 .c 文件。

OpenBLAS#

所有轮子都链接到通过 openblas-libs 存储库提供的 OpenBLAS 版本。共享对象(或 DLL)与轮子一起提供,并重命名以防止与文件系统中可能存在的其他 OpenBLAS 共享对象发生名称冲突。

构建源代码存档和轮子#

NumPy 轮子和 sdist 现在使用带有 github actions 的 cibuildwheel 构建。

构建文档#

我们不再构建 PDF 文件。所有需要的将是

  • virtualenv (pip)。

其他要求将在文档构建过程中自动填充。

上传到 PyPI#

上传唯一需要的应用程序是

  • twine (pip)。

你还需要一个 PyPI 令牌,最好将其保存在密钥环中。有关如何操作,请参阅 twine 的 密钥环 文档。

生成作者/PR 列表#

您将需要一个个人访问令牌 https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/,以便脚本可以访问 github NumPy 存储库。

  • gitpython (pip)

  • pygithub (pip)

发布内容#

  • 轮子 我们目前支持 Windows、OSX 和 Linux 上的 Python 3.8-3.10。

    • Windows:使用 Github Actions 构建的 32 位和 64 位轮子;

    • OSX:使用 Github Actions 构建的 x64_86 和 arm64 OSX 轮子;

    • Linux:使用 Github Actions 构建的 x64_86 和 aarch64 Manylinux2014 轮子。

  • 其他 发行说明和更改日志

  • 源代码分发 我们以 .tar.gz 格式构建源代码发行版。

发布流程#

商定发布计划#

典型的发布计划是一个 Beta 版、两个候选发行版和一个最终发行版。最好先在邮件列表中讨论时间安排,以便人们能够及时提交他们的提交、合并文档 wiki 编辑等。设置日期后,创建一个新的 maintenance/x.y.z 分支,在主分支中为下一个版本添加新的空发行说明,并更新 Trac 里程碑。

确保当前分支可以正确构建包#

当 PR 标题以 REL 开头时,CI 会构建轮子。您在发布前的最后一个 PR 应该这样标记,并且所有测试都应该通过。您也可以执行

git clean -fxdq
python setup.py bdist_wheel
python setup.py sdist

有关构建过程本身的详细信息,最好阅读下面的分步说明。

注意

以下步骤针对 Beta 版、候选发行版和最终发行版重复。

检查弃用#

创建发行分支 之前,应该检查是否已删除所有应该删除的弃用代码,并且所有新的弃用都在文档字符串或弃用警告中说明了将在哪个版本中删除该代码。

检查 C API 版本号#

需要在三个地方跟踪 C API 版本

  • numpy/_core/meson.build

  • numpy/_core/code_generators/cversions.txt

  • numpy/_core/include/numpy/numpyconfig.h

此过程分为三个步骤。

  1. 如果 API 已更改,请增加 numpy/core/meson.build 中的 C_API_VERSION。只有当针对当前 API 编译的任何代码都与上次发布的 NumPy 版本向后兼容时,API 才未更改。对 C 结构的任何更改或对公共接口的任何添加都将使新的 API 不向后兼容。

  2. 如果第一步中的 C_API_VERSION 已更改,或者 API 的哈希值已更改,则需要更新 cversions.txt 文件。要检查哈希值,请运行脚本 numpy/_core/cversions.py 并记下打印的 API 哈希值。如果该哈希值与 numpy/_core/code_generators/cversions.txt 中的最后一个哈希值不匹配,则哈希值已更改。使用适当的 C_API_VERSION 和哈希值,向 cversions.txt 添加新条目。如果 API 版本未更改,但哈希值不同,则需要注释掉该 API 版本的先前条目。例如,在 NumPy 1.9 中添加了注释,这改变了哈希值,但 API 与 1.8 中的相同。哈希值用作 API 更改的检查,但它并非决定性的。

    如果正确完成了步骤 1 和 2,则编译发行版不应给出警告“在构建开始时检测到 API 不匹配”。

  3. numpy/_core/include/numpy/numpyconfig.h 将需要一个新的 NPY_X_Y_API_VERSION 宏,其中 X 和 Y 是发行版的 major 和 minor 版本号。只有在 include 文件中的一些函数或宏已弃用时,才需要增加赋予该宏的值。

仅应在主要版本中更新 numpy/_core/meson.build 中的 C ABI 版本号。

检查发行说明#

使用 towncrier 构建发行说明并提交更改。这将删除 doc/release/upcoming_changes 中的所有片段,并添加 doc/release/<version>-note.rst

towncrier build --version "<version>"
git commit -m"Create release note"

检查发行说明是否最新。

更新发行说明,添加“亮点”部分。提及以下内容:

  • 主要新功能

  • 已弃用和移除的功能

  • 支持的 Python 版本

  • 对于 SciPy,支持的 NumPy 版本

  • 近期展望

分步说明#

这是在 Linux 上发布 NumPy 2.1.0 版本的演练,已针对使用 GitHub Actions 和 cibuildwheels 构建以及上传到 NumPy 的 Anaconda.org 暂存库 进行修改。这些命令可以复制到命令行中,但请务必将 2.1.0 替换为正确的版本。这应该与 通用发行指南 一起阅读。

设施准备#

在开始发布之前,使用 requirements/*_requirements.txt 文件确保您拥有所需的软件。大多数软件可以使用 pip 安装,但有些需要 apt-get、dnf 或您的系统使用的任何软件包管理器。您还需要一个 GitHub 个人访问令牌 (PAT) 来推送文档。有几种方法可以简化流程:

  • 可以将 Git 设置为使用密钥环存储您的 GitHub 个人访问令牌。在线搜索详细信息。

  • 您可以使用 keyring 应用程序存储 twine 的 PyPI 密码。有关详细信息,请参阅在线 twine 文档。

发布前#

添加/删除 Python 版本#

添加或删除 Python 版本时,需要编辑三个文件:

  • .github/workflows/wheels.yml # 用于 github cibuildwheel

  • tools/ci/cirrus_wheels.yml # 用于 cibuildwheel aarch64/arm64 构建

  • pyproject.toml # 用于分类器和最小版本检查。

在针对 main 分支的普通 PR 中进行这些更改,并在必要时进行反向移植。在提交摘要的标题行末尾添加 [wheel build],以便运行 wheel 构建来测试更改。我们目前在第一个 Python rc 之后,一旦 manylinux 和 cibuildwheel 支持,就会为新的 Python 版本发布 wheel。对于 Python 3.11,我们能够在 rc1 发布公告后一周内发布。

反向移植拉取请求#

已标记为此版本的更改必须反向移植到 maintenance/2.1.x 分支。

更新 2.1.0 里程碑#

查看带有 2.1.0 里程碑的问题/PR,并将它们推迟到以后的版本,或者可能删除里程碑。您可能需要添加里程碑。

创建发布 PR#

发布 PR 通常需要更新或创建四个文档:

  • 变更日志

  • 发行说明

  • .mailmap 文件

  • pyproject.toml 文件

这些更改应在针对维护分支的普通 PR 中进行。提交标题应包含 [wheel build] 指令以测试 wheel 是否构建成功。其他小的、杂项的修复也可能包含在这个 PR 中。提交消息可能类似于:

REL: Prepare for the NumPy 2.1.0 release [wheel build]

- Create 2.1.0-changelog.rst.
- Update 2.1.0-notes.rst.
- Update .mailmap.
- Update pyproject.toml

设置发布版本#

检查 pyproject.toml 文件,如果需要,设置发布版本。

$ gvim pyproject.toml

检查 pavement.pydoc/source/release.rst 文件#

检查 pavement.py 文件是否指向正确的发行说明。它应该在上一次发布后更新,但如果没有,请现在修复它。还要确保该说明在 release.rst 文件中有一个条目。

$ gvim pavement.py doc/source/release.rst

生成变更日志#

变更日志使用变更日志工具生成:

$ spin changelog $GITHUB v2.0.0..maintenance/2.1.x > doc/changelog/2.1.0-changelog.rst

其中 GITHUB 包含您的 GitHub 访问令牌。需要检查文本中是否存在非标准贡献者姓名,并删除 dependabot 条目。最好还删除 PR 标题中可能存在的任何链接,因为它们不能很好地转换为 markdown,请将它们替换为等宽文本。应通过更新 .mailmap 文件来修复非标准贡献者姓名,但这需要大量工作。最好在达到此步骤之前进行多次试运行,并使用 GitHub 问题 ping 相关人员以获取所需信息。

完成发行说明#

如果 doc/release/upcoming_changes/ 中有任何发行说明片段,请运行 spin notes,这会将片段合并到 doc/source/release/notes-towncrier.rst 文件中并删除这些片段。

$ spin notes
$ gvim doc/source/release/notes-towncrier.rst doc/source/release/2.1.0-notes.rst

一旦 notes-towncrier 的内容已合并到发行说明中,就可以删除 .. include:: notes-towncrier.rst 指令。说明总是需要一些修改,需要编写引言,并且应该特别指出重大更改。对于补丁版本,也可以追加变更日志文本,但对于初始版本则不行,因为它太长了。请检查之前的发行说明以了解如何操作。

发行演练#

请注意,在下面的代码片段中,upstream 指的是 GitHub 上的根仓库,origin 指的是您个人 GitHub 仓库中的分支。如果您没有分叉仓库而只是在本地克隆了它,则可能需要进行调整。您也可以编辑 .git/config 并添加 upstream(如果它不存在)。

1. 准备发布提交#

检出发布分支,确保它是最新的,并清理仓库。

$ git checkout maintenance/2.1.x
$ git pull upstream maintenance/2.1.x
$ git submodule update
$ git clean -xdfq

完整性检查

$ python3 -m spin test -m full

标记发布并推送标记。这需要 NumPy 仓库的写入权限。

$ git tag -a -s v2.1.0 -m"NumPy 2.1.0 release"
$ git push upstream v2.1.0

如果您需要由于错误而删除标记:

$ git tag -d v2.1.0
$ git push --delete upstream v2.1.0

2. 构建 wheel#

在此过程开始时标记构建将通过 cibuildwheel 触发 wheel 构建,并将 wheel 和 sdist 上传到暂存库。GitHub Actions 上的 CI 运行(对于所有基于 x86 和 macOS arm64 的 wheel)大约需要 1 小时 15 分钟。Cirrus 上的 CI 运行(对于 aarch64 和 M1)所需时间较短。您可以在 暂存库 中检查上传的文件,但请注意,它与您看到的正在运行的任务并不完全同步。

如果您希望手动触发 wheel 构建,您可以这样做:

  • 在 GitHub Actions 上 -> Wheel 构建器 中有一个“运行工作流程”按钮,单击它并选择要构建的标记。

  • 在 Cirrus 上,我们目前没有简单的方法来手动触发构建和上传。

如果 wheel 构建由于无关原因失败,您可以单独重新运行它:

  • 在 GitHub Actions 上,选择 Wheel 构建器,单击包含要重新运行的构建的提交。左侧有一个 wheel 构建列表,选择要重新运行的构建,然后在结果页面上点击逆时针箭头按钮。

  • 在 Cirrus 上,登录 Cirrus CI,查找 v2.1.0 标记并重新运行失败的任务。

3. 下载 wheel#

所有 wheel 都成功构建和暂存后,使用 tools/download-wheels.py 脚本从 Anaconda 暂存目录下载它们。

$ cd ../numpy
$ mkdir -p release/installers
$ python3 tools/download-wheels.py 2.1.0

4. 生成 README 文件#

这需要在下载所有安装程序后但更新 pavement 文件以继续开发之前完成。

$ paver write_release

5. 上传到 PyPI#

使用 twine 上传到 PyPI。在最近的 PyPI 更改之后,需要一个最近版本的 twine,此处使用了版本 3.4.1

$ cd ../numpy
$ twine upload release/installers/*.whl
$ twine upload release/installers/*.gz  # Upload last.

如果其中一个命令中断,您可能需要有选择地上传剩余的文件,因为 PyPI 不允许上传相同的文件两次。应最后上传源文件,以避免在 pip 用户在此过程中访问文件时可能发生的同步问题,这会导致 pip 从源代码构建而不是下载二进制 wheel 文件。PyPI 只允许单个源发行版,这里我们选择了 zip 压缩文件。

6. 将文件上传到 GitHub#

访问 numpy/numpy,应该有一个 v2.1.0 tag,单击它并点击该标签的编辑按钮,并将标题更新为“v2.1.0 (<date>)”。添加文件有两种方法:使用可编辑文本窗口和作为二进制上传。首先编辑 release/README.md,该文件是使用 pandoc 从 rst 版本转换而来的。需要修改的地方:如果包含更改日志的 PR 行,则会换行,需要取消换行;链接应更改为等宽文本。然后复制内容到剪贴板,并将其粘贴到文本窗口中。可能需要多次尝试才能使其看起来正确。然后

  • release/installers/numpy-2.1.0.tar.gz 作为二进制文件上传。

  • release/README.rst 作为二进制文件上传。

  • doc/changelog/2.1.0-changelog.rst 作为二进制文件上传。

  • 如果这是预发行版,请选中预发行版按钮。

  • 点击底部的 {Publish,Update} release 按钮。

7. 将文档上传到 numpy.org (预发行版跳过)#

注意

您需要一个 GitHub 个人访问令牌才能推送更新。

此步骤仅对于最终发行版才需要,对于预发行版和大多数补丁发行版可以跳过。make merge-docnumpy/doc 仓库克隆到 doc/build/merge 并使用新文档更新它。

$ git clean -xdfq
$ git co v2.1.0
$ rm -rf doc/build  # want version to be current
$ python -m spin docs merge-doc --build
$ pushd doc/build/merge

如果发行版系列是新的,则需要在 doc/build/merge/index.html 首页的“在此处插入”注释之后添加一个新部分。

$ gvim index.html +/'insert here'

此外,更新版本切换器 json 文件以添加新版本并更新标记为 (stable)preferred 的版本。

$ gvim _static/versions.json

然后运行 update.py 以更新 _static 中的版本。

$ python3 update.py

您可以在浏览器中“测试运行”新文档以确保链接有效,尽管版本下拉菜单不会更改,但它会从 numpy.org 获取其信息。

$ firefox index.html  # or google-chrome, etc.

更新稳定链接并更新。

$ ln -sfn 2.1 stable
$ ls -l  # check the link

一切看起来令人满意后,更新、提交并上传更改。

$ git commit -a -m"Add documentation for v2.1.0"
$ git push [email protected]:numpy/doc
$ popd

8. 将维护分支重置为开发状态 (预发行版跳过)#

为下一个版本创建发行说明并编辑它们以设置版本。这些说明将是框架,内容很少。

$ git checkout -b begin-2.1.1 maintenance/2.1.x
$ cp doc/source/release/template.rst doc/source/release/2.1.1-notes.rst
$ gvim doc/source/release/2.1.1-notes.rst
$ git add doc/source/release/2.1.1-notes.rst

将新的发行说明添加到文档发行列表中,并更新 pavement.py 中的 RELEASE_NOTES 变量。

$ gvim doc/source/release.rst pavement.py

更新 pyproject.toml 中的 version

$ gvim pyproject.toml

提交结果。

$ git commit -a -m"MAINT: Prepare 2.1.x for further development"
$ git push origin HEAD

转到 GitHub 并创建一个 PR。它应该很快被合并。

9. 在 numpy.org 上发布公告 (预发行版跳过)#

这假设您已分叉 numpy/numpy.org

$ cd ../numpy.org
$ git checkout main
$ git pull upstream main
$ git checkout -b announce-numpy-2.1.0
$ gvim content/en/news.md
  • 对于所有发行版,转到页面底部并添加一个单行链接。查看以前的链接以了解示例。

  • 对于一个周期中的 *.0 发行版,在顶部添加一个新部分,简要描述新功能并将新闻链接指向它。

提交并推送。

$ git commit -a -m"announce the NumPy 2.1.0 release"
$ git push origin HEAD

转到 GitHub 并创建一个 PR。

10. 向邮件列表发布公告#

应在 numpy-discussion、scipy-devel 和 python-announce-list 邮件列表上发布发行公告。查看以前的公告以了解基本模板。贡献者和 PR 列表与上面为发行说明生成的列表相同。如果您交叉发布,请确保 python-announce-list 为 BCC,以便不会将回复发送到该列表。

11. 发行后更新主分支 (预发行版跳过)#

检出主分支并前向移植文档更改。如果流程已更改或改进,您可能也希望更新这些说明。

$ git checkout -b post-2.1.0-release-update main
$ git checkout maintenance/2.1.x doc/source/release/2.1.0-notes.rst
$ git checkout maintenance/2.1.x doc/changelog/2.1.0-changelog.rst
$ git checkout maintenance/2.1.x .mailmap  # only if updated for release.
$ gvim doc/source/release.rst  # Add link to new notes
$ git status  # check status before commit
$ git commit -a -m"MAINT: Update main after 2.1.0 release."
$ git push origin HEAD

转到 GitHub 并创建一个 PR。

分支流程#

本指南包含在 Linux 上分支 NumPy 1.21.x 的流程。可以将命令复制到命令行,但请务必将 1.21 和 1.22 替换为正确的版本。在创建分支之前,最好尽可能使 .mailmap 保持最新状态,这可能需要几周时间。

这应与通用发行指南一起阅读。

分支#

创建分支#

这仅在启动新的维护分支时才需要。因为 NumPy 现在依赖于标签来确定版本,所以主分支中新开发周期的开始需要一个带注释的标签。操作如下:

$ git checkout main
$ git pull upstream main
$ git commit --allow-empty -m'REL: Begin NumPy 1.22.0 development'
$ git push upstream HEAD

如果由于合并了新的 PR 而导致推送失败,请执行

$ git pull --rebase upstream

并重复推送。推送成功后,对其进行标记

$ git tag -a -s v1.22.0.dev0 -m'Begin NumPy 1.22.0 development'
$ git push upstream v1.22.0.dev0

然后创建新的分支并推送它

$ git branch maintenance/1.21.x HEAD^
$ git push upstream maintenance/1.21.x

准备主分支以进行进一步开发#

创建一个 PR 分支以准备主分支以进行进一步开发。

$ git checkout -b 'prepare-main-for-1.22.0-development' v1.22.0.dev0

删除发行说明片段。

$ git rm doc/release/upcoming_changes/[0-9]*.*.rst

创建新的发行说明框架并添加到索引。

$ cp doc/source/release/template.rst doc/source/release/1.22.0-notes.rst
$ gvim doc/source/release/1.22.0-notes.rst  # put the correct version
$ git add doc/source/release/1.22.0-notes.rst
$ gvim doc/source/release.rst  # add new notes to notes index
$ git add doc/source/release.rst

更新 pavement.py 并更新 RELEASE_NOTES 变量以指向新的说明。

$ gvim pavement.py
$ git add pavement.py

更新 cversions.txt 以添加当前版本。在这个早期阶段,不应该有新的哈希值需要担心,只需按照之前的惯例添加注释即可。

$ gvim numpy/_core/code_generators/cversions.txt
$ git add numpy/_core/code_generators/cversions.txt

检查您的工作,提交并推送。

$ git status  # check work
$ git commit -m'REL: Prepare main for NumPy 1.22.0 development'
$ git push origin HEAD

现在创建一个拉取请求。