【问题标题】:Using Jinja2 with Sphinx autosummary将 Jinja2 与 Sphinx 自动摘要一起使用
【发布时间】:2019-12-19 14:30:30
【问题描述】:

我正在尝试使用 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"]
}

rstjinja()setup() 方法是从 here 借来的。它明确指出:

Jinja 模板将在处理 RST 之前呈现。

我的.rst文件如下:

#####
Title
#####

.. currentmodule:: Package.SubModule

.. autosummary::
    :nosignatures:
    :toctree:

    {% for item in entities %}
        {{ item }}
    {% endfor %}

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

我的问题是'autosummary' 不会为这些类生成存根,因此表中的这些条目是不可点击的。在终端上,对于缺少存根的每个类,我都会看到以下警告:

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

从我的 conf.py 文件中可以看出,这个设置已经是 True

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

#####
Title
#####

.. currentmodule:: Package.SubModule

.. autosummary::
    :nosignatures:
    :toctree:

    {% for item in entities %}
        {{ item }}
    {% endfor %}
    classA

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

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

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

附加信息: 在上面的例子中,类可以通过

from Package.SubModule import classA, classB, classD

【问题讨论】:

  • 由于'autosummary' 要求我们列出所有要包含的项目,我想使用 Jinja2 指定这些。。但是您仍然列出这些项目。现在您改为在html_context 中执行此操作。使用 Jinja 有什么好处?
  • 这有两个原因:1)条目列表可以在这个包的开发过程中改变,目的是让文档自动更新而不需要人工干预。上面的简化示例,我已经硬编码了html_context 中的条目,但在实际使用中,这些是通过一些代码确定的。 2)我们有一组类似的包,我们希望有一个通用的“脚本”来处理每个模块的文档。要记录的条目名称因这些包而异,但我们希望避免手动编辑。

标签: python-3.x jinja2 python-sphinx autodoc toctree


【解决方案1】:

我找到了使用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
}

注意:通过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
}

我的 .rst 文件示例:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-12
    • 2021-11-10
    • 2021-05-07
    • 1970-01-01
    • 2012-05-26
    相关资源
    最近更新 更多