贡献给Pyomo

我们欢迎所有贡献,包括错误修复、功能增强和文档改进。Pyomo通过GitHub拉取请求(PRs)管理源代码贡献。

贡献要求

一个PR应该是一组相关的更改。对于大规模的非功能性更改(例如PEP8、注释)的PR应与功能性更改分开。这简化了审查过程,并确保功能性更改不会被大量的非功能性更改所掩盖。

我们不使用 squash 和 merge 来处理 PR,因此您分支中的所有提交都会出现在主历史记录中。除了详细记录的 PR 描述外,我们还鼓励使用描述性提交消息进行模块化/有针对性的提交。

编码标准

  • 必填项:black

  • 不使用 __author__

  • pyomo.contrib 中:贡献维护者的联系信息(例如 Github ID)应包含在 Sphinx 文档中

Pyomo的GitHub Actions工作流程的第一步是运行 black 和一个 拼写检查器 以确保遵守样式指南并尽量减少拼写错误。在打开拉取请求之前,请运行:

 # Auto-apply correct formatting
pip install black
black -S -C <path> --exclude examples/pyomobook/python-ch/BadIndent.py
# Find typos in files
conda install typos
typos --config .github/workflows/typos.toml <path>

如果拼写检查器对一个拼写正确的单词返回失败, 请将该单词添加到.github/workflows/typos.toml文件中。

在线Pyomo文档是使用Sphinx生成的,并启用了napoleon扩展。对于API文档,我们使用其中一种支持的文档字符串样式,但我们更倾向于使用NumPy标准。无论你选择哪种样式,我们要求文档字符串必须符合以下要求:

  • Modules

  • 公共和私有类

  • 公共和私有函数

我们也鼓励您包含示例,特别是对于新功能和pyomo.contrib的贡献。

测试

Pyomo 使用 unittestpytestGitHub Actions、 和 Jenkins 进行测试和持续集成。提交的代码应包括测试,以验证其结果和/或效果的有效性。单元测试是首选,但我们也接受集成测试。我们要求至少覆盖 PR 中修改的代码行的 70%,并希望覆盖率接近 90%。我们还要求所有测试在 PR 合并之前通过。

注意

如果您在拉取请求中遇到测试无法通过的问题,请标记任何核心开发人员以寻求帮助。

Pyomo 主分支提供了一个 Github Actions 工作流(配置在 .github/ 目录中),该工作流将测试推送到分支的任何更改,使用包括多个虚拟机(ubuntumac-oswindows)和多个 Python 版本的完整测试套件的一个子集。对于现有的 fork,请将你的 fork(和分支)与 Pyomo 的主分支进行获取和合并。对于新的 fork,你需要在 fork 的“Actions”选项卡中启用 GitHub Actions。这将使测试在每次推送到你的 fork 时自动运行。

在开发周期的任何阶段,可以通过在PR标题的开头包含“[WIP]”来打开一个“进行中”的拉取请求。任何标记为“[WIP]”或草稿的拉取请求将不会被核心开发团队审查或合并。然而,任何长时间未进行积极开发的“[WIP]”拉取请求可能会被标记为“过时”并关闭。

注意

草稿和进行中的拉取请求将不会触发测试。这是我们为了减少CI积压所做的努力。请使用提供的分支测试套件来评估/测试草稿功能。

Python 版本支持

根据政策,Pyomo 支持并测试当前支持的 Python 版本,如Python 版本状态所示。除非另有说明,否则预计所有受支持和测试的 Python 版本都将通过测试。

在Python次要版本的生命周期结束后,我们将在第一个Pyomo发布时移除对该Python版本的测试和支持。

这也将导致Pyomo次要版本的提升。

例如,假设Python 3.A被宣布为生命周期结束,而Pyomo处于版本6.3.Y。在Pyomo 6.3.(Y+1)发布后,Python 3.A将被移除,下一个Pyomo版本将是6.4.0。

处理分支和分支

所有的Pyomo开发都应该在Pyomo仓库的分支上进行。为了分叉Pyomo仓库,请访问 https://github.com/Pyomo/pyomo,点击右上角的“Fork”按钮,并按照指示操作。

本节讨论了两种推荐的向Pyomo贡献拉取请求的工作流程。第一种工作流程,标记为 使用我的分叉和GitHub在线UI, 不需要使用“远程”,并建议使用GitHub在线UI更新您的分叉。第二种工作流程,标记为 使用远程和git命令行,概述了一个为您的分叉和主Pyomo仓库定义单独远程的过程。

更多关于git的信息可以在 https://git-scm.com/book/en/v2找到。第2.5节包含了关于远程操作的信息。

使用我的分支和GitHub在线界面

在创建你的分支(按照上述说明)之后,你可以使用以下命令克隆你的仓库分支

git clone https://github.com/<username>/pyomo.git

对于新开发,我们强烈建议在功能分支上工作。当您有一个新功能要实现时,请使用以下内容创建分支。

cd pyomo/     # to make sure you are in the folder managed by git
git branch <branch_name>
git checkout <branch_name>

现在可以进行开发了。当你准备好时,将你所做的任何更改提交到本地仓库。这可以通过为功能开发中的不同任务提供信息丰富的提交消息来多次完成。

git add <filename>
git status  # to check that you have added the correct files
git commit -m 'informative commit message to describe changes'

为了将本地分支的更改推送到你fork的分支上,请使用

git push origin <branch_name>

当你完成所有更改并准备进行拉取请求时,请确保所有更改都已推送到你分叉上的分支

  • 访问 https://github.com/<用户名>/pyomo。

  • 在仓库中的文件和目录列表上方,你应该看到一个标有“Branch: main”的按钮。点击这个按钮,并选择正确的分支。

  • 点击“Branch: ”按钮右侧的“New pull request”按钮。

  • 填写拉取请求模板并点击绿色的“创建拉取请求”按钮。

在开发过程中,有时您可能希望将Pyomo主开发分支的更改合并到您分叉的功能分支以及本地克隆的存储库中。

使用GitHub UI将Pyomo主分支合并到你的分支

要更新你的fork,实际上你将会从Pyomo主仓库合并一个pull-request到你的fork中。

  • 访问 https://github.com/Pyomo/pyomo.

  • 点击文件列表上方的“New pull request”按钮。

  • 您将看到标题“比较更改”,下面有一些小字写着“比较分支、提交、标签等之间的更改。如果需要,您还可以比较不同分叉之间的更改。”点击最后一部分:“比较不同分叉”。

  • 你现在应该会看到下面有四个按钮:“基础仓库:Pyomo/pyomo”,“基础:main”,“头部仓库:Pyomo/pyomo”,以及“比较:main”。点击最左边的按钮并选择“<用户名>/Pyomo”。

  • 然后点击从左数第二个按钮,并选择你想要将Pyomo主分支合并到的分支。此时四个按钮应该显示为:“基础仓库:<用户名>/pyomo”,“基础:<分支名称>”,“头仓库:Pyomo/pyomo”,以及“比较:main”。这将设置你从Pyomo的主分支合并拉取请求到你fork的<分支名称>分支。

  • 你现在还应该看到一个拉取请求模板。如果你填写了拉取请求模板并点击“创建拉取请求”,这将创建一个拉取请求,该请求将使用Pyomo主分支中的任何更改来更新你的分支和分支。

  • 然后,您可以通过点击GitHub上您的分叉中的绿色“合并拉取请求”按钮来合并拉取请求。

使用远程仓库和git命令行

在您创建了您的fork之后,您可以克隆该fork并设置git 'remotes',以便您可以从不同的远程仓库合并更改(或将更改合并到不同的远程仓库)。下面,我们提供了一组建议,但当然,您也可以采用其他有效的GitHub工作流程。

以下命令展示了如何克隆你的分支并设置两个远程仓库,一个用于你的分支,另一个用于主 Pyomo 仓库。

git clone https://github.com/<username>/pyomo.git
git remote rename origin my-fork
git remote add head-pyomo https://github.com/pyomo/pyomo.git

注意,您可以使用以下命令查看远程仓库列表

git remote -v

创建本地分支和执行本地提交的命令与上一节中列出的命令相同。以下是一些基于此多远程设置的常见任务。

如果您有已经提交到本地特性分支()的更改,您可以使用以下命令将这些更改推送到您 fork 的分支上,

git push my-fork <branch_name>

为了使用Pyomo仓库分支的更改更新本地分支,

git checkout <branch_to_update>
git fetch head-pyomo
git merge head-pyomo/<branch_to_update_from> --ff-only

“--ff-only” 仅在合并可以通过快进完成时允许合并。如果您不需要快进,可以省略此选项。最常见的具体示例是

git checkout main
git fetch head-pyomo
git merge head-pyomo/main --ff-only

上述命令将更改从主分支的头部Pyomo仓库拉取到本地克隆的主分支。要将这些更改推送到您分叉的主分支,

git push my-fork main

设置您的开发环境

克隆你的fork后,你将需要从源代码安装Pyomo。

步骤1(推荐):创建一个新的conda环境。

conda create --name pyomodev

您可以根据需要更改环境名称pyomodev。 然后激活环境:

conda activate pyomodev

步骤2(可选):安装PyUtilib

在Pyomo 6.0.0中,对PyUtilib的硬依赖已被移除。对于与pyomo.dataportal.plugins.sheet相关的任何代码,仍然存在软依赖。

如果你的贡献需要PyUtilib,你可能需要PyUtilib的主分支来进行贡献。在一个新目录中克隆仓库的副本:

git clone https://github.com/PyUtilib/pyutilib

然后在包含 PyUtilib 克隆的目录中运行:

python setup.py develop

步骤3:安装Pyomo

最后,移动到包含您的Pyomo分叉克隆的目录并运行:

python setup.py develop

这些命令将克隆的代码注册到活动的Python环境中(pyomodev)。这样,您对pyomo源代码的更改将自动被活动环境使用。您可以创建另一个conda环境以切换到pyomo的其他版本(例如,稳定版)。

审查流程

在PR(拉取请求)被打开后,它将由核心开发团队的至少两名成员进行审查。核心开发团队由任何对Pyomo仓库具有写权限的人组成。由核心开发者打开的拉取请求只需要一次审查。审查者将决定他们认为PR是否应该合并,或者是否需要更多的更改。

评审者寻找:

  • pyomo.contrib之外:代码的严谨性和标准,边缘情况,副作用等。

  • pyomo.contrib 内部:代码没有“明显”的问题

  • 文档和测试

核心开发团队会尽力及时审查拉取请求,但我们不保证审查的时间框架。此外,拉取请求可能不会按照它们被打开的先后顺序进行审查。

贡献代码的位置

为了向Pyomo做出贡献,您首先需要分叉Pyomo的git仓库。接下来,您应该在您的分叉上创建一个专门用于开发您感兴趣的新功能或错误修复的分支。一旦您检出这个分支,您就可以开始编码了。对现有Pyomo功能的错误修复和小幅增强应该在Pyomo代码库的适当文件中进行。基于Pyomo的新示例、功能和包应该放在pyomo.contrib中。点击下面的链接,了解pyomo.contrib是否适合您的代码。

pyomo.contrib

Pyomo 使用 pyomo.contrib 包来促进包含增强 Pyomo 核心功能的第三方贡献。 有两种方式可以使用 pyomo.contrib 来集成第三方包:

  • pyomo.contrib can provide wrappers for separate Python packages, thereby

    允许这些包作为pyomo的子包导入。

  • pyomo.contrib can include contributed packages that are developed and

    由Pyomo开发团队之外的人员维护。

在Pyomo源代码树中包含contrib包提供了一种方便的机制,用于定义用户可以可选部署的新功能。我们期望这种机制包括Pyomo扩展和实验性建模能力。然而,contrib包被视为可选包,不由Pyomo开发团队维护。因此,代码贡献者有责任保持这些包的最新状态。

贡献包的贡献将被视为拉取请求,将由Pyomo开发团队进行审查。具体来说,此次审查将考虑所提议功能的适用性,是否有测试来检查代码的执行,以及是否有文档来描述该功能。贡献包将与Pyomo一起进行测试。如果出现测试失败,这些包将被禁用,并将创建一个问题来解决这些测试失败。

Pyomo中的贡献包

第三方贡献可以直接包含在pyomo.contrib包中。pyomo/contrib/example包提供了一个如何实现这一点的示例,包括插件和包测试的目录。例如,这个包可以作为pyomo.contrib的子包导入:

from pyomo.environ import *
from pyomo.contrib.example import a

# Print the value of 'a' defined by this package
print(a)

尽管pyomo.contrib.example包含在Pyomo源代码树中,但它被视为一个可选包。Pyomo将尝试导入这个包,但如果导入失败,Pyomo将默默地忽略它。否则,这个pyomo包将像其他任何包一样被对待。具体来说:

  • 当加载pyomo.environ时,此包中定义的插件类会被加载。

  • 此包中的测试与其他Pyomo测试一起运行。