From ec69accd9db9003910f0c65b9cecd497c31b93f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Fri, 10 Jul 2026 12:53:50 +0200 Subject: [PATCH] fix: cache objects.inv to persist it across cached rebuilds (#815) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Mazzucotelli --- crates/zensical/src/workflow.rs | 16 ++++++++++--- python/zensical/compat/mkdocstrings.py | 31 ++++++++++++++++++++------ 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/crates/zensical/src/workflow.rs b/crates/zensical/src/workflow.rs index 198fcdf..f1d97aa 100644 --- a/crates/zensical/src/workflow.rs +++ b/crates/zensical/src/workflow.rs @@ -358,17 +358,27 @@ pub fn generate_object_inventory( // Retrieve inventory from Python interpreter using pyo3 let config = config.clone(); pages.map(move |_| { + let cache_dir = config.get_cache_dir(); + let cache_path = cache_dir.join("objects.inv"); + + // Load previously cached inventory, if any + let cached = fs::read(&cache_path).ok(); + let data = Python::attach(|py| { let module = py.import("zensical.compat.mkdocstrings")?; - module.call_method0("get_inventory")?.extract::>() + module + .call_method1("get_inventory", (cached,))? + .extract::>() }); - // Write object inventory to disk - let site_dir = config.get_site_dir(); + // Write object inventory to disk and update cache if let Ok(data) = data { + let site_dir = config.get_site_dir(); let path = site_dir.join("objects.inv"); let _ = fs::create_dir_all(path.parent().expect("invariant")); let _ = fs::write(path, &data); + let _ = fs::create_dir_all(&cache_dir); + let _ = fs::write(&cache_path, &data); } }); } diff --git a/python/zensical/compat/mkdocstrings.py b/python/zensical/compat/mkdocstrings.py index d93f079..97dd487 100644 --- a/python/zensical/compat/mkdocstrings.py +++ b/python/zensical/compat/mkdocstrings.py @@ -23,6 +23,7 @@ from __future__ import annotations +from io import BytesIO from pathlib import Path from typing import TYPE_CHECKING, Any @@ -103,15 +104,31 @@ def get_mkdocstrings_extension( return MkdocstringsExtension(handlers=HANDLERS, autorefs=autorefs) -def get_inventory() -> bytes: - """Get the objects.inv inventory as bytes. +def get_inventory(cached: bytes | None) -> bytes: + """Get inventory bytes, merging cached entries with fresh handlers data.""" + try: + from mkdocstrings import ( # noqa: PLC0415 # ty:ignore[unresolved-import] + Inventory, + ) + except ImportError: + return cached or b"" - This function is called from Rust to write - the objects.inv file in the site directory. - """ - if HANDLERS: + if HANDLERS is None: + return cached or b"" + + if not cached: return HANDLERS.inventory.format_sphinx() - return b"" + + base = Inventory.parse_sphinx(BytesIO(cached)) + for name, item in HANDLERS.inventory.items(): + base[name] = item + + # Bug in mkdocstrings's `parse_sphinx` method + # not parsing project and version (fixed in latest). + base.project = HANDLERS.inventory.project + base.version = HANDLERS.inventory.version + + return base.format_sphinx() def reset() -> None: