编写文档#

cuDF 文档分为多个部分。 所有核心功能都使用内联文档字符串进行记录。 用户指南或开发者指南等附加页面是独立编写的。 虽然文档字符串使用 reStructuredText (reST) 编写, 但后者使用 MyST 编写。 内联文档字符串使用一组额外的 reST 页面进行组织。 然后使用 Sphinx 将所有内容编译在一起。 本文档讨论了这些组件以及如何为它们做出贡献。

文档字符串#

cuDF 文档字符串使用 numpy 风格。 为了替代完整的解释, 我们在这里包含了一个格式示例和常用的部分:

class A:
    """Brief description of A.

    Longer description of A.

    Parameters
    ----------
    x : int
        Description of x, the first constructor parameter.
    """
    def __init__(self, x: int):
        pass

    def foo(self, bar: str):
        """Short description of foo.

        Longer description of foo.

        Parameters
        ----------
        bar : str
            Description of bar.

        Returns
        -------
        float
            Description of the return value of foo.

        Raises
        ------
        ValueError
            Explanation of when a ValueError is raised.
            In this case, a ValueError is raised if bar is "fail".

        Examples
        --------
        The examples section is _strongly_ encouraged.
        Where appropriate, it may mimic the examples for the corresponding pandas API.
        >>> a = A()
        >>> a.foo('baz')
        0.0
        >>> a.foo('fail')
        ...
        ValueError: Failed!
        """
        if bar == "fail":
            raise ValueError("Failed!")
        return 0.0

numpydoc 支持许多其他部分的文档字符串。 开发者应该熟悉它们,因为许多在不同的场景中非常有用。 我们的指南包括对标准 numpydoc 指南的一个补充。 类属性,虽然没有明确涵盖,但应该在 getter 函数中进行文档化。 这种选择使得 help 更加有用,并且能够在子类中继承文档字符串。

我们所有的文档字符串都使用ruff pydocstyle rules进行验证。 这确保了文档字符串风格在代码库中保持一致和符合规范。

已发布的文档#

文档是使用Sphinx编译的,它从代码中提取文档字符串。然而,我们的目标不仅仅是简单地列出所有API,而是模仿pandas文档。为此,我们将API文档组织到特定的页面和部分中。这些页面存储在docs/cudf/source/api_docs中。例如,所有DataFrame文档都包含在docs/cudf/source/api_docs/dataframe.rst中。该页面包含“计算/描述性统计”等部分,以使API更易于发现。

在每个部分中,文档是使用autosummary创建的。这个插件使得为每个记录的API生成页面变得容易。为此,文档的每个部分看起来如下:

Section name
~~~~~~~~~~~~
.. autosummary::
   API1
   API2
   ...

每个列出的项目都会自动将其文档字符串渲染到一个单独的页面中。 此布局来自我们使用的Sphinx主题

注意

在底层,autosummary 生成如下所示的存根页面(以 cudf.concat 为例):

cudf.concat
===========

.. currentmodule:: cudf

.. autofunction:: concat

autofunction这样的命令来自autodoc。 这个指令将导入cudf并从cudf.concat中提取文档字符串。 这种方法使我们能够在组织文档时做最少的手动工作, 同时仍然尽可能接近地匹配pandas的布局。

在添加新API时,开发者只需将API添加到适当的页面。 将函数名称添加到适当的自动摘要列表中就足以记录它。

记录类#

Python 类和 RAPIDS 中使用的 Sphinx 插件以非平凡的方式交互。 autosummary 为类生成的默认页面使用 autodoc 自动检测并记录类的所有方法。 这意味着除了手动创建的 autosummary 页面(其中类方法按相关功能分组)之外,每个类还有另一个页面,其中该类的所有方法都自动汇总在一个表格中以便快速访问。 然而,我们还使用了 numpydoc 扩展,它提供了相同的功能。 我们同时使用两者,以尽可能匹配 pandas 文档的内容和风格。

pandas 对于类文档中包含的信息也非常讲究。 虽然主要面向用户的类的文档页面,如 DataFrameSeriesIndex 包含了所有 API,但不太显眼的类或子类(如 Index 的子类)只包含那些特定于这些子类的方法。 例如,cudf.CategoricalIndex 只在其页面上包含 codescategories,而不是整个 Index 功能集。

为了满足这些需求,我们采取以下方法:

  1. 默认的autosummary类模板被一个更简单的模板所覆盖,该模板不生成方法或属性文档。换句话说,我们禁用了autosummary生成方法和属性列表的功能。

  2. 我们完全依赖 numpydoc 来列出需要完整 API 的类(DataFrame/Series/等)。如果(且仅当)方法和属性部分尚未在类的文档字符串中定义,numpydoc 将自动填充这些部分。

  3. 对于只应包含API子集的类,我们在类的文档中明确包含这些API。当这些列表存在时,numpydoc 不会覆盖它们。如果方法或属性部分应为空,则该部分仍必须包含,但应仅包含“None”。例如,CategoricalIndex 类的文档可能包含如下内容:

    Attributes
    ----------
    codes
    categories

    Methods
    -------
    None

与pandas比较#

cuDF 旨在提供类似 pandas 的体验。 然而,由于各种原因,cuDF 的 API 可能与 pandas 存在差异。 如果存在这些差异,应该进行文档记录。 我们通过 pandas-compat 指令来促进此类文档记录。 该指令应在文档字符串中使用,如下所示:

"""Brief

Docstring body

.. pandas-compat::
    :meth:`pandas.DataFrame.METHOD`

    Explanation of differences

所有此类API兼容性说明都收集并显示在渲染的文档中。

编写文档页面#

除了文档字符串外,我们的文档还包含一些更专门的用户指南。 这些页面存储在docs/cudf/source/user_guide中。 这些页面都是使用MyST编写的,MyST是Markdown的超集。 MyST允许开发者使用熟悉的Markdown语法编写, 同时在需要时提供reST的全部功能。 这些页面并不符合任何特定的风格或用例集。 然而,如果您开发了任何足够复杂的新功能, 请考虑用户是否会从更完整的演示中受益。

注意

我们鼓励在页面之间使用链接。 我们启用了Myst自动生成的锚点, 因此链接应使用适当命名空间的锚点,而不是添加手动链接。

构建文档#

需求#

以下是构建文档所需的:

  • 一个与RAPIDS兼容的GPU。这是必要的,因为文档会执行代码。

  • 在相同的构建环境中拥有cudf的工作副本。 我们建议遵循构建说明

  • Sphinx, numpydoc, 和 MyST-NB。 假设你遵循了构建说明,这些应该会自动安装到你的环境中。

构建和查看文档#

一旦你有了cudf的工作副本,构建文档就很简单了:

  1. 导航到 /path/to/cudf/docs/cudf/

  2. 执行 make html

这将在您的 shell 中运行 Sphinx 并在 build/html/index.html 生成输出。 查看结果。

  1. 导航到 build/html

  2. 执行 python -m http.server

然后,打开一个网页浏览器并访问 https://localhost:8000。 如果当前有其他程序正在使用端口8000, python -m http.server 会自动找到下一个可用的端口。 或者,您可以使用 python -m http.server $PORT 指定一个端口。

您可以在远程机器上构建文档,但希望在本地查看它们。假设另一台机器的IP地址在您的本地网络上可见,您可以通过将localhost替换为主机的IP地址来查看文档。或者,您也可以使用例如ssh -N -f -L localhost:$LOCAL_PORT:localhost:$REMOTE_PORT $REMOTE_IP来转发端口。这将使$REMOTE_IP:$REMOTE_PORTlocalhost:$LOCAL_PORT上可见。

记录cuDF内部结构#

与公共API不同,内部代码(函数、类等)的文档没有经过检查。 强烈建议对内部代码进行文档化,但没有以任何特定方式强制执行。 关于风格,完整的numpy风格文档字符串或常规的#注释都是可以接受的。 前者对于复杂或广泛使用的功能可能很有用, 而后者对于小型一次性函数来说是可以的。