SciPy 核心开发者指南#

决策过程#

SciPy 有一个正式的治理模型,记录在SciPy 项目治理中。以下部分以非正式的方式记录了关于代码和提交权限的实际决策过程。正式的治理模型是主导的,以下内容仅供参考。

代码#

关于添加(或不添加)新功能、破坏向后兼容性或对代码库进行其他重大更改的任何重要决策,都应在 scipy-dev 论坛上进行讨论后(最好在完全达成共识的情况下)做出。

任何非微不足道的更改(微不足道指拼写错误或单行维护提交)都必须通过拉取请求(PR)进行。它必须由另一位开发者审查。如果审查不够快,并且 PR 需要快速合并,PR 提交者应向论坛发送消息,说明他们打算在时间 X 因原因 Y 在没有审查的情况下合并该 PR,除非有人在此之前对其进行审查。

更改和新增内容应经过测试。未经测试的代码是损坏的代码。

提交权限#

提交权限的授予由 SciPy 指导委员会决定;提交权限的更改将在 scipy-dev 论坛上公布。

决定新功能#

迄今为止,接受拟议新功能的一般决策规则取决于以下条件:

  1. 该方法适用于许多领域并“普遍认为”有用,

  2. 它符合子模块的主题,并且不需要广泛的支持框架即可运行,

  3. 实现看起来可靠,未来不太可能需要大量调整(例如,预期维护负担有限),

  4. 有人愿意贡献它,并且

  5. 有人愿意审查它。

最后一个标准常常是拟议功能的症结所在。代码在彻底审查之前无法合并,而且总有积压的维护任务与审查人员的时间竞争。理想情况下,贡献者应在开始工作之前找到一位具有适当领域专业知识的审查人员。

尽管很难给出“普遍有用且普遍认可有效”的确切定义,但权衡以下几点可能会有所帮助:

  • 该方法在实践中是否在不同领域中使用/有用?正确使用它需要多少领域特定的背景知识?

  • 考虑模块中已有的代码。您添加的内容是遗漏吗?它是否解决了您期望模块能够解决的问题?它是否以显著方式补充了现有功能?

  • 考虑通常期望的类似方法/功能的等价类。其中,原则上最小的集合是什么,才能确保所提供的功能中没有明显的遗漏?这将涉及多少内容?包含其中一个代表性功能是否涵盖了大多数用例?原则上,将最小集合中的所有内容都包含在模块中是否合理?

  • 您添加的内容在文献中是否被充分理解?如果不是,您有多确定它会进展顺利?与其他类似方法相比,该方法性能如何?

  • 请注意,每年两次的发布周期和向后兼容性策略使得后续纠正问题更加困难。

子模块的范围也各不相同,因此最好将每个子模块视为一个单独的项目——“特殊函数的数值评估”相对明确,而“常用优化算法”则不那么明确。

GitHub 上的开发#

SciPy 的开发主要在 GitHub 上进行;本节描述了处理问题、拉取请求和管理主 scipy 仓库的预期工作方式。

标签和里程碑#

每个议题和拉取请求通常会获得至少两个标签:一个用于主题或组件(例如 scipy.statsDocumentation 等),另一个用于议题或拉取请求的性质(例如 enhancementmaintenancedefect 等)。根据情况可能添加的其他标签:

  • good-first-issue:适用于新贡献者处理的议题。

  • needs-work:用于有未解决的审查意见的拉取请求。

  • needs-decision:用于需要做出决策的议题或拉取请求。

  • needs-champion:用于原始作者未完成但值得恢复的拉取请求。

  • backport-candidate:发布管理器应考虑反向移植的错误修复。

为计划发布的每个版本号创建里程碑。需要解决的议题和需要合并的拉取请求应设置为相应的里程碑。拉取请求合并后,其里程碑(以及它关闭的议题的里程碑)应设置为下一个即将发布的版本——这使得可以轻松概览更改,并将完整的更改列表添加到发布说明中。

拉取请求审查工作流程#

在审查拉取请求时,请利用拉取请求工作流程功能,参见使用工作流程功能

处理拉取请求#

  • 合并贡献时,提交者有责任确保这些贡献符合贡献 SciPy中概述的要求。还要检查新功能和向后兼容性破坏是否已在 scipy-dev 论坛上讨论过。

  • 新代码通过拉取请求(PR)提交。

  • 使用绿色按钮合并新代码。如果存在合并冲突,请要求 PR 提交者进行 rebase(这可能需要提供一些 git 指令)。

  • 反向移植和完成 PR 的微不足道(例如拼写错误或 PEP8 修复)的添加可以直接推送。

  • 对于添加新功能或以某种方式复杂的 PR,请至少等待一两天再合并。这样,其他人可以在代码提交之前有机会发表评论。

  • 压缩提交或清理您认为过于混乱的 PR 提交消息是可以的。但请确保在执行此操作时保留原始作者姓名。只要提交消息未(大致)遵循编写提交消息中的准则,强烈建议进行压缩。

  • 确保已合并 PR 上的标签和里程碑设置正确。

  • 当您想拒绝一个 PR 时:如果原因非常明显,您可以直接关闭它并解释原因。如果原因不明显,那么最好先解释为什么您认为该 PR 不适合包含在 SciPy 中,然后让第二个提交者评论或关闭。

反向移植#

所有拉取请求(无论它们包含增强功能、错误修复或其他内容)都应针对主分支进行。只有错误修复才是反向移植到维护分支的候选对象。SciPy 的反向移植策略是 (a) 只反向移植重要的修复,以及 (b) 只有在合理确定将在相关维护分支上进行新的错误修复发布时才进行反向移植。通常,合并重要错误修复的开发者会添加 backport-candidate 标签并通知发布管理器,由发布管理器决定是否以及何时完成反向移植。反向移植完成后,必须再次移除 backport-candidate 标签。

反向移植拉取请求的一个好策略是合并多个主分支拉取请求,以减少持续集成测试的负担,并减少维护分支历史中合并提交的混乱。通常最好为反向移植拉取请求中代表的每个主分支拉取请求都有一个单独的提交。这样,历史清晰,如果需要可以以直接的方式回滚。

发布说明#

当 PR 合并后,请考虑这些更改是否需要在发布说明中提及。需要提及的内容包括:新功能、向后不兼容的更改、废弃项以及“其他更改”(任何其他值得注意的内容,请参阅旧的发布说明以了解值得提及的类型)。

发布说明条目在wiki上维护。发布管理器将从那里收集内容并将其整合到 HTML 文档中。我们使用这种机制来避免由于每个 PR 直接修改 doc/release/ 下的同一个文件而导致的合并冲突。

可以监控更改(Atom feed)并拉取(wiki 是一个 git 仓库:https://github.com/scipy/scipy.wiki.git)。

其他#

交叉引用: 在 GitHub 上交叉引用议题和拉取请求通常很有用。GitHub 允许使用 gh-xxxx#xxxx 来进行,其中 xxxx 是议题/PR 号。强烈推荐使用 gh-xxxx 格式,因为它清楚地表明这是一个 GitHub 链接。旧的议题包含 #xxxx,这指的是 Trac(我们在 GitHub 之前使用的)工单。

PR 命名约定: 拉取请求、议题和提交消息通常以三字母缩写开头,例如 ENH:BUG:。这有助于快速了解提交/PR/议题的性质。有关缩写的完整列表,请参见编写提交消息

许可#

SciPy 采用修改后的(三条款)BSD 许可证分发。贡献者添加到 SciPy 的所有代码、文档和其他文件均在此许可证下获得许可,除非在源代码中明确指定了其他许可证。贡献者保留他们编写并提交给 SciPy 的代码的版权。

与 SciPy 使用的修改后 BSD 许可证兼容的其他许可证有 2-clause BSD、MIT 和 PSF。不兼容的许可证是 GPL、Apache 以及需要署名/引用或禁止用于商业目的的自定义许可证。

拉取请求通常提交的内容是复制或派生自未许可代码或与 SciPy 许可证不兼容的默认许可证代码。例如,发布在 StackOverflow 上的代码受 CC-BY-SA 许可证保护,由于其“相同方式共享”条款而不兼容。除非原始代码作者愿意根据修改后的 BSD(或兼容)许可证重新许可其代码,否则这些贡献不能被 SciPy 接受。如果原始作者同意,请在源文件中添加注释说明,并将相关通信转发到 scipy-dev 论坛。

另一种常见情况是代码从 R、Octave(均采用 GPL 许可)或商业应用程序中的代码翻译或派生而来。此类代码也不能包含在 SciPy 中。但是,只要作者不查看原始不兼容许可的源代码,仅实现与 R/Octave/… 中相同的 API 功能是允许的。

版本编号#

SciPy 版本编号符合PEP 440。发布的最终版本是唯一出现在PyPI上的版本,编号格式为 MAJOR.MINOR.MICRO,其中:

  • MAJOR 是一个整数,表示主版本。它很少更改;MAJOR 的更改表示重大(可能向后不兼容的)更改。

  • MINOR 是一个整数,表示次版本。次版本通常每年发布两次,可能包含新功能、弃用和错误修复。

  • MICRO 是一个整数,表示错误修复版本。错误修复版本在需要时发布,通常每个次版本发布一到两个。它们不能包含新功能或弃用。

发布的 alpha、beta 和 rc(发布候选)版本的编号方式与最终版本相同,但分别带有后缀 a#b#rc#,其中 # 是一个整数。开发版本以 .dev0+<git-commit-hash> 为后缀。

有效的 SciPy 版本字符串示例:

0.16.0
0.15.1
0.14.0a1
0.14.0b2
0.14.0rc1
0.17.0.dev0+ac53f09

已安装的 SciPy 版本包含这些版本标识符:

scipy.__version__            # complete version string, including git commit hash for dev versions
scipy.version.short_version  # string, only major.minor.micro
scipy.version.version        # string, same as scipy.__version__
scipy.version.full_version   # string, same as scipy.__version__
scipy.version.release        # bool, development or (alpha/beta/rc/final) released version
scipy.version.git_revision   # string, git commit hash from which scipy was built

弃用#

希望移除现有功能的原因有很多:它有 bug、API 难以理解、已被性能更好的功能取代、需要移动到另一个 SciPy 子模块等。

一般来说,不事先警告用户就移除某些功能不是一个好主意。因此,在从公共 API 中移除任何功能之前,应执行以下操作:

  1. 在 scipy-dev 论坛上提议弃用该功能,并获得同意。

  2. 为其添加一个 DeprecationWarning,说明该功能已弃用,以及在哪个版本中弃用。对于 Cython API,请参阅弃用公共 Cython API以了解具体步骤。

  3. 在该版本的发布说明中提及弃用。

  4. 在引入 DeprecationWarning 的版本发布日期后,至少等待 6 个月再移除该功能。

  5. 在发布说明中提及该功能的移除。

实际操作中,6 个月的等待期通常意味着等待两个版本。在引入警告时,还要确保在运行测试套件时过滤掉这些警告,以免它们污染输出。

对于特定弃用,可能有理由希望忽略此弃用策略;这始终可以在 scipy-dev 论坛上讨论。

内嵌代码#

SciPy 代码库的许多部分在其他地方维护,并以内嵌形式包含在 SciPy 中。其中一些部分以内嵌 git 子模块的形式存在,例如 xsf,或者放置在 subprojects 目录下(或两者兼有)。

其他部分尽管有上游维护,但并未以内嵌 git 子模块的形式或在 subprojects 目录下。这通常是因为:

  1. 上游仓库的一个子集是通过脚本以内嵌形式包含的。

    (这些部分未来可能会被移至 subprojects 目录下。)

  2. 代码已被复制到 SciPy 并经过修改。

    (这些部分中的一些未来可能会看到上游贡献的补丁,并成为 git 子模块或被移至 subprojects 目录下。)

维护者应注意不要接受对 SciPy 中代码由上游积极维护的部分的贡献(特别是微不足道的更改)。相反,他们应将贡献者引导至上游仓库。

通过脚本内嵌的代码库部分包括:

  • PRIMA,位于 scipy/_lib/pyprima

包含从上游复制的代码的代码库部分包括:

有关仓库中内嵌代码的更多详情和跟踪,请参阅scipy/scipy#21232

分发#

分发 Python 包并非易事——特别是对于像 SciPy 这样构建要求复杂的包——并且随时可能发生变化。有关推荐工具和技术的最新概述,请参阅Python 打包用户指南。本文档讨论了 SciPy 的一些主要问题和注意事项。

依赖项#

依赖项是用户为了使用(或构建/测试)一个包而必须安装的东西。它们通常会引起麻烦,特别是如果它们不是可选的。SciPy 尽量将其依赖项保持在最低限度;当前必需和可选的构建时依赖项可以在SciPy 的配置文件 pyproject.toml 中查看。唯一非可选的运行时依赖项是 NumPy

此外,当然还需要 C、C++ 和 Fortran 编译器来构建 SciPy,但我们不认为它们是依赖项,因此在此不予讨论。详情请参见从源代码构建

当一个包提供有用的功能并被提议作为新的依赖项时,也要考虑是否将其内嵌(即随 SciPy 一同分发其副本)。例如,decorator 已内嵌到 scipy._lib 中。

依赖项处理问题#

Python 打包工具处理项目报告的依赖项存在一些问题。由于 SciPy 经常收到关于此的错误报告,我们在此详细说明。

SciPy 通过 pyproject.toml 报告其对 NumPy 的构建依赖,并且 SciPy 也有一个运行时检查,确保有适当版本的 NumPy 可用。SciPy 不再使用 setup_requires(过去会调用 easy_install);构建依赖现在只通过 pyproject.toml 处理。pyproject.toml 依赖于 PEP 517;pip--no-use-pep517--no-build-isolation 标志,这些标志可能会忽略 pyproject.toml 或以不同方式处理它——如果用户使用这些标志,他们需要自行安装正确的构建依赖项。

NumPy 及其他依赖项的版本范围#

对于依赖项,设置其版本的上限和下限非常重要。对于构建时依赖项,它们在 pyproject.toml 中指定,并且这些版本适用于 SciPy 本身的构建。对于像 meson-pythonpybind11 这样的依赖项,指定版本范围或特定版本都可以。对于 NumPy,我们还需要关注 ABI 兼容性。然而,对于 NumPy >=2.0.0rc1,向后兼容性可以追溯到 NumPy 1.19 系列,因此在构建时在 pyproject.toml 中不再需要指定最低支持的 NumPy 版本。

对于运行时依赖项(目前只有 numpy),我们在 pyproject.tomlscipy/__init__.py 中指定版本范围。正确设置上限有点棘手。如果我们不设置任何上限,几年后可能会引入一个过新的版本,届时 NumPy 可能已经弃用并移除了 SciPy 依赖的某些 API。另一方面,如果我们将上限设置为最新已发布的版本,那么一旦新的 NumPy 版本发布,就没有与之兼容的 SciPy 版本了。鉴于 NumPy 和 SciPy 都以 6 个月为周期发布,并且 NumPy 中弃用的功能应该再保留两个版本,我们将上限指定为 <2.xx+3.0(其中 xx 是最新已发布的 NumPy 的次版本号)。

支持的 Python 和 NumPy 版本#

SciPy 支持的 Python 版本列在 pyproject.toml 中的 PyPI 分类器列表中,并在每个版本的发布说明中提及。所有新发布的 Python 版本将尽快得到支持。有关停止支持 Python 或 NumPy 版本的通用策略,请参见NEP 29。停止支持的最终决定始终在 scipy-dev 论坛上做出。

SciPy 版本支持的最低 NumPy 版本在发布说明中提及,并编码在 pyproject.tomlscipy/__init__.py 中。通常,最新的 SciPy 版本支持大约 5-7 个 NumPy 次版本:即长达 2.5 年前的 NumPy 版本(鉴于撰写本文时 NumPy 的发布频率约为每年 2 次),再加上未来两个版本。

可选依赖项和编译器支持的版本记录在工具链路线图中。请注意,SciPy 的持续集成设置并未充分或完全测试所有支持的可选依赖项版本。相关问题将在问题跟踪器或论坛中出现时处理。

构建二进制安装程序#

注意

本节仅讨论构建用于分发的 SciPy 二进制安装程序。有关在使用 SciPy 的同一机器上构建 SciPy 的信息,请参见从源代码构建

在构建二进制文件并在 PyPI 或其他地方分发它们时,需要考虑一些事项。

一般

  • 二进制文件特定于单个(主)Python 版本(因为不同的主 Python 版本不兼容 ABI,至少到 Python 3.12 为止)。

  • 针对 NumPy 2.0.0 构建,然后它将适用于所有具有相同主版本号的 NumPy 版本(NumPy 确实保持向后 ABI 兼容性),并且可追溯到撰写本文时的 NumPy 1.19 系列。

  • 构建可移植 SciPy 二进制文件的最简单可用工具链是我们在常见平台上的 cibuildwheel 基础设施,详细信息可在我们的 CI 基础设施代码中找到,并通过 Windows、Linux 和 MacOS 上的 cibuildwheel 命令提供,尽管在某些情况下需要一些额外的外部依赖项

Windows

  • 对于使用免费工具链构建的 64 位 Windows 安装程序,请使用numpy/numpy中记载的方法。一旦明确该工具链的维护能够长期持续,该方法很可能会用于 SciPy 本身。详情请参见 MingwPy 项目和此讨论串

  • 生成 64 位 Windows 安装程序的另一种方法是使用 iccifort 加上 MKL(或使用 MSVC 代替 icc)。有关 Intel 工具链的说明,请参阅本文;有关(部分)MSVC 的说明,请参阅此 wiki 页面

  • 较早的 SciPy 版本包含一个 .exe“超级包”安装程序。这些安装程序包含 3 个完整构建(无 SSE、SSE2、SSE3),并使用numpy/numpy-vendor构建。该构建设置已知不再运行良好且不再受支持。它使用 g77 而非 gfortran,原因在于复杂的 DLL 分发问题(参见gh-2829)。由于该工具链不再受支持,因此不再需要 g77 支持,SciPy 现在可以包含 Fortran 90/95 代码。

Linux

  • PyPI 兼容的 Linux wheels 可以通过 manylinux 项目生成,该项目是我们的 cibuildwheel 基础设施在幕后使用的。

其他 Linux 构建设置会导致与 PyPI 不兼容的 wheel,需要通过自定义渠道分发,例如在 Wheelhouse 中,详情请参阅 wheelWheelhouse 文档。

文档字符串中的交互式示例#

文档字符串中的示例可以使用jupyterlite-sphinx 扩展实现交互性,该扩展实现了 .. try_examples:: 指令。当在文档字符串的“Examples”部分中使用时,此指令将创建一个按钮,允许用户在交互式 JupyterLite 窗口中打开示例,或在新选项卡中作为 Jupyter 笔记本打开。对于 SciPy,此指令通过 doc/source/conf.py 中的 global_enable_try_examples 配置选项自动添加到所有带有“Examples”部分的文档字符串中。

要隐藏将文档字符串示例转换为嵌入式笔记本的按钮,在构建 HTML 文档后,编辑 scipy/doc/build/html/ 后的 try_examples.json 运行时配置文件,并将要忽略的文件 URL 路径添加到 ignore_patterns 列表中。此列表要求元素为 JavaScript 正则表达式模式。干净文档构建中此文件的初始版本是:

{
    "global_min_height": "400px",
    "ignore_patterns": [".*"]
}

在干净的文档构建中,用于将示例部分转换为嵌入式交互式笔记本的按钮默认隐藏。

有关 jupyterlite-sphinx TryExamples 指令的更多信息,请参见其文档。

进行 SciPy 发布#

在最高层面,发布管理器发布新 SciPy 版本的工作如下:

  1. 在 SciPy 论坛上提议发布时间表,网址为 https://discuss.scientific-python.org/

  2. 为发布创建维护分支。

  3. 标记发布。

  4. 构建所有发布制品(源代码、安装程序、文档)。

  5. 上传发布制品。

  6. 宣布发布。

  7. 将发布说明和构建脚本中的相关更改移植到主分支。

本指南将详细描述如何执行上述每个步骤。除了发布经理必须执行的这些步骤外,以下是与发布相关的活动和惯例的描述:

提议发布时间表#

典型的发布周期如下所示:

  • 创建维护分支

  • 发布 beta 版本

  • 发布“发布候选”(RC)

  • 如果需要,发布一个或多个新的 RC

  • 在最后一个发布候选版本没有问题后发布最终版本

上述每个步骤之间通常至少间隔一周。经验表明,一个新次版本(minor version)的发布周期通常在 4 到 8 周之间。错误修复版本不需要 beta 或 RC,可以更快完成。

理想情况下,最终发布应与最后一个 RC 完全相同,但可能存在微小差异——由发布经理判断其风险。通常,如果编译代码或复杂的纯 Python 代码发生更改,则需要新的 RC,而从主分支反向移植的简单错误修复则不需要新的 RC。

要提议时间表,请将包含分支以及 beta/rc/最终发布估计日期的列表发送到 SciPy 论坛,网址为 https://discuss.scientific-python.org/。在同一条消息中,请所有人检查是否有需要包含但未用发布里程碑或“backport-candidate”标签标记的重要问题/PR。

创建维护分支#

在分支之前,确保发布说明尽可能更新。在发布说明中包含 tools/gh_lists.pytools/authors.py 的输出。

维护分支的命名格式为 maintenance/<major>.<minor>.x(例如 0.19.x)。要创建一个维护分支,只需将一个具有正确名称的分支推送到 scipy 仓库。紧接着,推送一个提交,其中您在主分支上增加版本号并为该新版本添加发布说明。向 SciPy 论坛(https://discuss.scientific-python.org/)发送电子邮件,告知大家您已完成此操作。

更新版本切换器#

版本切换器下拉菜单仅需在 main 分支上更新新的发布信息。

  • doc/source/_static/version_switcher.json:添加新版本、新开发版本,并将 "preferred": true 从旧版本转移到新版本。

更新依赖项的上限#

在主分支中,我们不设置上限,因为我们希望在那里测试新的发布版本或开发版本的依赖项。然而,在维护分支中,目标是能够创建可工作多年的发布版本。因此必须设置正确的上限。创建维护分支后必须更新以下位置:

  • pyproject.toml:所有构建时依赖项,以及支持的 Python

    和 NumPy 版本

  • scipy/__init__.py:用于 NumPy 版本检查

每个文件都有注释,描述如何设置正确的上限。

标记发布#

首先确保您已正确设置 GPG。有关签署发布标签的讨论,请参阅scipy/scipy#4919;如果您没有 GPG 密钥,请参阅https://keyring.debian.org/creating-key.html上的说明来创建。请注意,在某些平台上,使用 gpg2 而非 gpg 可能更合适,以便 gpg-agent 可以存储密码,正如scipy/scipy#10189中所讨论的那样。在远程准备发布时,可能需要在 ~/.gnupg/gpg-agent.conf 中设置 pinentry-mode loopback,否则使用 gpg2 将通过无法访问的图形密码提示进行。

为了让您的密钥更容易被识别为您本人,可以考虑将您的密钥发送到公共密钥服务器,使用以下命令:

gpg --send-keys <yourkeyid>

检查所有相关提交是否都在分支中。特别是,检查发布里程碑下的议题和 PR(scipy/scipy),带有“backport-candidate”标签的 PR,以及发布说明是否最新并包含在 HTML 文档中。

然后更新 pyproject.toml 中的 version,并使用类似 REL: set version to <version-number> 的消息提交更改。暂时不要将此提交推送到 SciPy 仓库。

最后,使用 git tag -s <v1.x.y> 在本地标记发布(-s 确保标签已签名)。如果偏好 gpg2,则 git config --global gpg.program gpg2 可能更合适。继续构建发布制品(下一节)。仅当您成功构建了 sdists 和文档后,才将发布提交推送到 scipy 仓库。然后继续构建 wheels。仅当所有 wheels 在 TravisCI 和 Appveyor 上成功构建后,才将发布标签推送到仓库(如果失败,您必须移动标签,这是不好的做法)。最后,在推送标签后,还要推送第二个提交,该提交会增加版本号并在 version: 后附加 .dev0,并将 ISRELEASED 再次设置为 False。这同样适用于新的发布候选版本,以及从发布候选版本切换到正式发布时移除 rc 后缀。

构建发布制品#

以下是为发布创建的完整制品列表:

  • sdist(scipy-x.y.y.tar.gz,用于 PyPI 和 GitHub Releases)

  • Windows, Linux 和 macOS 的二进制 wheels

  • 文档 (html)

  • 一个 README.txt 文件

  • 一个 Changelog 文件

运行 python -m build --sdist 生成 sdist(注意:我们仍然需要将其移入 CI 任务!),并通过在仓库根目录运行 python dev.py notes(带标签,请参阅 python dev.py notes --help)来构建 Changelog 和 README,它们最终位于 REPO_ROOT/release/。在本地创建签名标签后执行此操作。如果此操作顺利完成,请将发布提交(不是标签,请参阅上文)推送到 scipy 仓库。

要构建 wheels,请将包含文本 [wheel build] 的提交推送到用于当前发布的分支。这将触发所有所需 Python 版本和平台上的 cibuildwheel 构建。NumPy 和其他依赖项的适当版本限制应在分支后立即在 pyproject.toml 中更新。如果 wheel 构建揭示了需要在维护分支上通过反向移植修复的问题,您可以删除本地标签(例如 git tag -d v1.2.0rc1),然后从上面在新候选提交上重新开始标记。

cibuildwheel 基础设施会运行从构建的 wheels 中提取的测试,如果测试通过,则将 wheels 上传到 https://anaconda.org/multibuild-wheels-staging/scipy

您可以从那里下载它们,以便上传到 PyPI。这可以使用 tools/download-wheels.py 以自动化方式完成。

$ python tools/download-wheels.py 1.5.0rc1 -w REPO_ROOT/release/installers

在此之后,我们需要重新生成 README 文件,以便其中包含刚刚下载的 wheels 的 MD5 和 SHA256 校验和。再次运行 python dev.py notes

上传发布制品#

对于一个发布,目前有五个在线上传位置:

  • PyPI (sdist, wheels)

  • GitHub Releases (sdist, 发布说明, Changelog)

  • scipy.org(发布公告)

  • docs.scipy.org(html 文档)

PyPI

先上传 wheels,然后上传 sdist

twine upload REPO_ROOT/release/installers/*.whl
twine upload REPO_ROOT/release/installers/scipy-1.x.y.tar.gz

Github Releases

使用 scipy/scipy 上的 GUI 创建发布并上传所有发布制品。在此阶段,宜推送标签并在 GUI 中将新发布(候选)与此标签关联。例如,git push upstream v1.2.0rc1,其中 upstream 代表 scipy/scipy。检查之前的发布有助于准确确定 GUI 上传过程中应包含哪些制品。另外请注意,发布说明不会自动填充到 GitHub 上的发布描述中,并且一些手动格式化为 Markdown 可能有助于匹配网站上以前发布的格式。我们通常不在这些 GUI 描述中包含议题和拉取请求列表。

scipy.org

站点源代码位于 scipy/scipy.org。通过 PR 更新 content/en/news.md 中的新闻部分。这仅适用于正式发布,不适用于发布候选版本。

docs.scipy.org

首先在 scipy/doc/ 中运行 make dist 构建 scipy 文档。验证它们是否正常,然后使用 make upload USERNAME=rgommers RELEASE=0.19.0 将它们上传到文档服务器。请注意,需要文档服务器的 SSH 访问权限;如果您没有,请咨询 @pv(服务器管理员)、@tylerjereddy 或 @rgommers(可上传)。

网站本身的源代码维护在 scipy/docs.scipy.org 中。在 index.rst 的发布版本表中添加新的 SciPy 版本。推送该提交,然后执行 make upload USERNAME=yourusername。这仅适用于正式发布,不适用于发布候选版本。

注意

部署文档上的版本切换器在 version_switcher.json 的更改合并到 main 分支之前,不会将新发布视为稳定版本(参见gh-22305)。因此,将发布说明和版本切换器更改前向移植到 main 理想情况下应与新发布的文档部署同时进行。

总结#

https://discuss.scientific-python.org/c/announcements/ 发送发布公告。

对于 beta 和 rc 版本,请大家测试(运行 scipy 测试并针对自己的代码进行测试),并在 Github 或 Discourse 上报告问题。

最终发布完成后,将发布说明、构建脚本、tools/authors.py 中的作者姓名映射以及在维护分支上进行的任何其他更改移植到主分支。

通过编辑发布服务器上上传文档根文件夹中的运行时配置文件 try_examples.json 来启用交互式示例。必须从 ignore_patterns 列表中删除正则表达式模式 ".*"

$ ssh your-username@docs.scipy.org
$ cd /srv/docs_scipy_org/doc/scipy-1.13.1
$ vim try_examples.json  # edit the ignore list to remove: ".*"