Sphinx 4.0 版本演进全解析:核心特性、破坏性变更与修复清单

原创2026-09-26 11:19:241,387 阅读
文章标签:文档开发工具

Sphinx 4.0 版本演进全解析:核心特性、破坏性变更与修复清单

Sphinx 4.0 是 Sphinx 文档生成器的重要里程碑版本,带来 C 领域关键字解析增强、Python 领域 canonical 机制、autodoc 类型注解能力升级,以及 MathJax 3 迁移等一系列关键变化。本文基于 doc/changes/4.0.rst 变更日志,结合当前仓库源码与配置文档,系统梳理 4.0 系列(4.0.0 → 4.0.3)的新特性、不兼容变更、弃用项与修复内容,帮助升级用户快速评估影响面并完成迁移。

Sphinx 4.0 系列于 2021 年 5 月正式发布(4.0.0 于 2021-05-09,随后在 5 月、7 月相继发布 4.0.1、4.0.2、4.0.3 补丁版本)。这一版本包含三个 beta 迭代(4.0.0b1/b2/b3),大量特性与变更在 beta 阶段即已确定,补丁版本主要聚焦修复。以下按版本逐层展开。

Sphinx 4.0.3:C 领域关键字扩展与回归修复

4.0.3(2021-07-05 发布)是 4.0 系列的最后一个补丁版本,重点完善了 C 领域的语法解析能力,并修复了 4.0 引入的几个回归问题。

新增特性

C23 关键字支持与 c_extra_keywords 配置项

Sphinx 的 C 领域解析器在 sphinx/domains/c/_ids.py 中维护了一份 C 语言关键字表。4.0.3 为这份表补充了 C23 标准新增的关键字 _Decimal32、_Decimal64 和 _Decimal128:

# sphinx/domains/c/_ids.py
_keywords: Set[str] = frozenset({
    ...
    '_Decimal32', '_Decimal64', '_Decimal128',
    '_Generic',
    ...
})

同时新增配置项 c_extra_keywords,允许用户自定义解析器识别为关键字的标识符。在 sphinx/domains/c/init.py 中,该配置的默认值被设为 _macro_keywords:

app.add_config_value(
    'c_extra_keywords',
    _macro_keywords,
    'env',
    types=frozenset({frozenset, list, set, tuple}),
)

_macro_keywords 包含只有在包含对应头文件时才具有关键字语义的宏名(见 sphinx/domains/c/_ids.py):

_macro_keywords: Set[str] = frozenset({
    'alignas', 'alignof', 'bool', 'complex',
    'imaginary', 'noreturn', 'static_assert', 'thread_local',
})

这些标识符(如 alignas、static_assert)严格来说不是 C 语言保留字,而是 <stdalign.h> 等头文件定义的宏,因此默认被当作"准关键字"处理。文档 doc/usage/configuration.rst 给出了完整说明:该配置项类型为 Set<a href="https://link.gitcode.com/i/b8bbea6d1401a6c56afb8d6a9bb85126" target="_blank">str] | Sequence[str],默认值为这 8 个宏名,在 4.0.3 中引入,并在 7.4 版本起允许使用 set 类型。解析器在 [sphinx/domains/c/_parser.py 中检查匹配文本是否为配置的关键字,若用户自定义的关键字与代码中实际使用的标识符冲突,会给出明确错误提示。

# 用法示例(conf.py)
c_extra_keywords = ['my_keyword', 'your_keyword']

修复的 Bug

4.0.3 修复了以下问题:

  • #9330:changeset 领域中 versionchanged 指令的内容为列表时,PDF 构建会报错;
  • #9313:LaTeX 构建中,带合并单元格的复杂表格自 4.0 起损坏,本版本修复;
  • #9305:使用日文引擎构建 PDF 时,反斜杠可能引发 "Improper discretionary list" 错误;
  • #9354:将特殊宏名从关键字列表中移除(呼应 c_extra_keywords 的引入,把 "类关键字宏" 的处理交给用户配置);
  • #9322:PropagateDescDomain 变换触发 KeyError。

Sphinx 4.0.2:Jinja2 3.0 兼容与 manpage 目录行为修正

4.0.2(2021-05-20 发布)以兼容性修正为主。

依赖变更

  • #9216:支持 Jinja2 3.0。此前 Sphinx 与 Jinja2 3.0 存在兼容问题,4.0.2 完成适配;
  • #9222:将 Underscore.js 升级到 1.13.1(HTML 主题依赖的 JavaScript 库)。

不兼容变更

  • #9217:manpage 构建默认不再创建节(section)目录。这一行为通过配置项 man_make_section_directory 控制(详见下文 4.0.0 部分),4.0.2 将默认值恢复为原先行为。

修复的 Bug

  • #9210:并行构建时,viewcode 遇到不可导入的模块会崩溃;
  • #9240:当安装了不支持 pending_xref_condition 节点的扩展并注册了 missing-reference 处理器时,会抛出未知节点(Unknown node)错误。

Sphinx 4.0.1:autodoc 与 i18n 修复

4.0.1(2021-05-11 发布)是 4.0.0 发布两天后的快速修复版本,全部为 Bug 修复:

  • #9189:autodoc 在从类属性(property)生成签名时抛出 ValueError 会崩溃;
  • #9188:autosummary_generate 设置为列表值时发出警告;
  • #8380:HTML 搜索结果标签损坏;
  • #9198:i18n 在运行 compile_catalog 时 Babel 报错;
  • #9205:Python 领域 :canonical: 选项导致 "more than one target for cross-reference" 警告;
  • #9201:websupport 抛出 UndefinedError: 'css_tag' is undefined。

Sphinx 4.0.0 主版本:不兼容变更全景

4.0.0(2021-05-09 发布)是包含大量破坏性变更的主版本,涉及 Python 版本支持、Docutils 依赖、HTML 输出、LaTeX 引擎、Python 领域等多个方面。升级前务必逐项核对。

依赖与运行环境变化

4.0.0 的依赖调整分为两个 beta 阶段:

4.0.0b1:

  • 移除 Python 3.5 支持;
  • 移除 Docutils 0.12 和 0.13 支持;
  • LaTeX 新增 tex-gyre 字体依赖。

4.0.0b2:

  • 支持 Docutils 0.17。注意:Docutils 0.17 改变了 HTML builder 的输出,部分主题不兼容,升级时需要更新自定义 CSS。

关键不兼容变更清单

以下变更按影响面分类梳理:

autodoc 与类型注解

  • #8539:当同时设置 autodoc_typehints='description' 与 autoclass_content='class' 时,info-field-list 会生成到类描述中;
  • #7383:autodoc 支持为 property(属性)生成类型注解;
  • #5603:允许通过 canonical 名称引用同时拥有规范名与别名的 Python 类;
  • #8539:新增配置项 autodoc_typehints_description_target,用于控制 autodoc_typehints=description 的行为;
  • #8841:autodoc_docstring_signature 在没有反斜杠续行的情况下也能继续查找多行签名;
  • #8924:autodoc 支持 TypeVar 的 bound 参数。

Python 领域(py domain)

  • #4826:Python 对象结构改变——增加一个布尔值用于标记对象是否为 canonical(规范)对象;
  • #4826:为 Python 指令新增 :canonical: 选项,用于描述对象定义的位置;
  • #7199:新增 py:property 指令,用于描述 property;
  • #7199:新增配置项 python_use_unqualified_type_names(实验性),当引用可以解析时抑制 Python 引用的模块名;
  • #5977::var:、:cvar: 和 :ivar: 字段不再创建交叉引用;
  • #8127:info-field-list 中的省略号(Ellipsis)会触发 nitpicky 警告(b2 修复)。

HTML 输出与主题

  • #7849:html_codeblock_linenos_style 默认值改为 'inline';
  • #8380:搜索结果由 <div> 包裹改为 <p> 包裹;
  • 基础主题 layout.html 中 documentation_options.js 的 script 标签移入 script_files 变量;
  • 基础主题 layout.html 中的 CSS 标签移入 css_files 变量;
  • #8915:对 sphinx_rtd_theme 0.2.4 及更早版本发出警告;
  • #9023:更改 cpp:expr 与 cpp:texpr 的 CSS 类(b2)。

LaTeX

  • #8508:日文文档的 latex_engine 默认设置为 uplatex;
  • #8769:LaTeX 重构——sphinx.sty 拆分为多个文件,并重命名 latex 构建输出目录中的部分辅助文件;
  • #8937:使用显式标题替代 <no title>。

i18n 与其他

  • #7784:图片 alt 文本的 msgid 改变,且默认翻译(无需 gettext_additional_targets 设置);
  • #4550:figure 与 table 节点的 align 属性默认值由 'default' 改为 None;
  • #8487:csv-table 指令的 :file: 选项现在把绝对路径当作相对于源目录的路径处理;
  • #8326:master_doc 更名为 root_doc;
  • #8201:toctree 包含重复条目时发出警告;
  • #8342:为指令或角色指定未知领域时发出警告(如 :unknown:doc:);
  • #8898:extlinks 的链接标题字符串中 %s 成为必需关键字(同时支持 %s 出现在链接标题中);
  • domain 的 Index 类成为 abc.ABC 的子类,明确指示具体类必须覆盖的方法。

man_make_section_directory:一次默认值往返

manpage 目录行为的变更值得单独说明。该配置项在 3.3 引入(见 doc/changes/3.3.rst),4.0.0 将其默认值从 True 改为 False(不再创建节目录),4.0.2 又恢复为 True(见 doc/usage/configuration.rst)。

当前仓库中 sphinx/builders/manpage.py 的实现展示了该配置对输出路径的实际影响:

if self.config.man_make_section_directory:
    dirname = 'man%s' % section
    ensuredir(self.outdir / dirname)
    targetname = f'{dirname}/{name}.{section}'
else:
    targetname = f'{name}.{section}'

即当配置为 True 时,manpage 输出为 man{section}/{name}.{section} 形式;为 False 时直接输出 {name}.{section}。当前默认值为 True。该配置在 sphinx/builders/manpage.py 中注册:

'man_make_section_directory', False, '', types=frozenset({bool})

(注意注册处的默认参数 False 是 4.0.2 之后的最终值,文档中标注的默认值为 True 的差异以实际发布版本为准——这一往返变化本身正是升级时需要留意的典型不兼容点。)

弃用项(Deprecated)清单

4.0.0 正式弃用以下内容,升级到后续版本(尤其是 5.0)前应逐步清理:

弃用项 说明
html_codeblock_linenos_style HTML 代码块行号样式配置
favicon 与 logo 模板变量 HTML 模板变量
sphinx.directives.patches.CSVTable 指令补丁
sphinx.directives.patches.ListTable 指令补丁
sphinx.directives.patches.RSTTable 指令补丁
DocumenterBridge.filename_set autodoc 内部接口
DocumenterBridge.warn() autodoc 内部接口
SphinxComponentRegistry.get_source_input() 组件注册表接口
SphinxComponentRegistry.source_inputs 组件注册表接口
sphinx.transforms.FigureAligner 变换类
sphinx.util.pycompat.convert_with_2to3() 兼容工具函数
sphinx.util.pycompat.execfile_() 兼容工具函数
sphinx.util.smartypants 工具模块
sphinx.util.typing.DirectiveOption 类型定义

4.0.0 新增特性详解

autodoc:类型注解体系全面增强

4.0.0 是 autodoc 类型注解能力的分水岭。除上文列出的 autodoc_typehints_description_target 配置与 TypeVar bound 支持外,还包含:

  • #7383:property 类型注解支持,允许在文档中直接呈现类属性的类型;
  • #5603:canonical 名称引用,类存在别名时可按规范名引用;
  • #8818(b2):超类包含 Any 参数时不再触发 nitpicky 警告;
  • #9095(b2):处理损坏的 metaclass 时不再抛出 TypeError;
  • #9110(b2):GenericAlias 元数据在 py37+ 下作为引用渲染。

Python 领域:canonical 机制与实验性类型名优化

  • :canonical: 选项与 python_use_unqualified_type_names 配置的加入,让文档作者能够更精确地控制 Python 对象定位与类型名展示;
  • py:property 指令补全了 Python 领域对 property 的描述能力;
  • #9121(b2):当 canonical 对象与其别名对象同时定义在文档中时,不再重复发出警告。

MathJax 2 → 3 迁移

  • #7425:MathJax 从 2 升级到 3。使用自定义 MathJax 配置的用户需要将旧的 MathJax 路径指向 3,或更新配置;
  • #8195(b2):mathjax_config 重命名为 mathjax2_config,并新增 mathjax3_config,对应两代 MathJax 的独立配置入口(详见 sphinx/ext/mathjax.py)。

HTML 搜索与主题

  • #8070:支持搜索 2 字符单词;
  • #9036:允许继承搜索页面;
  • #2018:html_favicon 与 html_logo 接受 URL 形式的图片地址;
  • #8905(b1 修复):html_add_permalinks=None 与 html_add_permalinks="" 不再被忽略。

其他特性

  • #7199:新增节点 sphinx.addnodes.pending_xref_condition,可按条件选择合适的引用内容;
  • #8942:C++ 支持 C++20 三路比较运算符 <=>(spaceship operator);
  • #8938:imgconverter 显示命令可用性检查的错误信息;
  • #7830:为源码与模板变更检测添加调试日志;
  • #7549:autosummary 的 autosummary_generate 默认启用。

4.0.0 修复的 Bug(按构建目标归纳)

LaTeX 相关(数量最多,反映 4.0 对 LaTeX 后端的大量重构):

  • #7241:cpp:enumerator 不换行;
  • #8711:代码块中的反引号在 TeXLive 2019 下触发 pdf 构建警告并改变字体;
  • #8253:未指定尺寸的图片被过度放大(仅对 pdflatex/lualatex 修复);
  • #8881:PDF 书签面板深度不足以支撑导航;
  • #8874:Pygments LaTeXFormatter 两处输出问题忽略 Pygments 样式;
  • #8925:3.5.0 的 verbatimmaxunderfull 设置未按预期工作;
  • #8980:\pysigline 缺少换行;
  • #8995:旧版 \pysiglinewithargsret 的水平空间计算错误,应使用 ragged right 样式;
  • #9009:release 值含下划线导致无效 LaTeX。

C/C++ 领域相关:

  • #8911:cpp_index_common_prefix 改为移除最长匹配前缀而非首个匹配;
  • 正确拒绝将关键字用作参数名的函数声明;
  • #8933:viewcode 在并行构建下无法创建回链;
  • #8960:修复函数参数列表中(成员)函数指针类型的渲染;
  • 修复数组声明符、指向成员(函数)的指针声明符及 sizeof... 参数中的名称链接;
  • C 领域数组声明符中的名称链接修复;
  • b2:当 alias 指令是文件中第一个 C/C++ 指令、且其后还有其他 C/C++ 指令时,不再抛出 KeyError。

HTML 相关:

  • #9098(b2):Safari 中 doctest 的 copy-range 保护不生效;
  • #9167(b3):特定页面添加 CSS 文件失败;
  • #8915:sphinx_rtd_theme 的翻译失效。

autodoc 相关:

  • #8917:函数 __globals__ 值错误时发出警告;
  • #8415:从其他模块导入的 TypeVar(Python 3.7+)无法解析;
  • #8992:无法解析 types.TracebackType 类型注解。

升级到 Sphinx 4.0 的实践建议

结合上述变更,从 3.x 升级到 4.0 时可参考以下检查清单:

  1. 确认运行环境:Python ≥ 3.6(3.5 已移除),Docutils ≥ 0.14 且建议升级到 0.17(注意 HTML 输出变化);
  2. 检查 LaTeX 构建:日文文档默认引擎变为 uplatex;sphinx.sty 已拆分重构,依赖旧辅助文件的脚本需要调整;
  3. 核对 manpage 输出结构:man_make_section_directory 的默认值在 4.0.0 与 4.0.2 间发生往返变化,请以实际安装版本的行为为准;
  4. 审查 Python 领域文档::canonical: 新选项、py:property 指令、python_use_unqualified_type_names(实验性)按需启用;:var: 等字段不再生成交叉引用;
  5. 迁移 MathJax:使用自定义 MathJax 配置的站点需切换到 mathjax3_config(或保留 mathjax2_config);
  6. 更新主题与 CSS:Docutils 0.17 改变 HTML 输出;基础主题的脚本/CSS 标签位置变化;检查是否依赖已弃用的模板变量 favicon/logo;
  7. 替换弃用 API:对照上文弃用清单,清理 sphinx.util.smartypants、pycompat 相关函数等调用;
  8. 关注 C/C++ 领域:若文档涉及 C23 关键字或自定义宏名,可用 c_extra_keywords 灵活配置(4.0.3+)。

结语

Sphinx 4.0 是一个"承上启下"的版本:它完成了 MathJax 3、Docutils 0.17、Jinja2 3.0 等关键依赖的现代化,重构了 LaTeX 后端与 Python 领域结构,也为后续 5.0 的大规模弃用清理铺平了道路。理解 4.0 系列逐版本的变化脉络(尤其是 4.0.0 的破坏性变更、4.0.2 的默认值回调、4.0.3 的 C 领域完善),是平滑升级与正确解读后续版本变更日志的基础。相关细节可继续查阅 doc/changes/ 目录下的系列变更记录。

登录后查看全文
sphinx