Sphinx结合readthdocs.yaml实现定制Read The Docs

Build Filed: TypeError: 'generator'...

我在使用readthdocs.io平台构建sphinx文档时,在2021年10月开始遇到build fail。报错同 Build Failed. TypeError: 'generator' object is not subscriptable #8616

...
TypeError: 'generator' object is not subscriptable

Exception occurred:
  File "/home/docs/checkouts/readthedocs.org/user_builds/diadocsdk-1c/envs/dev/lib/python3.7/site-packages/sphinx/domains/std.py", line 638, in note_labels
    n = node.traverse(addnodes.toctree)[0]
TypeError: 'generator' object is not subscriptable

原因是对于2020年10月之前创建的Sphinx项目,ReadTheDocs(RTD)会使用Sphinx<2的版本,此时如果你更新过pip环境, docutils-0.18 就会不兼容。所以上传到 RTD 平台编译就会失败。不过,在我本地编译的时候,安装的是 docutils==0.17.1 ,所以没有任何问题。

解决方法是明确指定RTD环境,参考 RTD eproducible Builds 特别是 RTD pinning dependencies

  • 在项目目录下添加一个配置文件 .readthedocs.yaml :

# File: .readthedocs.yaml

version: 2

# Build from the docs/ directory with Sphinx
sphinx:
  configuration: source/conf.py

# Explicitly set the version of Python and its requirements
python:
  version: 3.7
  install:
    - requirements: source/requirements.txt

这个配置文件会指定项目需要的安装依赖包

  • 在源代码 sources 目录下添加 requirements.txt :

sphinx
sphinx_rtd_theme
docutils
sphinxnotes-strike
sphinxcontrib-newsfeed
sphinxcontrib-youtube
sphinxcontrib-video
  • 在源代码 sources 目录下添加 environment.yaml 这个文件非常重要,会强制 ReadTheDocs(RTD) 安装和使用指定pip包,这样就能能够避免 docutils 版本冲突:

name: source
channels:
  - conda-forge
  - defaults
dependencies:
  - sphinx==4.2.0
  - pip:
    - sphinx_rtd_theme==1.0.0
    - docutils==0.17.1
    - sphinxnotes-strike==1.0
  • 然后 make html 没有问题后, git push 到github,再观察 ReadTheDocs(RTD) 就会发现build成功了。

python版本指定升级以适配Sphinx

最近一次重新安装了 Python virtualenv ,然后重新生成了 requirements.txt 配置(为了解决版本漏洞)。但是发现Read The Docs平台build失败,从build日志可以看到安装 Sphinx 失败:

安装Sphinx失败
ERROR: No matching distribution found for Sphinx==8.2.3

但是为何线下我自己的sphinx make html 是正常的呢?

注意到 Sphinx==8.2.3 显示的是大写字母的 Sphinx ,我本地的 Python 3.12.4 ,而之前构建RTD时候指定了版本 3.7 。看来现在高版本的Sphinx,安装名从小写的 sphinx 改成了大写的 Sphinx 导致。

那么,修订 .readthedocs.yaml 配置,升级对应 Python 版本:

升级RTD环境的Python版本
# File: .readthedocs.yaml

version: 2

# Build from the docs/ directory with Sphinx
sphinx:
  configuration: source/conf.py

# Explicitly set the version of Python and its requirements
python:
  version: 3.12
  install:
    - requirements: source/requirements.txt

这样重建RTD就能够成功

指定graphviz依赖

:ref:`` 运行需要系统中安装 graphviz 工具,所以也需要对 readthdocs.yaml 设置,否则Read The Docs平台编译会WARNING:

环境中缺乏 graphviz 工具时RTD报错
WARNING: dot command 'dot' cannot be run (needed for graphviz output), check the graphviz_dot setting

类似上述指定python版本,我尝试指定graphviz的安装版本 2.42 :

尝试指定环境安装 graphviz
# File: .readthedocs.yaml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details

# Required
version: 2

# Set the version of Python and other tools you might need
build:
  os: ubuntu-24.04
  tools:
    python: "3.12"
    graphviz: "2.42"

# Build documentation in the source/ directory with Sphinx
sphinx:
  configuration: source/conf.py

# If using Sphinx, optionally build your docs in additional formats such as PDF
# formats:
#    - pdf

# Optionally declare the Python requirements required to build your docs
python:
  install:
    - requirements: source/requirements.txt

但是发现build失败,提示变量错误: 原来Read The Docs 只支持有限的变量: python, nodejs, ruby, rust, golang

不支持 python, nodejs, ruby, rust, golang 以外的变量
 Config file validation error Config validation error in build.tools. 
 Expected one of (python, nodejs, ruby, rust, golang), got type str (graphviz). 
 Double check the type of the value. 
 A string may be required (e.g. "3.10" instead of 3.10)

原来在编译环境中只能指定语言的版本,如果需要安装软件包则使用另外一个分类 apt_packages 可以安装不同的软件包:

通过 apt_packages 安装 graphviz
# File: .readthedocs.yaml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details

# Required
version: 2

# Set the version of Python and other tools you might need
build:
  os: ubuntu-24.04
  tools:
    python: "3.12"
  apt_packages:
    - graphviz

# Build documentation in the source/ directory with Sphinx
sphinx:
  configuration: source/conf.py

# If using Sphinx, optionally build your docs in additional formats such as PDF
# formats:
#    - pdf

# Optionally declare the Python requirements required to build your docs
python:
  install:
    - requirements: source/requirements.txt

参考