将 Jinja2 与 Sphinx 自动摘要结合使用

Sha*_*tan 5 jinja2 python-3.x python-sphinx autodoc toctree

我正在尝试使用sphinx.ext.autosummary来记录 Python 包。由于“自动摘要”要求我们列出要包含的所有项目,因此我想使用 Jinja2 来指定这些项目。

我的conf.py如下(显示相关部分):

extensions = [
    'sphinx.ext.autodoc',
    'sphinx.ext.autosummary',
    'sphinx.ext.doctest',
    'sphinx.ext.todo',
    'sphinx.ext.coverage',
    'sphinx.ext.viewcode',
    'sphinx.ext.napoleon',
    'sphinx_automodapi.automodapi'
]

autodoc_default_options = {
    'imported-members':True
}
add_module_names = False
autosummary_generate = True
numpydoc_show_class_members = False

def rstjinja(app, docname, source):
    """
    Render our pages as a jinja template for fancy templating goodness.
    """
    # Make sure we're outputting HTML
    if app.builder.format != 'html':
        return
    src = source[0]
    rendered = app.builder.templates.render_string(
        src, app.config.html_context
    )
    source[0] = rendered

def setup(app):
    app.connect("source-read", rstjinja)

# in actual usage, `entities` is determined at docs generation time via some code
html_context = {
    'entities' : ["classA", "classB", "classD"]
}
Run Code Online (Sandbox Code Playgroud)

方法rstjinja()和方法setup()都是从这里借来的。它明确指出:

Jinja 模板将在处理 RST 之前渲染。

我的 .rst 文件如下:

#####
Title
#####

.. currentmodule:: Package.SubModule

.. autosummary::
    :nosignatures:
    :toctree:

    {% for item in entities %}
        {{ item }}
    {% endfor %}
Run Code Online (Sandbox Code Playgroud)

输出正确地显示了一个由 3 个条目组成的汇总表(一个对应我指定的三个类中的每一个:“classA”、“classB”、“classD”)。第一列显示类的名称,第二列显示单行描述(来自其文档字符串)。第二列中的数据清楚地表明 Sphinx 能够识别相关类并提取其文档字符串。

我的问题是“自动摘要”不会为这些类生成存根,因此表中的这些条目不可单击。在终端上,我看到每个缺少存根的类都出现以下警告:

警告:自动摘要:未找到存根文件“Package.SubModule.classA”。检查您的 autosummary_generate 设置。

正如我的 conf.py 文件中所见,此设置已经是True.

如果我将 .rst 文件更改为以下内容(为了探索):

#####
Title
#####

.. currentmodule:: Package.SubModule

.. autosummary::
    :nosignatures:
    :toctree:

    {% for item in entities %}
        {{ item }}
    {% endfor %}
    classA
Run Code Online (Sandbox Code Playgroud)

然后我得到一个与前一个情况类似的表,但在末尾有一个额外的行对应于“classA”。有趣的是,“classA”的两个条目(第一个通过 Jinja 生成,第二个通过显式指定)现在超链接到为“classA”创建的存根。

为什么会这样呢?当仅通过 Jinja 指定相同信息时,为什么不创建存根(即使 sphinx 确实在表中显示了这些信息的文档字符串)?

我该如何解决这个问题?对我来说,能够提供要通过 Jinja 记录的实体列表非常重要(因为我通过 中的一些 Python 代码确定了这些实体conf.py)。

附加信息:在上面的示例中,可以通过以下方式导入类

from Package.SubModule import classA, classB, classD

Sha*_*tan 2

我找到了使用sphinx_automodapi.automodapi扩展的解决方法。

我的相关内容conf.py

import sphinx_automodapi

extensions = [
    'sphinx.ext.autodoc',
    'sphinx.ext.doctest',
    'sphinx.ext.todo',
    'sphinx.ext.coverage',
    'sphinx.ext.viewcode',
    'sphinx.ext.napoleon',
    'sphinx_automodapi.automodapi'
]

add_module_names = False
autosummary_generate = True
numpydoc_show_class_members = False

def rstjinja(app, docname, source):
    """
    Render our pages as a jinja template for fancy templating goodness.
    """
    # Make sure we're outputting HTML
    if app.builder.format != 'html':
        return
    src = source[0]
    rendered = app.builder.templates.render_string(
        src, app.config.html_context
    )
    source[0] = rendered

def setup(app):
    app.connect("source-read", rstjinja)


html_context = {
    'entities'       : ["classC", "classE"] # NOTE: specify classes NOT to be included/documented; items specified here will be skipped in doc generation
}
Run Code Online (Sandbox Code Playgroud)

注意:通过的类列表html_context是要从文档中排除的类。如果扩展允许直接指定所需的类,那就太好了。我已经开了一张票(此处: https: //github.com/astropy/sphinx-automodapi/issues/92)(目前尚未解决)。

在实际使用中,类列表可以动态确定。例如:

import inspect, importlib, sciunit
package_import_name = "package_name"

submodule = "{}.submodule_name".format(package_import_name)
module = importlib.import_module(submodule)
exlcude_classes = [x[0] for x in inspect.getmembers(module,
                    lambda member: inspect.isclass(member)
                                    and not(<<specify condition>>))]

html_context = {
    'entities'       : exlcude_classes
}
Run Code Online (Sandbox Code Playgroud)

我的 .rst 文件示例:

##########
Submodules
##########

.. automodapi:: package_name.submodule_name
    :nosignatures:
    :no-main-docstr:
    :skip: {{ entities|join(', ') }}
Run Code Online (Sandbox Code Playgroud)