为Astropy贡献代码,一个有效的例子

此示例基于修复 Issue 1761 从列表中 astropy issues on GitHub . 结果是 pull request 1917 .

问题标题是“len()不适用于坐标”,并描述“如果能够使用 len 在坐标数组上,以知道存在多少个坐标。”

选择这个特定的例子是因为它在GitHub中被标记为easy;似乎是开始的最佳地方!

在你开始之前

确保您有一个astropy的本地副本,如中所述 尝试开发版本 . 简而言之,输出 git remote -v ,在本地 astropy 应该是这样的:

astropy   git@github.com:astropy/astropy.git (fetch)
astropy   git@github.com:astropy/astropy.git (push)
your-user-name     git@github.com:your-user-name/astropy.git (fetch)
your-user-name     git@github.com:your-user-name/astropy.git (push)

的URL的精确形式 your-user-name 取决于使用GitHub设置的身份验证方法。

重要的一点是 astropy 应该指向官员 astropy 回购和 your-user-name 应该指向 your 副本 astropy 在吉瑟布上。

获取astropy的最新更新

本教程中的几个步骤只执行一个命令。它们分别被分解出来,以文字和代码来描述流程。

通知本地副本 astropy 关于开发版本的最新更改:

git fetch astropy --tags

设置独立的工作区

  • 做一个新的 git 解决此问题的分支并切换到分支:

    git checkout astropy/master -b fix-1761
    
  • 为这个修复创建一个Python环境并切换到该环境。下面的示例显示了Miniconda/Anaconda Python发行版中的必要步骤:

    conda create -n apy-1761 python=3.9 # replace 3.9 with desired version
    conda activate apy-1761
    

    如果您使用的是不同的分发,请参阅 Python虚拟环境 有关创建和激活新环境的说明。

  • 在此环境中安装我们的分支:

    pip install -e .[test]
    

您真的需要为每个修复设置单独的Python环境吗?不,但是您肯定希望有一个Python环境来进行代码贡献工作。创建新的环境很快,不占用太多空间,并且提供了一种使您的工作井然有序的方法。

如果安装失败,请尝试升级 pip 使用 pip install pip -U 命令。这也是保持 conda 通过运行更新 conda update conda -n base 当被要求这样做的时候;也许 git 也是。

请先测试一下

在天体物理学中测试的重要性怎么强调都不为过。测试是让你确信新代码做了它应该做的,并且不会破坏旧代码。

在进行任何更改之前,至少应该运行相关的测试,以确保Python环境设置正确。

第一个挑战是找出在哪里寻找相关的测试。 Issue 1761 是一个问题 coordinates 包,所以它的测试在 astropy/coordinates/tests . 其余的 astropy 具有类似的布局,如中所述 测试指南 .

使用以下命令在该目录中运行当前测试:

pytest astropy/coordinates/tests

如果您正在处理的错误涉及远程数据访问,则需要使用额外的标志来运行测试,即。, pytest ... --remote-data .

如果所有通过测试的bug都存在,则需要新的测试来暴露这个bug。

子包将其测试组织成多个测试模块;例如:

$ ls astropy/coordinates/tests
test_angles.py
test_angular_separation.py
test_api_ape5.py
test_arrays.py
...

Issue 1761 影响坐标数组,因此将新测试放入 test_arrays.py . 对于所有步骤,如有疑问,请在 astropy-dev mailing list .

此时的目标可能有点违反直觉:编写一个测试,我们知道当前代码将失败。此测试允许 astropy 以自动化的方式检查我们的修复是否真的起作用,并防止回归(即,确保将来对代码的更改不会破坏我们的修复)。

查看中的现有代码 test_arrays.py ,每个测试都是一个名称以开头的函数 test_ . 添加测试的适当位置是在文件中的最后一个测试函数之后。

给测试一个合理清晰的名称;例如。, test_array_len . 找出需要导入什么以及如何设置测试的最简单方法是查看其他测试。完整的测试在下面和 pull request 1917 .

编写测试,然后查看它是否如预期的那样工作;记住,在本例中,我们期望它能够正常工作 fail 没有补丁 pull request 1917 . 运行 pytest astropy/coordinates/tests/test_arrays.py 将给出预期的失败;输出的摘要是:

================= FAILURES =============================
______________ test_array_len __________________________

    def test_array_len():
        from .. import ICRS

        input_length = 5
        ra = np.linspace(0, 360, input_length)
        dec = np.linspace(0, 90, input_length)

        c = ICRS(ra, dec, unit=(u.degree, u.degree))

>       assert len(c) == input_length
E       TypeError: object of type 'ICRS' has no len()

astropy/coordinates/tests/test_arrays.py:291: TypeError

成功!

将此测试添加到本地 git 回购

保持 git 一次只专注于一个逻辑部分。我们刚刚编写的测试是一个逻辑变化,所以我们将提交它。如果愿意的话,您可以等待并将此测试与修复程序一起提交。

对于本教程,我们将单独提交测试。如果你不知道该做什么,就问吧 astropy-dev mailing list .

检查更改了什么

我们可以看到发生了什么变化 git status ::

$ git status
On branch fix-1761
Your branch is up-to-date with 'astropy/master'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   astropy/coordinates/tests/test_arrays.py

no changes added to commit (use "git add" and/or "git commit -a")

这里有两个信息:

  • 一个文件已更改;即。, astropy/coordinates/tests/test_arrays.py

  • 此文件尚未添加到git的临时区域,因此它列在下面 Changes not staged for commit .

使用 git diff 要查看所做的更改:

$ git diff
diff --git a/astropy/coordinates/tests/test_arrays.py b/astropy/coordinates/test
index 2785b59..7eecfbb 100644
--- a/astropy/coordinates/tests/test_arrays.py
+++ b/astropy/coordinates/tests/test_arrays.py
@@ -278,3 +278,14 @@ def test_array_indexing():
     assert c2.equinox == c1.equinox
     assert c3.equinox == c1.equinox
     assert c4.equinox == c1.equinox
+
+
+def test_array_len():
+    from .. import ICRS
+
+    input_length = 5
+    ra = np.linspace(0, 360, input_length)
+    dec = np.linspace(0, 90, input_length)
+
+    c = ICRS(ra, dec, unit=(u.degree, u.degree))
+
+    assert len(c) == input_length

git的图形界面使跟踪这些更改变得更加容易;请参阅 获取GitGUI(可选) 如果你感兴趣的话。

准备改变

git 要求您分两步添加更改:

  • git add ... ;这会将文件添加到准备提交时将添加到回购的项目列表中。

  • 提交更改 git commit ... ;这实际上增加了对回购的更改。

这些步骤可以合并到一个步骤中(不推荐);分两个步骤执行的好处是,撤消转移比提交更容易。我们稍后会看到, git status 甚至告诉你怎么做。

如果要同时在多个不同的地方进行更改,则转移非常方便。做你的第一个改变,准备它,然后做你的第二个改变和阶段。一旦所有的工作都准备好了,就把更改作为一次提交来提交。

在这种情况下,第一阶段的改变是:

git add astropy/coordinates/tests/test_arrays.py

您不会在命令行中注意到任何更改,但是 git status 会让你知道:

$ git status
On branch fix-1761
Your branch is up-to-date with 'astropy/master'.

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   astropy/coordinates/tests/test_arrays.py

注意 git 如果需要的话,包含取消暂存更改所需的命令。

提交您的更改

接下来,我们将提交不带修复程序的测试:

$ git commit -m "Add test for array coordinate length (issue #1761)"
[fix-1761 dd4ef8c] Add test for array coordinate length (issue #1761)
 1 file changed, 12 insertions(+)

提交消息应该简洁。包括GitHub问题号可以让GitHub自动创建指向相关问题的链接。

使用 git status 为了重温我们目前的状况:

$ git status
On branch fix-1761
Your branch is ahead of 'astropy/master' by 1 commit.
  (use "git push" to publish your local commits)

nothing to commit, working directory clean

换言之,我们已经更改了 astropy 但我们并没有将这些更改推送到我们的GitHub帐户。

解决问题

写代码

现在我们已经编写了一个测试,我们将解决这个问题。对修复程序的完整讨论超出了本教程的范围,但是修复程序是添加一个 __len__ 方法到 astropy.coordinates.SphericalCoordinatesBase 在里面 coordsystems.py (如果你试图寻找代码,代码已经被重构了)。所有的球面坐标系都继承自这个基类,并且正是这个基类实现了 __getitem__ 方法,该方法允许对坐标数组进行索引。

pull request 1917 查看对代码的更改。

测试您的更改

有几个级别需要测试:

  • 这段代码的改变是否使我们编写的测试成功了?运行检查 pytest astropy/coordinates/tests/test_arrays.py . 在这种情况下,是的!

  • 其余的坐标测试还通过吗?运行检查 pytest astropy/coordinates/ . 在这种情况下,是的,我们没有打破任何东西!

  • 所有的 Astropy 测试都成功了吗?运行检查 pytest 从顶级目录。这可能需要一段时间,这取决于系统的速度。又成功了!

备注

跳过或失败的测试是可以的。失败或错误是不好的。如果你被卡住了,继续问 astropy-dev mailing list 寻求帮助!

准备并提交您的更改

将文件添加到 git 回购分两步进行:阶段,然后提交。

要使其与我们上面所做的提交稍有不同,请确保您仍在顶级目录中,并检查 git status ::

$ git status
On branch fix-1761
Your branch is ahead of 'astropy/master' by 1 commit.
  (use "git push" to publish your local commits)

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   astropy/coordinates/coordsystems.py

no changes added to commit (use "git add" and/or "git commit -a")

请注意,无论您在哪个目录中(只要您位于repo中的某个目录中),git都知道发生了什么变化。

将更改分阶段:

git add astropy/coordinates/coordsystems.py

对于此提交,使用多行提交消息很有帮助,当接受此更改时,该消息将自动关闭GitHub上的问题。下面的代码片段在bash(以及类似的shell)中实现了这一点:

$ git commit -m"
> Add len() to coordinates
>
> Closes #1761"
[fix-1761 f196771] Add len() to coordinates
 1 file changed, 4 insertions(+)

多行提交消息的另一个选择是使用Git GUI或运行 git commit 没有一条消息可以被编辑提示。

当您使用 git log ::

Add len() to coordinates

Closes #1761

如果提交消息看起来不正确,请运行 git commit --amend . 如果您仍然遇到问题,请询问如何在 astropy-dev mailing list .

在这一点上,没有一个阿谀奉承的维护者对您的更改一无所知。

我们稍后会用一个“拉请求”来处理这个问题,但是首先,请看 停下来想想:还有什么测试或其他改变吗? .

停下来想想:还有什么测试或其他改变吗?

在这一点上暂停一下,回顾一下您所建议的更改是否已完成,这一点毫无坏处。在这种情况下,还可以包括更多的测试,例如:

  • len() 在一个坐标上调用 not 一个数组?

  • len() 当坐标是一个有一个条目的数组时工作?

这两个都在中提到 pull request 1917 ,所以检查它们也没什么坏处。在这种情况下,他们也提供了一个机会来说明 pytest 框架。

第二种情况比较简单,因此将按照我们上面使用的开发周期首先处理:

  • 改变 astropy/coordinates/tests/test_arrays.py

  • 测试更改

测试通过了;但是我们将实现对标量大小写的检查,而不是提交这一个更改。

我们可以想象两种不同的理想结果:

  • len(scalar_coordinate) 行为就像 len(scalar_angle) 抬起 TypeError 对于标量坐标。

  • len(scalar_coordinate) 返回1,因为有一个坐标。

如果你遇到这样的情况,不知道该怎么办,就问吧。最好在GitHub上的GitHub上询问您正在修复的问题。

或者,做出选择,并在GitHub上的pull请求中明确选择了什么以及为什么;下面给出了相关说明。

测试预期错误

在这种情况下,我们选择了提高 TypeError ,因为用户需要知道,如果以后尝试索引一个坐标,则他们创建的坐标将不会表现为一个坐标的数组。

这个 pytest 框架使得异常测试相对容易;您可以将预期失败的代码放在 with 块::

c = ICRS(0, 0, unit=(u.degree, u.degree))

with pytest.raises(TypeError):
    len(c)

可以添加这样的测试 test_array_len 在里面 test_arrays.py . 在你自己的工作中,如果你愿意,你也可以选择把它放到一个新的测试函数中。

旁白:Python课程——让其他人做你的工作

对这个问题的实际修复非常非常短。在 coordsystems.py ,添加了两行:

def __len__(self):
    return len(self.lonangle)

lonangle 包含 Angle 代表经度的s(有时是RA,有时是经度)。只要打个电话 len() 在数组中的一个角度上,您可以免费获得 Angle 类来处理标量的大小写。

在这里添加一个显式检查标量的情况,会有两个需要保持同步的东西:处理标量 Angle 以及坐标。

提交任何其他更改

对于需要修改的其他文件,继续遵循上面的开发周期,包括changelog(请参见 编辑变更日志 )和文档,根据需要:

  • 检查一下 all astropy 测试仍然通过;请参阅 测试您的更改

  • git status 看看需要上演和承诺什么

  • git add ... 准备改变

  • git commit ... 提交更改

  • git log 检查变更历史

这个 git 没有输出的命令是:

git status
git add astropy/coordinates/tests/test_arrays.py
git commit -m "Add tests of len() for scalar coordinate and length 1 coordinate"
git log

编辑变更日志

保持更改列表的最新状态几乎是不可能的,除非每个参与者在提出更改时进行适当的更新。

文件中有更改 CHANGES.rst 在顶层目录(目录 setup.py 是)。将更改放在与里程碑(也称为版本)匹配的列表下,该里程碑是由GitHub中的维护人员为该问题设置的。如果您在请求请求中提出一个新特性,您可能需要等待此更改,直到讨论了请求请求。

此问题已标记为 astropy 0.3.1,如下图所示,因此changelog条目出现在那里。

../../_images/milestone.png

入口 CHANGES.rst 应该总结一下你做了什么,包括拉取请求编号。对于编写变更日志条目,您不需要了解所使用的标记语言(尽管您可以在 Sphinx primer );查看其他条目并进行模拟。

对于这个问题,条目是以 - Implemented ::

astropy.coordinates
^^^^^^^^^^^^^^^^^^^

- Implemented ``len()`` for coordinate objects. [#1761]

以a开头的行 - 生成项目符号列表项,使其成为 astropy.coordinateslen() in double backtick使文本以等宽字体呈现。

将更改提交到更改.rst

你可以使用 git status 如上所述,或直接跳转到暂存和提交:

git add CHANGES.rst
git commit -m "Add changelog entry for 1761"

将您的更改推到GitHub astropy分支

使用此命令将本地更改推送到 astropy 在请求审阅更改之前在GitHub上:

git push your-user-name fix-1761

将更改作为请求请求提出

此阶段需要转到GitHub帐户并导航到 your 副本 astropy ;url将类似于 https://github.com/your-user-name/astropy .

到达后,从“分支”下拉列表中选择包含修复的分支:

../../_images/worked_example_switch_branch.png

选择正确的分支后,单击“Pull Request”按钮,如下所示:

../../_images/pull_button.png

给你的拉请求起个合理的名字。包括带有前导的问题编号 # 在拉取请求的描述中,以便创建到原始问题的链接,如中所述 astropy 的拉取请求模板。

请看 pull request 1917 对于本教程中演示的拉取请求。

根据需要修改和推动

您可能会被要求在拉取请求的讨论中进行更改。在本地副本中进行这些更改,将其提交到本地repo,并将其推送到GitHub。GitHub将自动更新您的请求。