尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Sphinx 扩展开发 How-to 指南:依赖其他扩展与通过入口点注册 Builder

Sphinx 扩展开发 How-to 指南:依赖其他扩展与通过入口点注册 Builder 文档开发工具【免费下载链接】sphinxThe Sphinx documentation generator项目地址https://gitcode.com/gh_mirrors/sp/sphinx点击查看免费下载本文是 Sphinx 官方开发者文档 doc/development/howtos/index.rst 的深度解读聚焦于扩展开发者最常遇到的两个问题如何在扩展内部按需激活另一个扩展setup_extension以及如何通过 Python 入口点entry point让自定义 builder 在sphinx-build命令行下被自动发现。读完本文你将能够写出不依赖用户conf.py配置、可独立分发的 Sphinx 扩展与自定义 builder。Sphinx 为扩展开发提供了完整的 API入口在 sphinx/application.py 的Sphinx类其中setup_extension与add_builder是构建可组合扩展的两块基石。本文结合源码实现细节逐一说明其用法、约束与最佳实践。如何依赖另一个扩展setup_extension的运行时激活问题背景扩展开发者的配置困境普通用户要启用 Sphinx 扩展只需在项目的conf.py的extensions列表中加入模块名即可。但对于扩展开发者而言这个路径行不通你的扩展在用户的conf.py里可能只出现一次即你自己的扩展名你无法控制用户为你的扩展额外填写你依赖的其他扩展名。当你的扩展需要复用另一个 Sphinx 扩展的功能时例如需要sphinx.ext.autodoc的文档生成能力如果只依赖用户手动配置会出现扩展已安装但未激活的静默失败。解决方案在setup()中调用app.setup_extension()Sphinx 提供了Sphinx.setup_extension(extname)方法用于在运行时主动激活另一个扩展。其源码实现位于 sphinx/application.pydef setup_extension(self, extname: str) - None: Import and setup a Sphinx extension module. Load the extension given by the module *name*. Use this if your extension needs the features provided by another extension. No-op if called twice. logger.debug([app] setting up extension: %r, extname) self.registry.load_extension(self, extname)官方文档给出的标准用法见 setup_extension.rstdef setup(app): app.setup_extension(sphinx.ext.autodoc)setup()函数是每个 Sphinx 扩展的入口Sphinx 会在加载扩展时调用它。在上述代码中你的扩展一旦被激活就会立刻把sphinx.ext.autodoc也加载并初始化之后你就可以放心地使用 autodoc 提供的指令、角色与事件。底层原理Registry.load_extension的幂等与错误处理setup_extension实际委托给Registry.load_extension实现于 sphinx/registry.py。理解这段源码有助于你正确使用该 API幂等加载No-op if called twice源码首先检查if extname in app.extensions: return因此同一扩展重复调用setup_extension是安全的不会重复执行其setup()。黑名单处理若目标扩展位于EXTENSION_BLACKLIST已被合并进 Sphinx 核心的旧扩展会打印 warning 并跳过。导入失败处理import_module失败时会抛出ExtensionError提示Could not import extension。这意味着被依赖扩展必须确实可导入否则你的扩展激活时构建会直接失败。缺少setup()的处理模块能导入但没有setup()函数时会输出 warningis it really a Sphinx extension module?此时扩展会被注册为空的元数据。版本检查若被依赖扩展调用了Sphinx.require_sphinx()进行最低版本校验而当前 Sphinx 过旧会抛出VersionRequirementError错误信息会带上扩展名。关键提醒把被依赖扩展写进安装依赖文档的 note 强调了一个容易被忽略的部署要点Since your extension will depend on another, make sure to include it as a part of your extensions installation requirements.setup_extension只负责运行时激活不负责安装。如果你的扩展依赖sphinx.ext.autodoc但用户的 Sphinx 是完整安装autodoc 随 Sphinx 发行这通常没有问题但如果你依赖的是第三方扩展如sphinxcontrib-*系列必须在你的pyproject.toml或setup.py的dependencies中声明它否则用户安装你的扩展时不会自动带上被依赖扩展运行时导入必然失败。这是编写可分发扩展时最常见的坑之一。通过入口点发现 Builder为什么需要入口点发现机制传统上用户使用自定义 builder 必须在conf.py的extensions列表中显式声明扩展模块。Sphinx 自 1.6 版本起versionadded:: 1.6引入了基于 Python 入口点entry points的 builder 发现机制只要你的 builder 扩展被安装sphinx-build就能直接按名字找到它用户无需在extensions中列出。声明方式pyproject.toml中的sphinx.builders组builder 扩展需要在pyproject.toml中定义一个位于sphinx.builders组的入口点原文档见 builders.rst[project.entry-points.sphinx.builders] mybuilder my.extension.module这里有三条硬性约束入口点名称必须与 builder 类的name属性一致。Builder.name是构建器在sphinx-build -b name命令行中使用的名字。入口点值必须是扩展模块的点分路径dotted name即my.extension.module而不是类名。仍然必须在扩展的setup()函数中调用app.add_builder()注册 builder 类。入口点只负责发现模块真正的注册逻辑仍在setup()里完成。源码中的发现与加载链路入口点发现机制的完整实现位于 sphinx/registry.pydef preload_builder(self, app: Sphinx, name: str) - None: if name is None: return if name not in self.builders: builder_entry_points entry_points(groupsphinx.builders) try: entry_point builder_entry_points[name] except KeyError as exc: raise SphinxError( __(Builder name %s not registered or available through entry point) % name ) from exc self.load_extension(app, entry_point.module) def create_builder(self, app: Sphinx, name: str, env: BuildEnvironment) - Builder: if name not in self.builders: raise SphinxError(__(Builder name %s not registered) % name) return self.buildersname调用链路如下sphinx-build -b mybuilder启动时Sphinx.create_builder(name)sphinx/application.py将名字传给Registry.create_builder。create_builder发现mybuilder尚未注册于是调用preload_builder。preload_builder通过entry_points(groupsphinx.builders)查询已安装的入口点按名称取到对应入口点并调用load_extension(app, entry_point.module)加载该模块——这会执行模块的setup()函数从而触发app.add_builder()完成注册。若入口点不存在则抛出SphinxError提示 Builder name %s not registered or available through entry point。add_builder的注册逻辑sphinx/registry.py还会做两类校验注册的 builder 类必须具有name属性否则抛出ExtensionError若同名 builder 已存在且未传overrideTrue抛出ExtensionError同名冲突保护。Sphinx.add_builder自 1.8 起支持override关键字见 sphinx/application.py。完整的自定义 builder 示例结合入口点机制与add_builder一个最小可用的自定义 builder 扩展包含两部分。扩展模块my/extension/module.pyfrom sphinx.builders import Builder class MyBuilder(Builder): name mybuilder # 与入口点名称、-b 参数一致 format html epilog My builder finished. def init(self): pass def get_outdated_docs(self): return self.env.found_docs def write(self, *ignored): for docname in self.env.found_docs: # 这里实现具体的输出逻辑 pass def setup(app): app.add_builder(MyBuilder) return { version: 0.1, parallel_read_safe: True, parallel_write_safe: True, }pyproject.toml声明入口点[project] name my-sphinx-extension version 0.1.0 [project.entry-points.sphinx.builders] mybuilder my.extension.module安装该扩展后用户即可直接运行sphinx-build -b mybuilder source/ build/无需在用户的conf.py中配置任何内容。两个 How-to 的配套上下文setup_extension与 builder 入口点机制共同服务于 Sphinx 的扩展生态用setup_extension可以实现扩展叠加扩展的组合式设计但务必把被依赖扩展写入安装依赖setup_extension.rst。用sphinx.builders入口点可以让自定义 builder 像内置 builder 一样即装即用但注册动作本身仍需add_builderbuilders.rst。若希望进一步深入可参考 sphinx/application.py 中Sphinx类的其余扩展点add_config_value、add_directive、add_role、add_node、add_domain等以及 Sphinx 自带的 builder 实现如 sphinx/builders/html/init.py作为自定义 builder 的参考模板。总结本文围绕官方 How-to 文档讲解了两个扩展开发要点setup_extension用于在运行时激活依赖扩展且具备幂等性其底层由 sphinx/registry.py 的load_extension实现sphinx.builders入口点自 Sphinx 1.6 起允许 builder 被自动发现其加载链路贯穿 sphinx/registry.py 的preload_builder与create_builder。掌握了这两项能力你的扩展就能做到零配置激活依赖、builder 即装即用真正达到生产级可分发的标准。赞分享文档开发工具【免费下载链接】sphinxThe Sphinx documentation generator项目地址https://gitcode.com/gh_mirrors/sp/sphinx点击查看免费下载相关推荐北京昇腾GPT-2性能优化指南ONNX/TFLite模型转换与部署加速北京昇腾GPT 2性能优化指南ONNX/TFLite模型转换与部署加速 北京昇腾GPT 2是基于HuggingFace GPT 2的优化版本特别针对昇腾NPTars依赖注入框架扩展自定义注入逻辑与扩展点实践Tars依赖注入框架扩展自定义注入逻辑与扩展点实践 你是否在使用Tars框架时遇到依赖注入逻辑无法满足业务需求的情况是否需要针对特定场景定制对象创建规则本后端微服务终极Redoc规范扩展指南从x-tagGroups到高级API文档定制终极Redoc规范扩展指南从x tagGroups到高级API文档定制 Redoc作为一款强大的OpenAPI文档生成工具通过其丰富的规范扩展功能帮助开发API设计文档前端上一篇Highlight.io 接入 Salesforce LWCHead Markup、CSP 与 Trusted URLs 的完整配置指南下一篇从一条大 Prompt 到多智能体分工500-AI-Agents-Projects 完整拆解创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表