我使用 mkdocs 和 mkdocstring 来构建我的文档,并在文档字符串中包含代码示例。我还使用 doctest(通过
pytest --doctest-modules
)来测试所有这些示例。
如果我像这样格式化我的文档字符串:
"""
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 对待所有内容,直到空行作为预期输出并旨在匹配是完全
如果我在没有代码块的情况下格式化文档测试的文档字符串:
"""
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 for x in flatten([1,2,[3,4,[5],6],7,[8,9]])][1, 2, 3, 4, 5, 6, 7, 8, 9]
如果我在代码块末尾之前使用额外的空行对其进行格式化:
"""
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 通过了但是
有人知道更好的解决方案吗?
修补 doctest 用于识别代码块的正则表达式解决了这个问题。在此记录下来,供将来偶然发现此问题的人使用...
由于这不是我想在项目中定期执行的操作(!),因此我创建了 pytest-doctest-mkdocstrings 作为 pytest 插件来为我执行此操作,并包含一些额外的健全性检查、配置选项等。
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
包含在“想要”的标识中