如何为 NumPy 文档做贡献#

本指南将帮助您决定贡献什么以及如何将其提交到官方 NumPy 文档.

文档团队会议#

NumPy 社区已经设定了一个坚定目标,即改进其文档.我们定期在 Zoom 上举行文档会议(日期在 numpy-discussion mailing list 上公布),欢迎所有人参加.如果您有任何问题或需要有人指导您完成您的第一步,请联系我们 – 我们很乐意提供帮助.会议记录 on hackmd.io ,并存储在 NumPy Archive repository .

需要什么#

NumPy Documentation 包含了详细信息.API 参考文档直接从代码中的 docstrings 生成,文档被 built 时.尽管我们为暴露给用户的每个函数和类提供了几乎完整的参考文档,但对于其中一些函数和类,缺少使用示例.

我们缺少的是范围更广的文档 – 教程,操作指南和解释.报告缺陷是另一种贡献方式.我们将讨论这两种方式.

贡献修复#

我们很乐意听到并修复文档缺陷.但是,为了解决最大的问题,我们最终不得不推迟或忽略一些错误报告.以下是要解决的最佳缺陷.

最高优先级是技术上的不准确 – docstring 缺少参数,函数/参数/方法的错误描述等等.其他 “结构性” 缺陷(如断开的链接)也具有优先权.所有这些修复都易于确认和实施.如果您知道如何操作,您可以提交一个包含修复的 pull request (PR) ;否则请 open an issue .

拼写错误和笔误的优先级较低;我们欢迎您告知我们,但可能无法及时修复它们.这些也可以作为 pull request 或 issue 来处理.

明显的措辞错误(例如遗漏了 “not”)属于拼写错误类别,但其他改写 – 即使是为了语法 – 也需要进行判断,这提高了门槛.首先通过提出 issue 来测试一下.

一些函数/对象,如 numpy.ndarray.transpose, numpy.array 等,在 C 扩展模块中定义,其 docstring 在 _add_newdocs.py 中单独定义

贡献新页面#

您在使用我们的文档时的挫折感是我们修复需求的最佳指南.

如果您编写一个缺失的文档,您就加入了开源的前线,但仅仅让我们知道缺少什么也是一种有意义的贡献.如果您想编写一个文档,请在 mailing list 中表达您的想法,以获得更多想法和反馈.如果您想提醒我们注意一个空白,请 open an issue .有关示例,请参见 this issue .

如果您正在寻找主题,我们正式的文档路线图是一个 NumPy 增强提案 (NEP), NEP 44 — Restructuring the NumPy documentation .它确定了我们的文档需要帮助的领域,并列出了我们希望看到的一些补充内容,包括 Jupyter notebooks .

文档框架#

有一些用于编写有用文档的公式,四个公式几乎涵盖了所有内容.之所以有四个公式,是因为有四种文档类别 – tutorial , how-to guide , explanationreference .文档以这种方式划分的洞察力属于 Daniele Procida 和他的 Diátaxis Framework .当您开始或提议一个文档时,请记住它将是这些类型中的哪一种.

NumPy 教程#

除了作为 NumPy 源代码树一部分的文档之外,您还可以以 Jupyter Notebook 格式将内容提交到 NumPy Tutorials 页面.这组教程和教育材料旨在为 NumPy 项目提供高质量的资源,既用于自学,也用于课堂教学.这些资源在一个单独的 GitHub 仓库中开发, numpy-tutorials ,您可以在其中查看现有的 notebook,打开 issue 以建议新主题或将您自己的教程作为 pull request 提交.

更多贡献方式#

不必担心英语不是你的母语,或者你只能写出一个粗略的草稿.开源是一项社区工作.尽你所能–我们会帮你解决问题.

图像和真实生活数据使文本更具吸引力和力量,但请确保你使用的内容已获得适当的许可并且可用.同样,即使是艺术作品的粗略想法也可以由其他人润色.

目前,NumPy 唯一接受的数据格式是其他 Python 科学库(如 pandas,SciPy 或 Matplotlib)也使用的格式.我们正在开发一个软件包来接受更多格式;请联系我们了解详情.

NumPy 文档保存在源代码树中.要将你的文档放入 docbase 中,你必须下载该树, build it ,并提交 pull request.如果你不熟悉 GitHub 和 pull request,请查看我们的 Contributor Guide .

我们的标记语言是 reStructuredText (rST),它比 Markdown 更复杂.Sphinx 是许多 Python 项目用于构建和链接项目文档的工具,它将 rST 转换为 HTML 和其他格式.有关 rST 的更多信息,请参阅 Quick reStructuredText GuidereStructuredText Primer

间接贡献#

如果你遇到任何可以作为 NumPy 文档的有用补充的外部材料,请通过 opening an issue 告知我们.

你不必直接在此处做出贡献才能为 NumPy 做出贡献.如果你在你的博客上写一篇教程,创建一个 YouTube 视频,或者在 Stack Overflow 和其他网站上回答问题,你就已经做出了贡献.

文档风格#

用户文档#

  • 一般来说,我们遵循 Google developer documentation style guide 作为用户指南的风格.

  • NumPy 风格适用于以下情况:

    • Google 没有指导,或者

    • 我们不希望使用 Google 风格

    我们目前的规则:

    • 我们将 index 复数化为 indices 而不是 indexes ,遵循 numpy.indices 的先例.

    • 为了保持一致性,我们也将 matrix 复数化为 matrices.

  • NumPy 或 Google 规则未能充分解决的语法问题,由最新版本的 Chicago Manual of Style 中"语法和用法"部分决定.

  • 我们欢迎你 alerted 我们应该添加到 NumPy 样式规则中的案例.

Docstrings#

当将 Sphinx 与 NumPy 约定结合使用时,您应该使用 numpydoc 扩展,以便正确处理您的 docstrings.例如,Sphinx 将从您的 docstring 中提取 Parameters 部分并将其转换为字段列表.使用 numpydoc 还可以避免普通的 Sphinx 在遇到 NumPy docstring 约定(如 sphinx 不希望在 docstrings 中找到的节头(例如 ------------- ))时产生的 reStructuredText 错误.

它可从以下位置获得:

请注意,对于 NumPy 中的文档,不必在示例的开头执行 import numpy as np .

请使用 numpydoc formatting standard ,如他们的 example 中所示.

记录 C/C++ 代码#

NumPy 使用 Doxygen 解析特殊格式的 C/C++ 注释块.这会生成 XML 文件,然后 Breathe 将其转换为 RST,供 Sphinx 使用.

完成文档编制过程需要三个步骤:

1. 编写注释块#

虽然仍然没有设置要遵循的注释样式,但 Javadoc 比其他样式更可取,因为它与当前现有的未索引注释块相似.

备注

请参阅 “Documenting the code” .

这是 Javadoc 样式的外观:

/**
 * This a simple brief.
 *
 * And the details goes here.
 * Multi lines are welcome.
 *
 * @param  num  leave a comment for parameter num.
 * @param  str  leave a comment for the second parameter.
 * @return      leave a comment for the returned value.
 */
int doxy_javadoc_example(int num, const char *str);

这是它的渲染方式:

警告

doxygenfunction: Cannot find file: /mnt/hgfs/github/numpy-2.3.0/doc/build/doxygen/xml/index.xml

对于单行注释,你可以使用三个正斜杠.例如:

/**
 *  Template to represent limbo numbers.
 *
 *  Specializations for integer types that are part of nowhere.
 *  It doesn't support with any real types.
 *
 *  @param Tp Type of the integer. Required to be an integer type.
 *  @param N  Number of elements.
*/
template<typename Tp, std::size_t N>
class DoxyLimbo {
 public:
    /// Default constructor. Initialize nothing.
    DoxyLimbo();
    /// Set Default behavior for copy the limbo.
    DoxyLimbo(const DoxyLimbo<Tp, N> &l);
    /// Returns the raw data for the limbo.
    const Tp *data();
 protected:
    Tp p_data[N]; ///< Example for inline comment.
};

这是它的渲染方式:

警告

doxygenclass: Cannot find file: /mnt/hgfs/github/numpy-2.3.0/doc/build/doxygen/xml/index.xml

常用的 Doxygen 标签:#

备注

更多标签/命令,请查看 https://www.doxygen.nl/manual/commands.html

@brief

开始一个段落,作为简要描述.默认情况下,文档块的第一句话会自动被视为简要描述,因为选项 JAVADOC_AUTOBRIEF 在 Doxygen 配置中已启用.

@details

就像 @brief 开始一个简要描述一样, @details 开始详细描述.你也可以开始一个新的段落(空行),那么不需要 @details 命令.

@param

为一个函数参数开始参数描述,参数名为 <parameter-name>,后跟参数的描述.会检查参数是否存在,如果此参数(或任何其他参数)的文档缺失或未出现在函数声明或定义中,则会发出警告.

@return

为一个函数开始返回值描述.多个相邻的 @return 命令将合并为一个段落.当遇到空行或其他分节命令时, @return 描述结束.

@code/@endcode

开始/结束代码块.代码块的处理方式与普通文本不同.它被解释为源代码.

@rst/@endrst

开始/结束 reST 标记块.

示例#

请看下面的例子:

/**
 * A comment block contains reST markup.
 * @rst
 * .. note::
 *
 *   Thanks to Breathe_, we were able to bring it to Doxygen_
 *
 * Some code example::
 *
 *   int example(int x) {
 *       return x * 2;
 *   }
 * @endrst
 */
void doxy_reST_example(void);

这是它的渲染方式:

警告

doxygenfunction: Cannot find file: /mnt/hgfs/github/numpy-2.3.0/doc/build/doxygen/xml/index.xml

2. 喂养 Doxygen#

并非所有头文件都会自动收集.你必须在 Doxygen 的子配置文件中添加所需的 C/C++ 头文件路径.

子配置文件具有唯一的名称 .doxyfile ,通常可以在包含文档化头文件的目录附近找到.如果头文件附近(2 层深度)没有配置文件,则需要创建一个新配置文件.

子配置文件可以接受任何 Doxygen configuration options ,但不要覆盖或重新初始化任何配置选项,而只使用连接运算符 “+=”.例如:

# to specify certain headers
INPUT += @CUR_DIR/header1.h \
         @CUR_DIR/header2.h
# to add all headers in certain path
INPUT += @CUR_DIR/to/headers
# to define certain macros
PREDEFINED += C_MACRO(X)=X
# to enable certain branches
PREDEFINED += NPY_HAVE_FEATURE \
              NPY_HAVE_FEATURE2

备注

@CUR_DIR 是一个模板常量,返回子配置文件的当前目录路径.

3. 包含指令#

Breathe 提供了各种自定义指令,允许将 Doxygen 生成的文档转换为 reST 文件.

备注

更多信息,请查看 “Directives & Config Variables

常用指令:#

doxygenfunction

此指令为单个函数生成适当的输出.函数名称在项目中必须是唯一的.

.. doxygenfunction:: <function name>
    :outline:
    :no-link:

查看 example 以查看其运行效果.

doxygenclass

此指令为单个类生成适当的输出.它采用标准项目,路径,轮廓和无链接选项,以及成员,受保护成员,私有成员,未文档化成员,成员组和仅成员选项:

.. doxygenclass:: <class name>
   :members: [...]
   :protected-members:
   :private-members:
   :undoc-members:
   :membergroups: ...
   :members-only:
   :outline:
   :no-link:

查看 doxygenclass documentation 了解更多详情并查看其运行效果.

doxygennamespace

此指令为命名空间的内容生成适当的输出.它采用标准项目,路径,轮廓和无链接选项,以及仅内容,成员,受保护成员,私有成员和未文档化成员选项.要引用嵌套命名空间,必须提供完整的命名空间路径,例如 foo::bar 表示 foo 命名空间内的 bar 命名空间.

.. doxygennamespace:: <namespace>
   :content-only:
   :outline:
   :members:
   :protected-members:
   :private-members:
   :undoc-members:
   :no-link:

查看 doxygennamespace documentation 了解更多详情并查看其运行效果.

doxygengroup

此指令为 Doxygen 组的内容生成适当的输出.Doxygen 组可以使用源代码注释中的特定 Doxygen 标记声明,如 Doxygen grouping documentation 中所述.

它采用标准项目,路径,轮廓和无链接选项,以及仅内容,成员,受保护成员,私有成员和未文档化成员选项.

.. doxygengroup:: <group name>
   :content-only:
   :outline:
   :members:
   :protected-members:
   :private-members:
   :undoc-members:
   :no-link:
   :inner:

请查看 doxygengroup documentation 以获取更多详细信息并查看其运行情况.

遗留指令#

如果一个函数,模块或 API 处于遗留模式,这意味着它被保留下来是为了向后兼容,但不建议在新代码中使用,您可以使用 .. legacy:: 指令.

默认情况下,如果使用时不带任何参数,遗留指令将生成以下输出:

遗留

此子模块被认为是遗留的,将不再接收更新.这也可能意味着它将在未来的 NumPy 版本中被删除.

我们强烈建议您也添加自定义消息,例如替换旧 API 的新 API:

.. legacy::

   For more details, see :ref:`distutils-status-migration`.

此消息将附加到默认消息,并将创建以下输出:

遗留

此子模块被认为是遗留的,将不再接收更新.这也可能意味着它将在未来的 NumPy 版本中被删除. 有关更多详细信息,请参见 numpy.distutils 的状态和迁移建议 .

最后,如果您想提及一个函数,方法(或任何自定义对象)而不是一个子模块,您可以使用一个可选参数:

.. legacy:: function

这将创建以下输出:

遗留

此函数被认为是遗留的,将不再接收更新.这也可能意味着它将在未来的 NumPy 版本中被删除.

文档阅读#

  • 技术作者的领先组织 Write the Docs 举办会议,提供学习资源并运行 Slack 频道.

  • “每个工程师也是一名作者,” Google 的 collection of technical writing resources 说道,其中包括面向开发人员的文档规划和写作的免费在线课程.

  • Software Carpentry’s 的使命是向研究人员教授软件. 除了托管课程外,该网站还解释了如何有效地表达想法.