如何为 NumPy 文档贡献#

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

文档团队会议#

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

需要什么#

NumPy 文档涵盖了详细信息。API 参考文档在文档构建时直接从代码中的 docstrings 生成。尽管我们为每个暴露给用户的函数和类提供了大部分完整的参考文档,但其中一些缺乏使用示例。

我们缺乏的是更广泛范围的文档——教程、操作指南和解释。报告缺陷是另一种贡献方式。我们将讨论这两种方式。

贡献修复#

我们渴望了解并修复文档缺陷。但为了解决最大的问题,我们最终不得不推迟或忽略一些错误报告。以下是需要优先处理的缺陷。

技术不准确性优先——例如缺少参数的 docstring、函数/参数/方法的错误描述等等。其他“结构性”缺陷,如断开的链接,也得到优先处理。所有这些修复都易于确认并实施。如果您知道如何操作,可以提交一个带有修复的拉取请求 (PR);否则,请开启一个问题

拼写错误和错别字优先级较低;我们欢迎报告它们,但可能无法及时修复。这些也可以通过拉取请求或问题来处理。

明显的措辞错误(例如漏掉“不”)属于拼写错误类别,但其他改写——即使是语法改写——也需要判断,这提高了门槛。先通过将修复作为问题提出,以探探水深。

某些 C 扩展模块中定义的函数/对象,如 numpy.ndarray.transpose、numpy.array 等,其 docstrings 分别在 _add_newdocs.py 中定义。

贡献新页面#

您在使用我们文档时遇到的挫折是我们需要修复内容的最佳指南。

如果您编写了缺失的文档,您就加入了开源的前线,但仅仅让我们知道缺少什么也是一项有意义的贡献。如果您想撰写文档,请先在邮件列表上分享您的想法,以获取更多想法和反馈。如果您想提醒我们存在空白,请开启一个问题。请参阅此问题以获取示例。

如果您正在寻找主题,我们正式的文档路线图是《NumPy 改进提案 (NEP)》,即NEP 44 — 重构 NumPy 文档。它指出了我们的文档需要帮助的领域,并列出了我们希望看到的一些新增内容,包括Jupyter notebooks

文档框架#

编写有用文档有其规律,四种规律几乎涵盖了所有内容。之所以有四种规律,是因为文档分为四类——教程操作指南解释参考。文档如此分类的见解源于 Daniele Procida 及其 Diátaxis 框架。当您开始或提议编写文档时,请务必明确它属于哪种类型。

NumPy 教程#

除了作为 NumPy 源代码树一部分的文档外,您还可以以 Jupyter Notebook 格式提交内容到 NumPy 教程页面。这套教程和教育材料旨在由 NumPy 项目提供高质量资源,既可用于自学,也可用于教学。这些资源在单独的 GitHub 仓库 numpy-tutorials 中开发,您可以在其中查看现有笔记本,开启问题以建议新主题,或以拉取请求的形式提交您自己的教程。

关于贡献的更多信息#

如果英语不是您的母语,或者您只能提供粗略的草稿,请不要担心。开源是一个社区协作的工作。尽力而为——我们会帮助解决问题。

图片和真实数据使文本更具吸引力和影响力,但请确保您使用的内容已获得适当许可并可用。同样,即使是粗略的艺术构思也可以由其他人润色。

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

NumPy 文档保存在源代码树中。要将您的文档添加到文档库中,您必须下载代码树,构建它,然后提交拉取请求。如果您不熟悉 GitHub 和拉取请求,请查阅我们的贡献者指南

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

间接贡献#

如果您遇到对 NumPy 文档有用的外部材料,请通过开启一个问题告知我们。

您不必在这里贡献才能为 NumPy 贡献。如果您在博客上撰写教程、制作 YouTube 视频或在 Stack Overflow 和其他网站上回答问题,您就做出了贡献。

文档风格#

用户文档#

  • 通常,我们遵循 Google 开发者文档风格指南来编写用户指南。

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

    • Google 没有提供指导,或者

    • 我们倾向于不使用 Google 风格

    我们当前的规则

    • 我们遵循 numpy.indices 的先例,将 index 的复数形式用作 indices 而不是 indexes

    • 为保持一致性,我们也将 matrix 的复数形式用作 matrices

  • NumPy 或 Google 规则未能充分解决的语法问题,将由最新版《芝加哥风格手册》中“语法和用法”一节决定。

  • 我们欢迎告知我们应添加到 NumPy 风格规则中的案例。

Docstrings#

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

可从以下位置获取

请注意,在 NumPy 内部的文档中,示例开头不需要 import numpy as np

请使用 numpydoc格式标准,如其示例所示。

C/C++ 代码文档#

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

文档过程分三步完成:

1. 编写注释块#

虽然目前还没有设定统一的注释风格,但由于与现有非索引注释块的相似性,Javadoc 风格比其他风格更受欢迎。

注意

请参阅“文档化代码”

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: 无法在项目“numpy”的 doxygen xml 输出中从目录: ../build/doxygen/xml 解析函数“doxy_javadoc_example”及参数 None。可能的匹配项

- int doxy_javadoc_example(int num, const char *str)
- int doxy_javadoc_example(int num, const char *str)
- int doxy_javadoc_example(int num, const char *str)

对于行注释,您可以使用三重斜杠。例如:

/**
 *  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.
};

渲染效果如下:

template<typename Tp, std::size_t N>
class DoxyLimbo#

表示虚数(limbo numbers)的模板。

用于整数类型的特化,这些整数类型不属于任何地方。它不支持任何实数类型。

参数 Tp:

整数类型。必须是整数类型。

参数 N:

元素数量。

公共函数

DoxyLimbo()#

默认构造函数。不初始化任何内容。

DoxyLimbo(const DoxyLimbo<Tp, N> &l)#

设置复制虚数的默认行为。

const Tp *data()#

返回虚数的原始数据。

DoxyLimbo()

默认构造函数。不初始化任何内容。

DoxyLimbo(const DoxyLimbo<Tp, N> &l)

设置复制虚数的默认行为。

const Tp *data()

返回虚数的原始数据。

DoxyLimbo()

默认构造函数。不初始化任何内容。

DoxyLimbo(const DoxyLimbo<Tp, N> &l)

设置复制虚数的默认行为。

const Tp *data()

返回虚数的原始数据。

受保护的属性

Tp p_data[N]#

行内注释示例。

常用 Doxygen 标签:#

注意

更多标签/命令,请参阅 https://doxygen.cn/manual/commands.html

@brief

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

@details

就像 @brief 开始一个简要描述一样,@details 开始详细描述。您也可以开始一个新段落(空行),然后就不需要 @details 命令了。

@param

开始对函数参数 的参数描述,后跟参数的描述。将检查参数的存在性,如果缺少此(或任何其他)参数的文档或其未出现在函数声明或定义中,则会发出警告。

@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: 无法在项目“numpy”的 doxygen xml 输出中从目录: ../build/doxygen/xml 解析函数“doxy_reST_example”及参数 None。可能的匹配项

- void doxy_reST_example(void)
- void doxy_reST_example(void)
- void doxy_reST_example(void)

2. 喂给 Doxygen#

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

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

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

# 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 文件。

注意

欲了解更多信息,请查看“指令和配置变量

常用指令:#

doxygenfunction

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

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

查看示例以了解其作用。

doxygenclass

此指令为单个类生成相应的输出。它接受标准的项目、路径、大纲和无链接选项,并额外接受成员、受保护成员、私有成员、未文档化成员、成员组和仅成员选项

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

查看doxygenclass 文档了解更多详情并查看其实际应用。

doxygennamespace

此指令为命名空间内容生成适当的输出。它接受标准的项目、路径、大纲和无链接选项,并额外接受仅内容、成员、受保护成员、私有成员和未文档化成员选项。要引用嵌套命名空间,必须提供完整的命名空间路径,例如 foo 命名空间内的 bar 命名空间为 foo::bar。

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

查看doxygennamespace 文档以了解更多详情并查看其实际应用。

doxygengroup

此指令为 Doxygen 组的内容生成适当的输出。Doxygen 组可以在源注释中通过特定的 Doxygen 标记声明,如 Doxygen 分组文档中所述。

它接受标准的项目、路径、大纲和无链接选项,并额外接受仅内容、成员、受保护成员、私有成员和未文档化成员选项。

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

查看doxygengroup 文档以了解更多详情并查看其实际应用。

遗留指令#

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

默认情况下,如果在没有参数的情况下使用,legacy 指令将生成以下输出:

遗留

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

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

.. legacy::

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

此消息将附加到默认消息之后,并生成以下输出

遗留

此子模块被视为遗留模块,将不再接收更新。这也可能意味着它将在未来的 NumPy 版本中被移除。更多详情,请参阅numpy.distutils 的状态和迁移建议

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

.. legacy:: function

这将创建以下输出

遗留

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

文档阅读#

  • 技术写作的领先组织 Write the Docs 举办会议、提供学习资源并运营 Slack 频道。

  • Google 的技术写作资源集合称“每位工程师都是作家”,其中包括为开发者提供的免费在线课程,内容涵盖文档规划和撰写。

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