事件回调 API

将回调函数连接到事件是一种简单的方法来扩展 Sphinx,通过在构建过程的各个点进行挂钩。

在扩展的 setup 函数中使用 Sphinx.connect(),或者在项目 conf.py 中的 setup 函数中,将函数连接到事件

def source_read_handler(app, docname, source):
    print('do something here...')

def setup(app):
    app.connect('source-read', source_read_handler)

另请参阅

扩展可以使用 Sphinx.add_event() 添加自己的事件,并使用 Sphinx.emit()Sphinx.emit_firstresult() 调用它们。

核心事件概述

以下是构建过程中发生的 核心事件概述。

1. event.config-inited(app,config)
2. event.builder-inited(app)
3. event.env-get-outdated(app, env, added, changed, removed)
4. event.env-before-read-docs(app, env, docnames)

for docname in docnames:
   5. event.env-purge-doc(app, env, docname)

   if doc changed and not removed:
      6. source-read(app, docname, source)
      7. run source parsers: text -> docutils.document
         - parsers can be added with the app.add_source_parser() API
         - event.include-read(app, relative_path, parent_docname, content)
           is called for each include directive
      8. apply transforms based on priority: docutils.document -> docutils.document
         - event.doctree-read(app, doctree) is called in the middle of transforms,
           transforms come before/after this event depending on their priority.

9. event.env-merge-info(app, env, docnames, other)
   - if running in parallel mode, this event will be emitted for each process

10. event.env-updated(app, env)
11. event.env-get-updated(app, env)

if environment is written to disk:
   12. event.env-check-consistency(app, env)

13. event.write-started(app, builder)
    - This is called after ``app.parallel_ok`` has been set,
      which must not be altered by any event handler.

# The updated-docs list can be builder dependent, but generally includes all new/changed documents,
# plus any output from `env-get-updated`, and then all "parent" documents in the ToC tree
# For builders that output a single page, they are first joined into a single doctree before post-transforms
# or the doctree-resolved event is emitted
for docname in updated-docs:
   14. apply post-transforms (by priority): docutils.document -> docutils.document
   15. event.doctree-resolved(app, doctree, docname)
       - In the event that any reference nodes fail to resolve, the following may emit:
       - event.missing-reference(env, node, contnode)
       - event.warn-missing-reference(domain, node)

16. Generate output files
17. event.build-finished(app, exception)

这也是 Sphinx 构建过程中的事件流程图

// A flow graph of the Sphinx build process, highlighting event callbacks

digraph events {
    graph [
        rankdir=TB
    ];
    node [
        shape=rect
        style=rounded
    ];
    "Sphinx" [
        shape=record
        label = "<init> Sphinx.__init__() | <build> Sphinx.build()"
    ];

    // During initialization
    "config-inited"[style=filled fillcolor="#D5FFFF" color=blue penwidth=2];
    "Sphinx":init -> "config-inited";
    "builder-inited"[style=filled fillcolor="#D5FFFF" color=blue penwidth=2];
    "Sphinx":init -> "builder-inited";

    // During build
    "Builder" [label = "Builder.build()"]
    "Sphinx":build -> "Builder";
    "Builder.build" [
        shape=record
        label = "
            <before_read> before read |
            <read> read |
            <after_read> after read |
            <write> write |
            <finalize> finalize"
    ];
    "Builder" -> "Builder.build";

    "env-get-outdated"[style=filled fillcolor="#D5FFFF" color=blue penwidth=2];
    "Builder.build":before_read -> "env-get-outdated";
    remove_each_doc [shape="ellipse", label="for removed"];
    "Builder.build":before_read -> "remove_each_doc";
    "env-purge-doc"[style=filled fillcolor="#D5FFFF" color=blue penwidth=2];
    "remove_each_doc" -> "env-purge-doc";
    "env-before-read-docs"[style=filled fillcolor="#D5FFFF" color=blue penwidth=2];
    "Builder.build":before_read -> "env-before-read-docs";

    // during read phase
    "Builder.read" [label = "Builder.read()"]
    "Builder.build":read -> "Builder.read";
    read_each_doc [shape="ellipse", label="for added | changed"];
    "Builder.read" -> "read_each_doc";
    merge_each_process [
    shape="ellipse", label="for each process\n(parallel only)"
    ];
    "Builder.read" -> merge_each_process;
    "env-updated"[style=filled fillcolor="#D5FFFF" color=blue penwidth=2];
    "Builder.read" -> "env-updated"

    // during read phase, for each document/process
    "env-purge-doc"[style=filled fillcolor="#D5FFFF" color=blue penwidth=2];
    "read_each_doc" -> "env-purge-doc";
    "source-read"[style=filled fillcolor="#D5FFFF" color=blue penwidth=2];
    "read_each_doc" -> "source-read";
    "Include" [label="Include\ndirective"]
    "read_each_doc" -> "Include";
    "include-read"[style=filled fillcolor="#D5FFFF" color=blue penwidth=2];
    "Include" -> "include-read";
    "ObjectDescription" [label="ObjectDescription\ndirective"]
    "read_each_doc" -> "ObjectDescription";
    "object-description-transform"[style=filled fillcolor="#D5FFFF" color=blue penwidth=2];
    "ObjectDescription" -> "object-description-transform";
    "doctree-read"[style=filled fillcolor="#D5FFFF" color=blue penwidth=2];
    "read_each_doc" -> "doctree-read";
    "env-merge-info"[style=filled fillcolor="#D5FFFF" color=blue penwidth=2];
    "merge_each_process" -> "env-merge-info";

    // after read phase
    "env-get-updated"[style=filled fillcolor="#D5FFFF" color=blue penwidth=2];
    "Builder.build":after_read -> "env-get-updated";
    if_read_changes [shape="diamond", label="if changed\ndocuments"];
    "Builder.build":after_read -> if_read_changes;
    if_read_changes -> "cache the\nBuild.Environment";
    "env-check-consistency"[style=filled fillcolor="#D5FFFF" color=blue penwidth=2];
    if_read_changes -> "env-check-consistency";

    // during write phase
    "write-started"[style=filled fillcolor="#D5FFFF" color=blue penwidth=2];
    "Builder.build":write -> "write-started";
    "Builder.write" [label = "Builder.write()"]
    "Builder.build":write -> "Builder.write";
    write_each_doc [shape="ellipse", label="for updated"];
    "Builder.write" -> write_each_doc;
    "ReferenceResolver" [
    label="ReferenceResolver\nPost-transform"
    ]
    write_each_doc -> "ReferenceResolver";
    "missing-reference"[style=filled fillcolor="#D5FFFF" color=blue penwidth=2];
    ReferenceResolver -> "missing-reference";
    "warn-missing-reference"[style=filled fillcolor="#D5FFFF" color=blue penwidth=2];
    ReferenceResolver -> "warn-missing-reference";
    "HyperlinkCollector" [
    label="HyperlinkCollector\nPost-transform"
    ]
    write_each_doc -> "HyperlinkCollector";
    "linkcheck-process-uri"[style=filled fillcolor="#D5FFFF" color=blue penwidth=2];
    HyperlinkCollector -> "linkcheck-process-uri";
    "doctree-resolved"[style=filled fillcolor="#D5FFFF" color=blue penwidth=2];
    write_each_doc -> "doctree-resolved";
    "html-page-context"[style=filled fillcolor="#D5FFFF" color=blue penwidth=2];
    write_each_doc -> "html-page-context";

    // html only
    "html-collect-pages"[style=filled fillcolor="#D5FFFF" color=blue penwidth=2];
    "Builder.build":finalize -> "html-collect-pages";

    // finalize build
    "build-finished"[style=filled fillcolor="#D5FFFF" color=blue penwidth=2];
    "Builder.build":finalize -> "build-finished";

    // constrain layout ordering
    {rank=same "config-inited" "builder-inited"};
    {rank=same; "env-get-outdated" "env-before-read-docs" "env-get-updated"};
    {rank=same; "env-purge-doc" "source-read" "doctree-read", "merge_each_process"};
    {rank=same; "env-updated" "env-check-consistency"};
    {rank=same; "env-merge-info" "write-started" "Builder.write"};
    {rank=max; "build-finished"};
}

Sphinx 核心事件流程

核心事件详情

以下是对这些事件的更详细列表。

config-inited(app, config)
参数:

在配置对象初始化时发出。

在版本 1.8 中添加。

builder-inited(app)
参数:

appSphinx

在创建构建器对象时发出(可作为 app.builder 使用)。

env-get-outdated(app, env, added, changed, removed)
参数:
返回值:

Sequence[str],表示需要重新读取的额外文档名称

在环境确定哪些源文件已更改并应重新读取时发出。addedchangedremoved 是环境已确定的文档名称集。可以返回一个需要重新读取的文档名称列表,以补充这些名称。

在版本 1.1 中添加。

env-purge-doc(app, env, docname)
参数:

在应从环境中清除源文件的所有痕迹时发出,即如果源文件被删除,或者在重新读取源文件之前。这是为了让扩展可以在环境的属性中保留他们自己的缓存。

例如,环境中有一个包含所有模块的缓存。当源文件发生更改时,缓存中与该文件对应的条目将被清除,因为模块声明可能已从文件中删除。

在版本 0.5 中添加。

env-before-read-docs(app, env, docnames)
参数:

在环境确定所有已添加和已更改文件的列表,以及在开始读取这些文件之前发出。它允许扩展作者在处理之前重新排序文档名称列表(就地),或者添加 Sphinx 未认为已更改的更多文档名称(但永远不要添加不在 found_docs 中的任何文档名称)。

也可以删除文档名称;谨慎操作,因为这会导致 Sphinx 将已更改的文件视为未更改。

在版本 1.3 中添加。

source-read(app, docname, content)
参数:
  • appSphinx

  • docnamestr

  • contentlist[str],包含单个元素,表示包含的文件的内容。

在读取源文件时发出。

可以处理 content 并替换此项,以实现源级转换。

例如,如果希望使用 $ 符号来分隔内联数学,如 LaTeX 中那样,可以使用正则表达式将 $...$ 替换为 :math:`...`

在版本 0.5 中添加。

include-read(app, relative_path, parent_docname, content)
参数:
  • appSphinx

  • relative_pathPath,表示相对于 源目录 的包含文件。

  • parent_docname – 包含 include 指令的文档名称的 str

  • contentlist[str],包含单个元素,表示包含的文件的内容。

在使用 include 指令读取文件时发出。

可以处理 content 并替换此项,以转换包含的内容,就像 source-read 事件一样。

在版本 7.2.5 中添加。

另请参阅

include 指令与 source-read 事件。

object-description-transform(app, domain, objtype, contentnode)
参数:

在运行对象描述指令时发出。domainobjtype 参数是字符串,表示对象的描述。contentnode 是该对象的 内容。它可以在就地进行修改。

在版本 2.4 中添加。

doctree-read(app, doctree)
参数:
  • appSphinx

  • doctreedocutils.nodes.document

在环境解析和读取 doctree 后,以及在将 doctree 序列化之前发出。doctree 可以在就地进行修改。

missing-reference(app, env, node, contnode)
参数:
  • appSphinx

  • envBuildEnvironment

  • node – 要解析的 pending_xref 节点。它的 reftypereftargetmodnameclassname 属性决定了引用的类型和目标。

  • contnode – 承载未来引用中文本和格式的节点,应该是返回的引用节点的子节点。

返回值:

要插入文档树中以替代该节点的新节点,或者为 None 以便让其他处理程序尝试。

当无法解析对对象的交叉引用时发出。如果事件处理程序可以解析引用,它应该返回一个新 docutils 节点,以插入文档树中以替代节点 *node*。通常,此节点是 reference 节点,包含 *contnode* 作为子节点。如果处理程序无法解析交叉引用,它可以返回 None 以便让其他处理程序尝试,或者引发 NoUri 以防止其他处理程序尝试并抑制有关此交叉引用未解析的警告。

在版本 0.5 中添加。

warn-missing-reference(app, domain, node)
参数:
返回值:

True 如果发出警告,否则为 None

当无法解析对对象的交叉引用时发出,即使在 missing-reference 之后也是如此。如果事件处理程序可以发出有关缺失引用的警告,它应该返回 True。配置变量 nitpick_ignorenitpick_ignore_regex 会阻止针对相应节点发出事件。

在版本 3.4 中添加。

doctree-resolved(app, doctree, docname)
参数:
  • appSphinx

  • doctreedocutils.nodes.document

  • docnamestr

当文档树被环境“解析”时发出,即所有引用都已解析,并且 TOC 已插入。可以就地修改 *doctree*。

这是替换自定义节点(在编写器中没有访问者方法)的地方,以便它们在编写器遇到它们时不会导致错误。

env-merge-info(app, env, docnames, other)
参数:

此事件仅在启用文档的并行读取时发出。它为每个已读取某些文档的子进程发出一次。

您必须在将数据存储在环境中的自定义位置的扩展中处理此事件。否则,主进程中的环境将不会知道子进程中存储的信息。

*other* 是子进程的环境对象,*env* 是主进程的环境。*docnames* 是已在子进程中读取的文档名称集。

在版本 1.3 中添加。

env-updated(app, env)
参数:
返回值:

可迭代的 str

在读取完所有文档后发出,此时环境和所有文档树现在是最新的。

您可以从处理程序返回可迭代的文档名称。然后将这些文档视为已更新,并在写入阶段(重新)写入。

在版本 0.5 中添加。

在版本 1.3 中更改: 处理程序的返回值现在被使用。

env-get-updated(app, env)
参数:
返回值:

可迭代的 str

当环境确定哪些源文件已更改并应重新读取时发出。您可以返回可迭代的文档名称以重新读取。

env-check-consistency(app, env)
参数:

在一致性检查阶段发出。您可以检查整个文档的元数据的完整性。

在版本 1.6 中添加。

write-started(app, builder)
参数:

在构建器开始解析和写入文档之前发出。

在版本 7.4 中添加。

build-finished(app, exception)
参数:
  • appSphinx

  • exceptionExceptionNone

当构建完成时发出,在 Sphinx 退出之前,通常用于清理。即使构建过程引发异常,此事件也会发出,作为 *exception* 参数给出。在事件处理程序运行后,异常将在应用程序中重新引发。如果构建过程没有引发异常,*exception* 将为 None。这允许根据异常状态自定义清理操作。

在版本 0.5 中添加。

构建器特定事件

这些事件由特定构建器发出。

html-collect-pages(app)
参数:

appSphinx

返回值:

可迭代的 (pagename, context, templatename),其中 *pagename* 和 *templatename* 是字符串,*context* 是一个 dict[str, Any]

当 HTML 构建器开始写入非文档页面时发出。

您可以通过从此事件返回可迭代对象来添加要写入的页面。

在版本 1.0 中添加。

html-page-context(app, pagename, templatename, context, doctree)
参数:
  • appSphinx

  • pagenamestr

  • templatenamestr

  • contextdict[str, Any]

  • doctreedocutils.nodes.documentNone

返回值:

strNone

当 HTML 构建器创建了一个上下文字典来使用它渲染模板时发出 - 这可以用来向上下文中添加自定义元素。

*pagename* 参数是正在渲染的页面的规范名称,即没有 .html 后缀,并且使用斜杠作为路径分隔符。*templatename* 是要渲染的模板的名称,这将是 'page.html',用于来自 reStructuredText 文档的所有页面。

*context* 参数是一个字典,其中包含传递给模板引擎的值,用于渲染页面,并且可以修改以包含自定义值。

*doctree* 参数在从 reStructuredText 文档创建页面时将是一个文档树;当页面仅从 HTML 模板创建时,它将是 None

您可以从处理程序返回一个字符串,它将替换 'page.html' 作为此页面的 HTML 模板。

提示

您可以通过 Sphinx.add_js_file()Sphinx.add_css_file() (自 v3.5.0 起)为特定页面安装 JS/CSS 文件。

在版本 0.4 中添加。

在版本 1.3 中更改: 返回值现在可以指定模板名称。

linkcheck-process-uri(app, uri)
参数:
  • appSphinx

  • uri – 收集的 URI 的 str

返回值:

strNone

当 linkcheck 构建器从文档中收集超链接时发出。

事件处理程序可以通过返回一个字符串来修改 URI。

在版本 4.1 中添加。