贡献方式#

本文档旨在概述贡献 SciPy 的方式。它试图回答常见问题,并提供一些关于社区流程在实践中如何运作的见解。熟悉 SciPy 社区且经验丰富的 Python 编码人员可能希望直接跳到 SciPy 贡献者指南.

有很多方法可以贡献

  • 贡献新代码

  • 修复错误、改进文档和其他维护工作

  • 审查开放的拉取请求

  • 对问题进行分类

  • 参与 scipy.org 网站的工作

  • 回答问题并参与 scipy-dev 和 scipy-user 邮件列表.

贡献新代码#

如果您已经使用科学 Python 工具集一段时间了,您可能有一些代码,您认为“这对其他人也很有用”。也许将其贡献给 SciPy 或其他开源项目是一个好主意。那么第一个要问的问题是,这段代码应该放在哪里?这个问题在这里很难回答,所以我们从一个更具体的问题开始:*什么代码适合放入 SciPy?*几乎所有添加到 SciPy 的新代码都有一个共同点,即它可能在多个科学领域有用,并且符合现有 SciPy 子包的范围(参见 决定新功能)。原则上,也可以添加新的子包,但这远不常见。对于特定于单个应用程序的代码,可能存在可以使用该代码的现有项目。一些 SciKits (scikit-learnscikit-imagestatsmodels 等) 就是很好的例子;它们有更窄的关注点,因此比 SciPy 具有更多特定于领域的代码。

现在,如果您有希望包含在 SciPy 中的代码,您该怎么做呢?在检查您的代码是否可以在 SciPy 中以兼容的许可证分发后(参见 许可证注意事项),第一步是在 scipy-dev 邮件列表中讨论它。所有新功能以及对现有代码的更改都在那里进行讨论和决定。您可以在代码完成之前就开始讨论,而且可能应该这样做。请记住,为了添加到 SciPy,您的代码需要由其他人审查,因此请尝试在您编写代码时找到愿意审查您工作的人。

假设邮件列表上的讨论结果是积极的,并且您有一个函数或代码片段可以完成您需要它做的事情,接下来该怎么办?在将代码添加到 SciPy 之前,它至少必须具有良好的文档、单元测试、基准测试和正确的代码风格。

  1. 单元测试

    原则上,您应该努力创建测试所有新增代码的单元测试。这在一定程度上可以确保您的代码运行正确,即使在您自己没有的 Python 版本、硬件或操作系统上也是如此。有关如何编写单元测试的详细说明,请参见 测试指南,以及 在本地运行 SciPy 测试 文档说明了如何运行它们。

  2. 基准测试

    单元测试检查功能是否正确;基准测试衡量代码性能。并非所有现有的 SciPy 代码都有基准测试,但应该有:随着 SciPy 的发展,监控执行时间变得越来越重要,以便发现意外的回归。有关编写和运行基准测试的更多信息,请参见 使用 airspeed velocity 对 SciPy 进行基准测试

  3. 文档

    清晰完整 的文档对于用户能够找到和理解代码至关重要。单个函数和类的文档 - 包括至少基本描述、所有参数和返回值的类型和含义,以及 doctest 格式的用法示例 - 放入文档字符串中。这些文档字符串可以在解释器中读取,并编译成 HTML 和 pdf 格式的参考指南。关键(区域)功能的更高级别文档以教程格式和/或模块文档字符串提供。有关如何编写文档的指南,请参见 文档风格,以及 使用 Sphinx 在本地渲染文档 解释了如何预览文档,因为它将在线显示。

  4. 代码风格

    统一的代码风格使其他人更容易阅读您的代码。SciPy 遵循标准的 Python 风格指南,PEP8,除了推荐的最大行长为 88 个字符,而不是 PEP8 的 79 个字符。

    我们提供了一个 git 预提交钩子,可以检查您的每次提交是否符合正确的风格。从 SciPy 存储库的根目录运行以下命令安装它(一次)

    cp tools/pre-commit-hook.py .git/hooks/pre-commit
    

    或者,您可以手动运行 linter

    python dev.py lint
    

    大多数 IDE 和文本编辑器也具有可以帮助您遵循 PEP8 的设置,例如通过四个空格来转换制表符。更多信息请参见 PEP8 和 SciPy

一个 清单,包括这些和其他要求,在示例 开发工作流程 的末尾提供。

你可能还有另一个问题:**我的代码应该放在哪里?** 为了回答这个问题,了解 SciPy 公共 API(应用程序编程接口)的定义很有帮助。对于大多数模块,API 是两层深的,这意味着你的新函数应该以 scipy.subpackage.my_new_func 的形式出现。 my_new_func 可以放在 /scipy/<subpackage>/ 下的现有或新文件中,它的名称被添加到该文件中的 __all__ 列表中(该列表列出了文件中的所有公共函数),然后这些公共函数在 /scipy/<subpackage>/__init__.py 中被导入。任何私有函数/类在它们的名称中应该有一个前导下划线 (_)。关于 SciPy 公共 API 的更详细描述,请参见 SciPy API

当你认为你的代码已准备好包含在 SciPy 中时,你可以在 Github 上发送一个拉取请求 (PR)。我们不会详细介绍如何使用 git,这在 Git for developmentGithub 帮助页面 中有很好的描述。当你为新功能发送 PR 时,请务必在 scipy-dev 邮件列表中提及此事。这可以促使感兴趣的人帮助审查你的 PR。假设你之前已经对你的代码/功能的一般想法获得了积极的反馈,代码审查的目的是确保代码是正确、高效的,并且符合上述要求。在许多情况下,代码审查会很快完成,但也有可能停滞不前。如果你已经解决了所有已给出的反馈,在邮件列表中再次请求审查是完全可以的(在合理的时间内,比如几周后)。审查完成后,PR 将合并到 SciPy 的“main”分支中。

以上描述了向 SciPy 添加代码的要求和流程。但它并没有回答决策是如何做出的。基本答案是:决策是通过共识做出的,由所有选择参与邮件列表讨论的人做出。这包括开发人员、其他用户和您自己。在讨论中寻求共识很重要——SciPy 是一个由科学 Python 社区为科学 Python 社区而创建的项目。在极少数情况下,如果无法达成一致,则相关模块的维护者可以决定问题。

许可证注意事项#

我的代码是基于我在网上找到的现有 Matlab/R/… 代码,这可以吗?

这取决于。SciPy 在 BSD 许可证下发布,因此,如果您基于的代码也是 BSD 许可证或具有 BSD 兼容许可证(例如 MIT、PSF),那么就可以了。GPL 或 Apache 许可证的代码、没有明确许可证的代码、需要引用的代码或仅供学术用途的代码不能包含在 SciPy 中。因此,如果您复制了具有此类许可证的现有代码或将其直接翻译成 Python,则您的代码不能包含在内。如果您不确定,请在 scipy-dev 邮件列表 上询问。

为什么 SciPy 在 BSD 许可证下而不是 GPL 许可证下?

与 Python 一样,SciPy 使用“宽松”的开源许可证,允许专有重用。虽然这允许公司使用和修改软件而无需回馈任何东西,但人们认为更大的用户群会导致更多的贡献,而且公司通常会发布他们的修改,而无需被要求这样做。请参阅 John Hunter 的 BSD 论点

有关 SciPy 许可证的更多信息,请参阅 许可证

维护现有代码#

上一节专门讨论了向 SciPy 添加新功能。该讨论的大部分内容也适用于现有代码的维护。维护意味着修复错误、提高代码质量、更好地记录现有功能、添加缺少的单元测试、添加性能基准、保持构建脚本最新等。SciPy 问题列表 包含所有报告的错误、构建/文档问题等。修复问题有助于提高 SciPy 的整体质量,也是熟悉该项目的好方法。您可能还想修复错误,因为您遇到了错误,并且需要该功能正常工作。

上面关于代码风格和单元测试的讨论同样适用于错误修复。通常最好先编写一个单元测试来展示问题,即它应该通过但实际上没有通过。一旦你有了这个测试,你就可以修复代码,使测试通过。这应该足以发送一个针对此问题的 PR。与添加新代码不同,在邮件列表中讨论这个问题可能没有必要 - 如果代码的旧行为明显错误,没有人会反对修复它。可能需要为更改的行为添加一些警告或弃用消息。这应该作为审查过程的一部分。

注意

仅更改代码风格的拉取请求(PR),例如修复文件中的一些 PEP8 问题,是不鼓励的。此类 PR 通常不值得弄乱 git 注释历史记录,并且会占用审查者时间,而这些时间可能更好地用于其他方面。但是,作为功能更改的一部分而触及的代码的代码风格清理是可以的。

审查拉取请求#

审查开放的拉取请求(PR)非常受欢迎,也是帮助加快项目进展速度的一种宝贵方式。如果您在特定领域(例如“优化算法”或“特殊函数”)拥有特定知识/经验,那么审查该领域的 PR 特别有价值 - 有时具有技术代码的 PR 必须等待很长时间才能合并,因为缺乏合适的审查者。

我们鼓励每个人参与审查过程;这也是熟悉代码库的好方法。审查者应该问自己以下问题中的一些或全部

  • 此更改是否经过充分讨论(与新功能和现有行为的更改相关)?

  • 该功能在科学上是否合理?算法可能已知根据文献有效;否则,仔细查看正确性很有价值。

  • 在所有条件下(例如空数组或 nan/inf 值等意外输入)意图的行为是否明确?

  • 代码是否符合贡献新代码中概述的质量、测试和文档期望?

如果我们还不认识你,请考虑自我介绍。

其他贡献方式#

除了编写代码之外,还有很多方法可以做出贡献。

对问题进行分类(调查错误报告的有效性和可能采取的措施)也是一项有用的活动。SciPy 有数百个开放问题;关闭无效的问题并正确标记有效的问题(理想情况下在评论中添加一些初步想法)可以优先考虑维护工作,并在处理现有函数或子包时轻松找到相关问题。要详细了解问题分类,请参阅分类和整理问题

参与 scipy-user 和 scipy-dev 邮件列表 上的讨论本身就是一种贡献。每个在这些列表中写下问题或想法的人,都希望得到回复,而撰写这些回复可以让项目和社区运作得更好,并显得更加友好。

scipy.org 网站包含了关于 SciPy 项目和 SciPy 社区的很多信息,它总是需要新的力量。网站的源代码位于他们自己的独立仓库中:scipy/scipy.org

入门#

感谢您对 SciPy 的贡献!如果您有兴趣贡献代码,我们希望您能继续阅读 SciPy 贡献者指南,了解如何设置您的开发环境、实施您的改进以及提交您的第一个 PR!