我正在使用mkdocs&mkdocstring来构建我的文档,并在文档字符串中包含代码示例.我还使用doctest(通过pytest --doctest-modules)来测试所有这些示例.

备选方案1--文件格式

如果我将我的文档字符串设置为如下格式:

    """
    Recursively flattens a nested iterable (including strings!) and returns all elements in order left to right.

    Examples:
    --------
    ```
    >>> [x for x in flatten([1,2,[3,4,[5],6],7,[8,9]])]
    [1, 2, 3, 4, 5, 6, 7, 8, 9]
    ```
    """

然后,它在文档中呈现得很好,但doctest失败,并显示错误:

Expected:
    [1, 2, 3, 4, 5, 6, 7, 8, 9]
    ```
Got:
    [1, 2, 3, 4, 5, 6, 7, 8, 9]

这是有意义的,因为doctest将everything视为预期输出,直到空白行为止,目标是匹配exactly

选项2--文档测试的格式

如果在不使用代码块的情况下格式化doctest的文档字符串:

    """
    Recursively flattens a nested iterable (including strings!) and returns all elements in order left to right.

    Examples:
    --------
    >>> [x for x in flatten([1,2,[3,4,[5],6],7,[8,9]])]
    [1, 2, 3, 4, 5, 6, 7, 8, 9]
    """

然后,doctest通过,但文档呈现

[X代表x in Flatten([1,2,[3,4,[5],6],7,[8,9]])][1,2,3,4,5,6,7,8,9]

解决方法?-为doctest添加一个空行

如果我在代码块末尾之前使用额外的空行格式化它:

    """
    Recursively flattens a nested iterable (including strings!) and returns all elements in order left to right.

    Examples:
    --------
    ```
    >>> [x for x in flatten([1,2,[3,4,[5],6],7,[8,9]])]
    [1, 2, 3, 4, 5, 6, 7, 8, 9]

    ```
    """

然后文档测试通过了,但是

  1. 在文档中的示例底部有一个空行(丑陋)
  2. 我需要记住在每个示例的末尾添加一个空行(容易出错且令人讨厌)

有人知道更好的解决办法吗?

推荐答案

修补doctest用来识别代码块的正则表达式解决了这个问题.在这里为那些在future 偶然发现这一点的人记录下来...

因为这不是我想在项目中经常做的事情(!),我创建了pytest-doctest-mkdocstrings作为一个最简单的插件来为我做这件事,并包括了一些额外的健全判断、配置选项等.

pip install pytest-doctest-mkdocstrings
pytest --doctest-mdcodeblocks --doctest-modules --doctest-glob="*.md"

对于那些正在寻找代码中的答案以使用自己的人来说,所需的更改是:


    _MD_EXAMPLE_RE = re.compile(
        r"""
            # Source consists of a PS1 line followed by zero or more PS2 lines.
            (?P<source>
                (?:^(?P<indent> [ ]*) >>>    .*)    # PS1 line
                (?:\n           [ ]*  \.\.\. .*)*)  # PS2 lines
            \n?
            # Want consists of any non-blank lines that do not start with PS1.
            (?P<want> (?:(?![ ]*$)    # Not a blank line
                        (?![ ]*```)  # Not end of a code block
                        (?![ ]*>>>)  # Not a line starting with PS1
                        .+$\n?       # But any other line
                    )*)
            """,
        re.MULTILINE | re.VERBOSE,
    )

    doctest.DocTestParser._EXAMPLE_RE = _MD_EXAMPLE_RE

具体地说,我已经在"想要"的标识中包括了(?![ ]*```) # Not end of a code block

Python相关问答推荐

大Pandas 胚胎中产生组合

根据在同一数据框中的查找向数据框添加值

为什么默认情况下所有Python类都是可调用的?

如何在python polars中停止otherate(),当使用when()表达式时?

我如何使法国在 map 中完全透明的代码?

在ubuntu上安装dlib时出错

为一个组的每个子组绘制,

多处理队列在与Forking http.server一起使用时随机跳过项目

我的字符串搜索算法的平均时间复杂度和最坏时间复杂度是多少?

无论输入分辨率如何,稳定扩散管道始终输出512 * 512张图像

Flash只从html表单中获取一个值

Flask Jinja2如果语句总是计算为false&

将标签移动到matplotlib饼图中楔形块的开始处

基于Scipy插值法的三次样条系数

使用类型提示进行类型转换

如何在验证文本列表时使正则表达式无序?

如何将相同组的值添加到嵌套的Pandas Maprame的倒数第二个索引级别

操作布尔值的Series时出现索引问题

修改.pdb文件中的值并另存为新的

如何在Python中实现高效地支持字典和堆操作的缓存?