贡献方式#

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

您可以通过多种方式做出贡献

  • 贡献新代码

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

  • 审查开放的拉取请求

  • 分类处理问题

  • 维护 scipy.org 网站

  • 论坛上回答问题和参与讨论。

贡献新代码#

如果您已经使用科学 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 pre-commit 钩子,可以检查您的每次提交是否符合规范的风格。通过在 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_funcmy_new_func可以放在/scipy/<subpackage>/下的现有文件或新文件中,其名称将添加到该文件中的__all__列表中(该列表列出了文件中的所有公共函数),然后这些公共函数将在/scipy/<subpackage>/__init__.py中导入。任何私有函数/类都应该在名称前加上下划线(_)。关于 SciPy 公共 API 的更详细描述,请参见SciPy API

一旦您认为您的代码已准备好包含在 SciPy 中,您可以在 Github 上发送一个拉取请求(PR)。我们在此不会详细介绍如何使用 git,这在Git 用于开发以及 Github 帮助页面上都有很好的描述。当您为新功能发送 PR 时,请务必在 scipy-dev 论坛上提及此事。这可以促使感兴趣的人帮助审查您的 PR。假设您之前已经就您的代码/功能的总体构想获得了积极反馈,那么代码审查的目的是确保代码正确、高效并满足上述要求。在许多情况下,代码审查进行得相对较快,但也有可能停滞不前。如果您已经解决了所有已给出的反馈,那么在(例如几周的合理时间过去后)再次在论坛上请求审查是完全可以的。一旦审查完成,该 PR 将合并到 SciPy 的“main”分支中。

以上描述了向 SciPy 添加代码的要求和流程。然而,它尚未回答决策是如何精确做出的问题。基本的答案是:决策由在论坛上选择参与讨论的每个人通过共识做出。这包括开发者、其他用户以及您自己。在讨论中争取共识很重要——SciPy 是一个由科学 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。与添加新代码不同,在论坛上讨论此事可能不是必需的——如果代码的旧行为明显不正确,没有人会反对修复它。可能需要为更改的行为添加一些警告或弃用消息。这应该是审查过程的一部分。

注意

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

审查拉取请求#

非常欢迎审查开放的拉取请求(PRs),这是帮助加快项目进展的宝贵方式。如果您在特定领域(例如“优化算法”或“特殊函数”)拥有专业知识/经验,那么审查该领域的 PR 尤其有价值——有时包含技术代码的 PR 由于缺乏合适的审查者而需要等待很长时间才能合并。

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

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

  • 此功能是否科学严谨?算法可能基于文献已知有效;否则,更仔细地检查其正确性很有价值。

  • 在所有条件下(例如空数组或 nan/inf 值等意外输入),预期行为是否清晰?

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

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

其他贡献方式#

除了编写代码之外,还有许多其他贡献方式。

分类处理问题(调查错误报告的有效性及可能采取的措施)也是一项有用的活动。SciPy 有数百个未解决的问题;关闭无效问题并正确标记有效问题(最好在评论中附上一些初步想法)有助于优先处理维护工作,并在处理现有函数或子包时轻松找到相关问题。要了解更多关于问题分类的信息,请参阅问题分类与整理

参与 scipy-user 和 scipy-dev 论坛上的讨论本身就是一种贡献。所有向这些列表提出问题或想法的人都希望得到回复,而撰写此类回复能使项目和社区更好地运作,并显得更受欢迎。

scipy.org 网站包含大量关于 SciPy 项目和 SciPy 社区的信息,并且总是需要新的帮助。网站的源代码位于其独立的仓库中:scipy/scipy.org

入门#

感谢您对为 SciPy 做出贡献的兴趣!如果您有兴趣贡献代码,我们希望您继续阅读SciPy 贡献者指南,以获取有关如何设置开发环境、实施改进以及提交您的第一个 PR 的详细信息!