在扩展中声明对 sphinx-build 的额外依赖

Declare additional dependency to sphinx-build in an extension

TL,DR:在 Sphinx 扩展中,我如何告诉 sphinx-build 将附加文件视为依赖项?在我的直接用例中,这是扩展的源代码,但这个问题同样适用于扩展使用的一些辅助文件。

我正在使用自定义扩展生成带有 Sphinx 的文档。我正在使用 sphinx-build 来构建文档。例如,我使用这个命令生成HTML(这是sphinx-quickstart生成的makefile中的命令):

sphinx-build -b html -d _build/doctrees   . _build/html

由于我的自定义扩展与文档源一起维护,我希望 sphinx-build 将其视为生成的 HTML(和 LaTeX 等)的依赖项。因此,每当我更改扩展程序的源代码时,我都希望 sphinx-build 重新生成输出。

我如何告诉 sphinx-build 将附加文件视为依赖项? 在 toctree 中没有提及,因为它不是源代码的一部分.从逻辑上讲,这应该是我通过扩展程序的 setup 函数所做的事情。


示例扩展(my_extension.py):

from docutils import nodes
from docutils.parsers.rst import Directive

class Foo(Directive):
    def run(self):
        node = nodes.paragraph(text='Hello world\n')
        return [node]

def setup(app):
    app.add_directive('foo', Foo)

样本来源(index.rst):

.. toctree::
   :maxdepth: 2

.. foo::

示例conf.py(基本上是sphinx-quickstart的输出加上我的扩展):

import sys
import os
sys.path.insert(0, os.path.abspath('.'))
extensions = ['my_extension']
templates_path = ['_templates']
source_suffix = '.rst'
master_doc = 'index'
project = 'Hello directive'
copyright = '2019, Gilles'
author = 'Gilles'
version = '1'
release = '1'
language = None
exclude_patterns = ['_build']
pygments_style = 'sphinx'
todo_include_todos = False
html_theme = 'alabaster'
html_static_path = ['_static']
htmlhelp_basename = 'Hellodirectivedoc'
latex_elements = {
}
latex_documents = [
    (master_doc, 'Hellodirective.tex', 'Hello directive Documentation',
     'Gilles', 'manual'),
]
man_pages = [
    (master_doc, 'hellodirective', 'Hello directive Documentation',
     [author], 1)
]
texinfo_documents = [
    (master_doc, 'Hellodirective', 'Hello directive Documentation',
     author, 'Hellodirective', 'One line description of project.',
     'Miscellaneous'),
]

解决方案的验证:

  1. 运行 make html(或如上sphinx-build)。
  2. 修改 my_extension.pyHello world 替换为 Hello again
  3. 运行 make html 再一次。
  4. 生成的 HTML (_build/html/index.html) 现在必须包含 Hello again 而不是 Hello world

它看起来像 note_dependency method in the build environment API should do what I want. But when should I call it? I tried various events 但 none 似乎以正确的状态击中了环境对象。起作用的是从指令中调用它。

import os
from docutils import nodes
from docutils.parsers.rst import Directive
import sphinx.application

class Foo(Directive):
    def run(self):
        self.state.document.settings.env.note_dependency(__file__)
        node = nodes.paragraph(text='Hello done\n')
        return [node]

def setup(app):
    app.add_directive('foo', Foo)

如果文档至少包含一个 foo 指令,当引入该指令的扩展发生变化时,它将被标记为过时。这是有道理的,尽管如果扩展添加许多指令或进行不同的更改可能会变得乏味。不知道有没有更好的办法

灵感来自 Luc Van Oostenryck's autodoc-C

据我所知,可以在 doctree-read 中调用 app.env.note_dependency 以将任何文件添加为当前正在读取的文档的依赖项。 因此,在您的用例中,我认为这会起作用:

from typing import Any, Dict
from sphinx.application import Sphinx
import docutils.nodes as nodes


def doctree-read(app: Sphinx, doctree: nodes.document):
    app.env.note_dependency(file)


def setup(app: Sphinx):
    app.connect("doctree-read", doctree-read)