pydeck 文档生成管线:从示例脚本到 Sphinx 文档画廊的三层自动化流程
【免费下载链接】deck.glWebGL2 powered visualization framework项目地址: https://gitcode.com/GitHub_Trending/de/deck.gl
本文以 bindings/pydeck/docs/scripts/README.md 为核心,系统讲解 pydeck 官方文档站中“示例画廊”的自动化生成机制:embed_examples.py如何把示例脚本转成内嵌源码与交互画面的 .rst 页面、generate_grid_html.py如何聚合生成画廊落地页、snap_thumbnails.py如何为每个示例截取缩略图。读完本文,你可以独立复现整套文档构建流程,并按 README 给出的标准步骤把一个新的示例图层加入 pydeck 画廊。
1. 管线概览:三层脚本与目录约定
bindings/pydeck/docs/scripts/README.md 开篇即点明定位:这是一个“为生成 pydeck 文档服务的辅助脚本集”。整套管线由三个阶段组成,每个阶段对应一个脚本:
| 阶段 | 脚本 | 产物 |
|---|---|---|
| 1. 页面嵌入 | embed_examples.py | 一组 .rst 文件,每个文件同时内嵌示例源码与可交互的 HTML 实例(点击画廊单元格后看到的页面) |
| 2. 画廊网格 | generate_grid_html.py | grid.html,以缩略图为单元、按分组组织的链接网格,即 pydeck 文档站的落地页 |
| 3. 缩略图 | snap_thumbnails.py | 画廊中使用的 .png 缩略图,从示例的实际渲染结果截图生成 |
目录约定集中定义在 const.py,理解它是理解整条管线的前提:
EXAMPLES_DIR:pydeck 示例目录 bindings/pydeck/examples(L7);EXAMPLE_GLOB:递归收集examples/下(含子目录)的全部*.py示例文件(L13)。子目录会成为画廊上的分组标签,而网格、页面、缩略图的命名仍以每个文件的基本名为键,因此按子文件夹组织示例只影响分组、不破坏命名体系(L9-L12 的注释说明了这一设计);GALLERY_DIR:画廊 .rst 页面目录docs/gallery/(L50);HTML_DIR:画廊 HTML 文件目录docs/gallery/html/(L52);LOCAL_IMAGE_DIR:缩略图目录docs/gallery/images/(L54);DECKGL_URL_BASE:deck.gl API 参考文档基址,用于给图层示例页挂回链(L58)。
此外,const.py 还定义了网格分组逻辑:DEFAULT_GROUP = "Layers"表示直接放在examples/根下的示例归入 “Layers” 分组;GROUP_ORDER = ["Layers", "Extensions"]固定前两个分区的顺序,其余分组按字母序排列。grouped_examples()据此返回有序(section_label, [snake_case 名称])列表——例如仓库中的 extensions 子目录(含 8 个扩展示例)与 post_processing 子目录(19 个示例)就各自形成独立分区。
还有一处 README 未提及但同样重要的环节:update_images_rst.py 会基于EXAMPLE_NAMES重新渲染 docs/images.rst。该文件头部注释表明其职责是“把示例缩略图注册进_static目录,并把示例页面登记进一个隐藏 toctree”——这正是 Sphinx 能收录gallery/images/*.png与gallery/*.rst的依据,当前仓库中的 images.rst 即为该脚本的产物(含a5_layer、arc_layer、binary_transport等条目的.. image::注册与.. toctree::列表)。
2. 第一阶段:embed_examples.py——示例脚本到 .rst 页面
embed_examples.py 的模块 docstring 说明了它的作用:“这些文件就是你在 pydeck 画廊页点击某个网格单元格后看到的页面”。核心函数create_rst()(L18-L47)对每个示例文件做四件事:
- 命名规范化:
to_snake_case_string()去掉路径与扩展名得到 snake_case 资产名(utils.py L13-L15);若名称中含layer,则拼出 deck.gl 文档回链(L21-L25)。源码注释坦承这一判断“相当粗糙”,后续计划扩展以支持 views 等对象——因此回链只对图层示例生效; - 运行示例并归档 HTML:通过
subprocess执行python {示例文件}; mv {html} {HTML_DIR}(L29-L34)。示例脚本本身在顶层目录生成同名.html(deck 前端由 Jupyter widget 的write_notebook等机制导出),随后被移入docs/gallery/html/; - 渲染 .rst 页面:读取示例 Python 源码,用 templates.py 中的
DOC_TEMPLATE(L46-L84)生成文档源。该模板的结构值得注意:- 可选的 deck.gl 文档外链(
.. raw:: html中的<a id="deck-link">); .. raw:: html :file: ./html/{snake_name}.html——把上一步归档的 HTML 文件原样内嵌,实现“文档页里直接运行示例”;- 内联样式约束:
#deck-container { height: 50vh; width: 100% }以及让.wy-nav-content撑满宽度的max-width: 100% !important,保证交互实例在 Sphinx 布局中有足够画幅; - “Source” 小节,以
.. code-block:: python输出完整示例源码;
- 可选的 deck.gl 文档外链(
- 写盘:输出到
docs/gallery/{资产名}.rst。
入口main()(L50-L56)使用multiprocessing.Pool(processes=4)并行处理EXAMPLE_GLOB中全部文件,并在转换前mkdir -p建好 HTML 输出目录;若一个示例文件都找不到会直接抛异常终止。页面标题由to_presentation_name()(utils.py L4-L10)生成:名称含layer或view时做驼峰化处理(并特判把json显示为Json),其余情况做 title case。
对应的构建入口是 docs/Makefile 的html-embeds目标,它直接调用python scripts/embed_examples.py。
3. 第二阶段:generate_grid_html.py——画廊落地页
generate_grid_html.py 逻辑非常薄:调用HTML_TEMPLATE.render(grouped_examples=grouped_examples(), ...)并把结果写入docs/gallery/grid.html(L10-L13)。复杂度都在模板侧,HTML_TEMPLATE(templates.py L3-L43)要点:
- 外层用 CSS Grid 布局:
grid-template-columns: repeat(3, 1fr)、grid-gap: 20px,即三列卡片; - 按分组循环:每个分组输出
<h2 class='gallery-section-title'>标题(分节顺序与标签即来自第 1 节所述grouped_examples()); - 每个单元格链接到
./gallery/{名称}.html,卡片内容是 200px 宽的缩略图./_images/{名称}.png加标题文本to_presentation_name(名称); - 还带了一个悬停特效
filter: hue-rotate(3.142rad)。
注意链接的相对关系:grid.html位于gallery/内,页面链接指向gallery/{name}.html、图片指向_images/(Sphinx 构建后_images为静态资源目录),与embed_examples.py归档的 HTML、snap_thumbnails.py产出的 PNG 在命名上完全对齐——“以文件基本名为键”的约定在这里收束。该阶段由 Makefile 的html-grid-page目标触发(Makefile L29-L31),它会先执行html-embeds再运行网格生成,保证页面与网格同步更新。
4. 第三阶段:snap_thumbnails.py——Playwright 截图管线
snap_thumbnails.py 为每个示例生成画廊缩略图,其 docstring 直接给出用法(L3-L10):
# 安装依赖(当前代码基线) uv pip install playwright Pillow playwright install chromium # 在 docs/ 目录下 make html-thumbnails # 为全部示例截图 python scripts/snap_thumbnails.py ../examples/widgets.py # 单个示例关键实现细节:
- 依赖切换:脚本在导入
playwright与PIL失败时会打印安装提示并退出(L21-L28)。注意 README 中旧版步骤写的是pip install pyppeteer && pip install Image,而当前源码已迁移到 Playwright + Pillow,实操时应以 docstring 与源码为准; - 大示例白名单:
LARGE_EXAMPLES = ("bitmap_layer", "icon_layer", "heatmap_layer", "terrain_layer", "maplibre_globe")(L32)。这类示例数据集加载慢,截图时不做networkidle等待,改为固定goto后wait_for_timeout(10000);其余示例用wait_until="networkidle", timeout=30000再额外等 3 秒让 deck.gl 完成渲染(L75-L91); - 截图流程:
snap()先经run_example()执行示例脚本、校验退出码与.html产物并移入HTML_DIR,再启动 Chromium(800×600 视口)加载file://页面、wait_for_selector("canvas")确认画布出现后落盘 PNG;外层snap_with_retries()提供 3 次重试(L60-L109); - 尺寸压缩:
shrink_image()用 Pillow 的Image.thumbnail((400, 300), Image.LANCZOS)原地压缩为 400×300 缩略图(L112-L121); - 失败语义:
main()汇总失败列表,只要有任何一个缩略图失败就以RuntimeError终止(L123-L140),保证画廊不出现“有格子无图”的半成品状态。
批量执行的构建入口是 docs/Makefile 的html-thumbnails目标(uv run python scripts/snap_thumbnails.py)。
5. 实操:按 README 步骤把新图层加入画廊
README 的 “Adding a new layer to the gallery” 一节给出了官方流程,结合当前源码可执行如下(以下均在bindings/pydeck/docs/目录下操作):
# 0) 安装截图依赖(README 原文:pip install pyppeteer && pip install Image; # 当前源码已迁移到 Playwright,请按 snap_thumbnails.py docstring 安装) uv pip install playwright Pillow && playwright install chromium # 1) 把新示例(如 examples/arc_layer.py)注册进 docs/images.rst # images.rst 由 update_images_rst.py 自动生成(注册缩略图 + 隐藏 toctree) python scripts/update_images_rst.py # 2) 生成内嵌页面与画廊网格 make html-grid-page # 3) 为新示例创建缩略图 python scripts/snap_thumbnails.py ../examples/arc_layer.py # 若需要为多个示例文件建缩略图: make html-thumbnails各步骤与源码的对应关系:
- 注册
images.rst:README 要求手工维护 docs/images.rst,而该文件实际由 update_images_rst.py 从EXAMPLE_NAMES重新渲染,新增示例后重新生成即可保证图片注册与 toctree 条目齐全; make html-grid-page:等价于先跑embed_examples.py(新示例获得gallery/{名称}.rst与gallery/html/{名称}.html)再跑generate_grid_html.py(网格出现新单元格);- 缩略图:单个示例走
python scripts/snap_thumbnails.py ../examples/{名称}.py,批量走make html-thumbnails;产物落入docs/gallery/images/{名称}.png,与网格模板中./_images/{名称}.png的引用同名对齐。
6. 小结:管线约定与扩展点
整条管线的可维护性建立在几条严格约定之上:
- 命名即契约:示例文件基本名(snake_case)贯穿 HTML、.rst、PNG 与 toctree 四个产物,
to_snake_case_string/to_presentation_name只负责展示层转换; - 分组即目录:
examples/子目录名(下划线转空格后 title-case)决定画廊分区,GROUP_ORDER固定 “Layers”“Extensions” 的展示顺序; - 失败即终止:
embed_examples.py对“无示例文件”抛异常,snap_thumbnails.py对任何缩略图失败抛RuntimeError,避免文档站以不完整状态发布。
常见扩展点:为大数据集示例加长等待时间(修改LARGE_EXAMPLES元组)、调整缩略图尺寸(THUMBNAIL_SIZE = (400, 300))、调整网格列数(HTML_TEMPLATE中的repeat(3, 1fr)),以及把embed_examples.py中粗糙的layer字符串判断扩展为按视图等对象类型挂 deck.gl 回链。所有相关脚本集中在 docs/scripts/ 目录,配合 docs/Makefile 的三个html-*目标即可完成一次完整的文档画廊再生成。
【免费下载链接】deck.glWebGL2 powered visualization framework项目地址: https://gitcode.com/GitHub_Trending/de/deck.gl
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考