发布版本#

以下指南包含有关如何准备 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 上成功构建。

工具链#

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

编译器#

使用与 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 文件中的一些函数或宏已弃用时,才需要增加提供给该宏的值。

仅应在 major 版本中更新 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 1.21.0 的演练,已修改为使用 GitHub Actions 和 cibuildwheels 构建并上传到 NumPy 的 Anaconda.org 暂存存储库。这些命令可以复制到命令行中,但请务必将 1.21.0 替换为正确的版本。这应该与 通用发布指南一起阅读。

设施准备#

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

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

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

发布前#

添加/删除 Python 版本#

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

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

  • .travis.yml # 用于 cibuildwheel aarch64 构建

  • setup.py # 用于分类器和最低版本检查。

在针对 main 的普通 PR 中进行这些更改,并在必要时进行回退。使用 BLD: 前缀(构建标签)作为提交摘要将导致运行轮子构建,以便测试更改。我们目前在第一个 Python rc 之后为新 Python 版本发布轮子,一旦 manylinux 和 cibuildwheel 支持它。对于 Python 3.11,我们能够在 rc1 公告后一周内发布。

回退拉取请求#

已标记为此版本的更改必须回退到 maintenance/1.21.x 分支。

创建发布 PR#

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

  • 更改日志

  • 发行说明

  • .mailmap文件

  • pyproject.toml文件

  • pyproject.toml.setuppy文件 # 1.26.x 仅限

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

REL: Prepare for the NumPy 1.20.0 release

- Create 1.20.0-changelog.rst.
- Update 1.20.0-notes.rst.
- Update .mailmap.
- Update pyproject.toml
- Update pyproject.toml.setuppy

[wheel build]

生成更改日志#

更改日志使用更改日志工具生成

$ spin changelog $GITHUB v1.20.0..maintenance/1.21.x > doc/changelog/1.21.0-changelog.rst

其中 GITHUB包含您的 GitHub 访问令牌。需要检查文本中是否有非标准贡献者名称,并删除 dependabot 条目。最好删除 PR 标题中可能存在的任何链接,因为它们无法很好地转换为 Markdown,用单空格文本替换它们。应通过更新 .mailmap文件来修复非标准贡献者名称,这是一项大量工作。最好在到达此点之前进行多次试运行,并使用 GitHub 问题 ping 违规者以获取所需的信息。

完成发行说明#

如果 doc/release/upcoming_changes/中存在任何发行说明片段,请运行 spin docs构建文档,将生成的 doc/source/release/notes-towncrier.rst文件的内容合并到发行说明文件(例如,doc/source/release/2.3.4-notes.rst)中,并删除现在已处理的 doc/release/upcoming_changes/中的片段。在发布周期中多次执行此操作是安全的。

生成的发布说明始终需要一些修复,需要编写简介,并且应该指出重大更改。对于修补程序版本,也可以追加更改日志文本,但对于初始版本则不适用,因为它太长了。检查以前的发布说明以了解如何执行此操作。

设置发布版本#

检查 pyproject.tomlpyproject.toml.setuppy文件,并在需要时设置发布版本

$ gvim pyproject.toml pyproject.toml.setuppy

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

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

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

发布流程#

请注意,在下面的代码片段中,upstream 指的是 GitHub 上的根仓库,而 origin 指的是您个人 GitHub 仓库中的 fork。如果您没有 fork 仓库,而是简单地将其克隆到本地,则可能需要进行调整。您也可以编辑 .git/config 并添加 upstream(如果尚未存在)。

1. 准备发布提交#

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

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

完整性检查。

$ python3 -m spin test -m full

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

$ git tag -a -s v1.21.0 -m"NumPy 1.21.0 release"
$ git push upstream v1.21.0

如果您需要因错误删除标签

$ git tag -d v1.21.0
$ git push --delete upstream v1.21.0

2. 构建轮子#

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

如果您希望手动触发轮子构建,可以这样做。

  • 在 GitHub Actions 上 -> 轮子构建器 存在一个“运行工作流”按钮,点击它并选择要构建的标签。

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

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

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

  • 在 Cirrus 上,我们还没有找到解决方法。

3. 下载轮子#

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

$ cd ../numpy
$ mkdir -p release/installers
$ python3 tools/download-wheels.py 1.21.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/numpy-1.21.0.tar.gz  # Upload last.

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

6. 将文件上传到 GitHub#

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

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

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

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

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

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

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

注意

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

此步骤仅适用于最终版本,对于预发布版和大多数修补程序版本可以跳过。make merge-docnumpy/doc 仓库克隆到 doc/build/merge 并使用新文档更新它。

$ git clean -xdfq
$ git co v1.21.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) 的版本。

$ gvim _static/versions.json

否则,只需要使用新的标签名称更新 zip 链接。由于我们不再生成 pdf 文件,因此如果存在,请删除 pdf 文件的行。

$ gvim index.html +/'tag v1.21'

您可以在浏览器中“测试运行”新文档以确保链接有效。

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

更新稳定链接并更新。

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

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

$ python3 update.py
$ git commit -a -m"Add documentation for v1.21.0"
$ git push
$ popd

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

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

$ cp doc/source/release/template.rst doc/source/release/1.21.1-notes.rst
$ gvim doc/source/release/1.21.1-notes.rst
$ git add doc/source/release/1.21.1-notes.rst

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

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

更新 pyproject.tomlpyproject.toml.setuppy 中的 version

$ gvim pyproject.toml pyproject.toml.setuppy

提交结果。

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

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

9. 在 numpy.org 上宣布发布(预发布版跳过)#

这假设您已 fork numpy/numpy.org

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

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

提交并推送。

$ git commit -a -m"announce the NumPy 1.21.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-1.21.0-release-update
$ git checkout maintenance/1.21.x doc/source/release/1.21.0-notes.rst
$ git checkout maintenance/1.21.x doc/changelog/1.21.0-changelog.rst
$ git checkout maintenance/1.21.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 1.21.0 release."
$ git push origin HEAD

转到 GitHub 并创建一个 PR。

12. 更新 oldest-supported-numpy#

如果此版本是第一个支持新 Python 版本的版本,或者第一个为新平台或 PyPy 版本提供轮子的版本,则应更新 scipy/oldest-supported-numpy 中的版本固定。要么提交一个带有 setup.cfg 更改的 PR,要么打开一个包含所需更改信息的 issue。

分支流程#

本指南包含在 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

现在创建一个拉取请求。