发布一个版本#

以下指南包括如何准备NumPy版本的详细信息.

如何准备发布#

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

当前构建和发布信息#

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

支持的平台和版本#

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

  • 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 toolchaincibuildwheels 和 GitHub actions 构建 NumPy.

  • Linux

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

  • BSD / Solaris

    没有提供二进制文件,但据报道在Solaris和BSD上成功构建.

工具链#

我们在云基础设施上构建所有的轮子 - 所以这个编译器列表是为了信息和本地调试构建.请参阅 numpy wheels 仓库中的 .travis.yml 脚本,了解使用 multibuild 构建配方的过时来源.

编译器#

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

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

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

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

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

OpenBLAS#

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

构建源代码存档和轮子#

现在使用 cibuildwheel 和 github actions 构建 NumPy 的 wheels 和 sdist.

构建文档#

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

  • virtualenv (pip).

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

上传到 PyPI#

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

  • twine (pip).

你还需要一个 PyPI 令牌,最好将其保存在密钥环中.请参阅 twine keyring 文档了解如何操作.

生成作者/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 位 wheels;

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

    • Linux: 使用 Github actions 构建的 x64_86 和 aarch64 Manylinux2014 轮子.

  • 其他 发布说明和更新日志

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

发布流程#

确定发布时间表#

一个典型的发布时间表是一个测试版、两个发布候选版和一个最终发布版.最好先在邮件列表中讨论时间安排,以便人们能及时提交他们的提交,合并文档维基编辑等.设定日期后,创建一个新的维护/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 是发布的主版本号和次版本号.该宏的值只有在包含文件中的某些函数或宏被弃用时才需要从上一个版本增加.

在 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 进行构建并上传到 anaconda.org 的 NumPy 暂存仓库 进行了修改.命令可以复制到命令行中,但请确保将 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 # 用于分类器和最低版本检查.

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

回移拉取请求#

此版本中标记的更改必须被移植到 maintenance/1.21.x 分支.

发布 PR#

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

  • 更新日志

  • The release-notes

  • .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 问题联系违规者以获取所需信息.

完成发布说明#

如果在 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 仓库中的分叉.如果您没有分叉仓库,而只是本地克隆了它,您可能需要进行调整.您还可以编辑 .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 触发 wheel 构建,并将 wheel 和 sdist 上传到暂存仓库.在 github actions 上运行的 CI(适用于所有基于 x86 和 macOS arm64 的 wheel)大约需要 1 1/4 小时.在 cirrus 上运行的 CI(适用于 aarch64 和 M1)所需时间较短.您可以在 staging repository 中检查已上传的文件,但请注意,它与您看到的运行作业不完全同步.

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

  • 在 github actions -> Wheel builder 上有一个”Run workflow”按钮,点击它并选择要构建的标签

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

如果某个轮子构建因不相关的原因失败,你可以单独重新运行它:

  • 在 github actions 中选择 Wheel builder,点击包含您想重新运行的构建的提交.在左侧有一个轮构建列表,选择您想重新运行的那个,然后在结果页面上点击逆时针箭头按钮.

  • 在cirrus上我们还没弄明白.

3. 下载 wheels#

当所有轮子都成功构建并暂存后,使用 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 从源代码构建而不是下载二进制 wheel.PyPI 只允许一个源代码分发,这里我们选择了 zip 存档.

6. 上传文件到 GitHub#

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

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

  • 以二进制文件形式上传 release/README.rst.

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

  • 如果这是一个预发布版本,请勾选预发布按钮.

  • 点击底部的 {发布,更新} 发布 按钮.

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

备注

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

这一步仅在最终发布时需要,预发布和大多数补丁发布可以跳过.``make merge-doc`` 将 numpy/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)preferred 的版本:

$ gvim _static/versions.json

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

$ python3 update.py

你可以在浏览器中”测试运行”新文档,以确保链接正常工作,尽管版本下拉菜单不会改变,它从 numpy.org 获取信息:

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

更新稳定链接并更新:

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

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

$ git commit -a -m"Add documentation for v1.21.0"
$ git push git@github.com:numpy/doc
$ 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 是密送,这样回复就不会发送到该列表.

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 版本提供 wheel 的版本,则应更新 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

现在发起一个拉取请求.