编写文档

Standard Providers》和《Localized Providers》下的所有内容都是使用 sphinx.ext.autodoc 自动生成的,它会在 sphinx-build 过程中从提供者方法中提取 docstrings。这也意味着 docstrings 必须以有效的 reStructuredText 编写。

此外,由于这个库的特性,必须包含示例用法来最好地展示其功能和可能性。由于有如此多的提供者方法和本地化版本,如果每个提供者方法的示例用法部分(包含可重现的输出)都手动编写,那么维护文档将是一场噩梦。

自动化示例用法部分

为了减轻文档维护的负担,本项目利用 sphinx.ext.autodoc 提供的 docstring 预处理功能,通过使用 :sample:“伪角色”,仅用几行文本即可自动生成示例用法部分,其中包含可重现的输出,如下所示

:sample[ size=SIZE][ seed=SEED]:[ KWARGS]

这将通过使用初始种子值 SEED 和可选关键字参数 KWARGS,调用提供者方法 SIZE 次来生成示例用法部分。如果未指定 SIZESIZE 小于 5,则默认为 5。如果未指定 SEED,则默认为 0

例如,假设行 :sample: 出现在名为 method1 的提供者方法的 docstring 中。这短短的一行文本将自动生成如下所示的示例用法部分

>>> Faker.seed(0)
>>> for _ in range(5):
...     fake.method1()
...
# Output 1
# Output 2
# Output 3
# Output 4
# Output 5

根据提供者方法的性质,默认的 5 个示例可能不够,因此可以使用 size=SIZE 来增加数量。您可能还希望提供参数来更改方法的行为,这可以通过使用 KWARGS 来完成。综上所述,如果我们使用 :sample size=10: a=1, b=2, c=3,生成的示例用法部分将如下所示

>>> Faker.seed(0)
>>> for _ in range(10):
...     fake.method1(a=1, b=2, c=3)
...
# Output 1
# Output 2
# Output 3
# Output 4
# Output 5
# Output 6
# Output 7
# Output 8
# Output 9
# Output 10

有时也可能需要展示特定的输出,但伪随机数生成器会妨碍实现,例如生成所述输出的几率非常低。为了解决这个问题,您可以使用 seed=SEED 来指定一个已知能生成所需输出的初始种子值。如果我们指定 :sample seed=12345: a=2,生成的示例用法部分将如下所示

>>> Faker.seed(12345)
>>> for _ in range(5):
...     fake.method1(a=2)
...
# Output 1
# Output 2
# Output 3
# Output 4
# Output 5

您可以混合使用 SIZESEEDKWARGS,如果 KWARGS 太长不适合一行,您可以像在实际 Python 代码中跨多行拆分关键字参数一样,将 KWARGS 拆分为多行。例如,假设 docstring 包含以下内容

:sample size=25 seed=12345: arg1='very long value, unfortunately',
                            arg2='yet another long value'

生成的示例部分用法将如下所示

>>> Faker.seed(12345)
>>> for _ in range(25):
...     fake.method1(arg1='very long value, unfortunately', arg2='yet another long value')
...
# Output 1
# Output 2
# ...
# Output 24
# Output 25

Docstring 预处理行为

如果提供者方法没有 docstring,或者 docstring 不包含格式正确的 :sample: 行,则会自动生成一个默认的示例用法部分,以帮助文档不充分的提供者方法。

一个 docstring 可能包含多个 :sample: 行,所有预期的 :sample: 行首先会被检查格式是否正确。格式错误的实例将被丢弃,详细信息将作为警告记录到控制台。所有格式正确的 :sample: 行都将从 docstring 中删除,并进行示例验证和生成,生成的 docstring 末尾将附加一个 :examples: 部分。以代码形式表示

# Source code docstring
def foo():
    """Summary line

    Lorem ipsum dolor sit amet, consectetur adipiscing elit.
    Fusce auctor faucibus condimentum.

    :sample:

    Duis posuere lacinia porta.
    Quisque mauris nisl, mattis sed ornare eget, accumsan sit amet mauris.

    :sample size=10 seed=1000:
    """
    return 1
# Resulting docstring (more or less) after preprocessing
def foo():
    """Summary line

    Lorem ipsum dolor sit amet, consectetur adipiscing elit.
    Fusce auctor faucibus condimentum.


    Duis posuere lacinia porta.
    Quisque mauris nisl, mattis sed ornare eget, accumsan sit amet mauris.

    :examples:

    >>> Faker.seed(0)
    >>> for _ in range(5):
    ...     fake.foo()
    ...
    1
    1
    1
    1
    1

    >>> Faker.seed(1000)
    >>> for _ in range(10):
    ...     fake.foo()
    ...
    1
    1
    1
    1
    1
    1
    1
    1
    1
    1
    """
    pass

请注意,它没有记住 :sample: 行的位置。无论 :sample: 行的原始位置如何,所有这些行的结果输出都将被收集并附加到 docstring 的末尾。在构建 docstring 流程时请记住这一点。

允许就地生成示例部分肯定有好处,因为它使创建更丰富的文档成为可能,但不幸的是,由于时间限制,目前尚无法实现。在该功能可用之前,请将所有 :sample: 行放在 docstring 的末尾,以帮助代码审阅者。

示例验证和安全过渡

在底层,示例部分是通过将解析后的 docstring 示例行馈送到标准库的 eval() 中来生成的。这种设置默认情况下肯定会带来一些安全隐患,这就是为什么 :sample: 行在生成之前要经过验证。

验证过程背后有很多细节,但简单来说,SIZESEED 只能是整数,而 KWARGS 只能是带有字面值或 OrderedDict 对象的关键字参数。尝试执行其他任何操作,例如调用其他内置函数或仅仅执行基本算术运算,都将导致验证失败。验证失败的详细信息将作为警告记录到控制台。

为了进一步提高安全性,用于此目的的所有潜在危险代码都已隔离到 faker.sphinx 模块中,并且该模块将从 PyPI 上托管的发行版中排除。

如果您有兴趣了解更多信息或对示例验证的实现方式进行安全审计,请参阅 faker.sphinx.validator.SampleCodeValidatorfaker.sphinx.docstring.ProviderMethodDocstring 的源代码和 docstrings。

示例生成

一旦 :sample: 行通过验证,sphinx-build 过程将尝试根据提供的信息生成结果。如果 KWARGS 包含提供者方法不期望的关键字参数,或者执行提供者方法导致异常,则示例运行仍可能失败。此类实例的详细信息也将作为警告记录到控制台。