在Sphinx中描述代码¶
在 教程的前几节 中,你可以阅读如何在 Sphinx 中编写叙述性或散文文档.在本节中,你将描述代码对象.
Sphinx 支持用几种语言记录代码对象,即 Python、C、C++、JavaScript 和 reStructuredText.每个都可以使用一系列指令和角色进行文档化,这些指令和角色按 域 分组.在本教程的其余部分,您将使用 Python 域,但本节中看到的所有概念也适用于其他域.
Python¶
记录 Python 对象¶
Sphinx 提供了几种角色和指令来记录 Python 对象,所有这些都分组在 Python 域 中.例如,你可以使用 py:function
指令来记录一个 Python 函数,如下所示:
Creating recipes
----------------
To retrieve a list of random ingredients,
you can use the ``lumache.get_random_ingredients()`` function:
.. py:function:: lumache.get_random_ingredients(kind=None)
Return a list of random ingredients as strings.
:param kind: Optional "kind" of ingredients.
:type kind: list[str] or None
:return: The ingredients list.
:rtype: list[str]
这将呈现如下:
注意几件事:
Sphinx 解析了
.. py:function
指令的参数,并适当地高亮显示了模块、函数名和参数.该指令内容包括函数的一行描述,以及包含函数参数、预期类型、返回值和返回类型的 信息字段列表.
备注
py:
前缀指定 域 .你可以配置默认域,这样你就可以省略前缀,无论是全局使用 primary_domain
配置,还是使用 default-domain
指令从调用点开始直到文件结束更改它.例如,如果你将其设置为 py
(默认),你可以直接写 .. function::
.
交叉引用 Python 对象¶
默认情况下,这些指令中的大多数生成可以被文档的任何部分通过使用 相应的角色 进行交叉引用的实体.对于函数的情况,你可以使用 py:func
来实现,如下所示:
The ``kind`` parameter should be either ``"meat"``, ``"fish"``,
or ``"veggies"``. Otherwise, :py:func:`lumache.get_random_ingredients`
will raise an exception.
在生成代码文档时,Sphinx 会自动生成一个交叉引用,只需使用对象的名称,而无需显式使用角色.例如,您可以使用 py:exception
指令描述函数引发的定制异常:
.. py:exception:: lumache.InvalidKindError
Raised if the kind is invalid.
然后,将此异常添加到函数的原始描述中:
.. py:function:: lumache.get_random_ingredients(kind=None)
Return a list of random ingredients as strings.
:param kind: Optional "kind" of ingredients.
:type kind: list[str] or None
:raise lumache.InvalidKindError: If the kind is invalid.
:return: The ingredients list.
:rtype: list[str]
最后,这是结果的呈现方式:
很美,不是吗?
在您的文档中包含doctests¶
由于你现在正在描述一个Python库中的代码,保持文档和代码尽可能同步将变得非常有用.在Sphinx中实现这一点的方法之一是将代码片段包含在文档中,称为*doctests*,这些代码片段在构建文档时会被执行.
为了演示本教程中涵盖的 doctests 和其他 Sphinx 功能,Sphinx 需要能够导入代码.为此,请在 conf.py
的开头写入以下内容:
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here.
import pathlib
import sys
sys.path.insert(0, pathlib.Path(__file__).parents[2].resolve().as_posix())
备注
更改 sys.path
变量的一个替代方法是创建一个 pyproject.toml
文件并使代码可安装,这样它的行为就像任何其他 Python 库一样.然而,``sys.path`` 方法更简单.
然后,在将doctests添加到您的文档之前,请在 conf.py
中启用 doctest 扩展:
extensions = [
'sphinx.ext.duration',
'sphinx.ext.doctest',
]
接下来,按照以下方式编写一个doctest块:
>>> import lumache
>>> lumache.get_random_ingredients()
['shells', 'gorgonzola', 'parsley']
Doctests 包括要运行的 Python 指令,前面带有 >>>
,这是标准的 Python 解释器提示符,以及每个指令的预期输出.这样,Sphinx 可以检查实际输出是否与预期输出匹配.
要观察 doctest 失败是什么样子(而不是像上面那样的代码错误),让我们首先错误地写返回值.因此,添加一个函数 get_random_ingredients
如下:
def get_random_ingredients(kind=None):
return ["eggs", "bacon", "spam"]
你现在可以运行 make doctest
来执行你的文档的doctests.最初这将显示一个错误,因为实际代码的行为与指定的不同:
(.venv) $ make doctest
Running Sphinx v4.2.0
loading pickled environment... done
...
running tests...
Document: usage
---------------
**********************************************************************
File "usage.rst", line 44, in default
Failed example:
lumache.get_random_ingredients()
Expected:
['shells', 'gorgonzola', 'parsley']
Got:
['eggs', 'bacon', 'spam']
**********************************************************************
...
make: *** [Makefile:20: doctest] Error 1
如你所见,doctest 报告了预期和实际的结果,便于检查.现在是时候修复函数了:
def get_random_ingredients(kind=None):
return ["shells", "gorgonzola", "parsley"]
最后,``make doctest`` 报告成功!
不过对于大型项目,这种手动方法可能会变得有点繁琐.在下一节中,您将看到 如何自动化这个过程.
其他语言 (C, C++, 其他)¶
文档化和交叉引用对象¶
Sphinx 还支持记录和交叉引用用其他编程语言编写的对象.有四个额外的内置域:C、C++、JavaScript 和 reStructuredText.第三方扩展可以为更多语言定义域,例如
例如,要记录一个 C++ 类型定义,你可以使用内置的 cpp:type
指令,如下所示:
.. cpp:type:: std::vector<int> CustomList
A typedef-like declaration of a type.
这将产生以下结果:
-
typedef std::vector<int> CustomList¶
一个类似于类型定义的声明.
所有这些指令都会生成可以被相应角色交叉引用的引用.例如,要引用前面的类型定义,你可以使用 cpp:type
角色,如下所示:
Cross reference to :cpp:type:`CustomList`.
这将生成一个指向先前定义的超链接:CustomList
.