Использование Jinja2 с автосводкой Sphinx
Я пытаюсь использовать 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()
были заимствованы отсюда. В нем четко указано, что:
Шаблоны 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 (поскольку я определяю их с помощью некоторого кода Python вconf.py
).
Дополнительная информация: в приведенном выше примере классы можно импортировать через
from Package.SubModule import classA, classB, classD
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(', ') }}