From 3505b06c2801dd87600cfe95c2709ce77079cf11 Mon Sep 17 00:00:00 2001 From: beykyle Date: Fri, 4 Sep 2026 14:23:21 -0400 Subject: [PATCH] docs: don't fail -W builds when intersphinx inventories are unreachable GitHub runners intermittently time out fetching docs.scipy.org (and friends), and Sphinx logs "failed to reach any of the inventories" without a warning type, so suppress_warnings cannot silence it and sphinx-build -W fails the whole docs build. Install a logging filter on the intersphinx logger in conf.py that drops that one message, and set intersphinx_timeout so a dead host fails fast instead of hanging. Claude-Session: https://claude.ai/code/session_014PvAXNJiHj9E9CiGeH45Pm --- docs/conf.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/docs/conf.py b/docs/conf.py index bd70881e..9e10a87d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -2,8 +2,13 @@ from __future__ import annotations +import logging import sys from pathlib import Path +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from sphinx.application import Sphinx REPO_ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(REPO_ROOT / "src")) @@ -84,6 +89,35 @@ "numpy": ("https://numpy.org/doc/stable", None), "scipy": ("https://docs.scipy.org/doc/scipy", None), } +# Fail fast instead of hanging when an inventory host is unreachable. +intersphinx_timeout = 30 + + +class _IgnoreUnreachableInventories(logging.Filter): + """Drop the intersphinx "failed to reach any of the inventories" warning. + + GitHub runners intermittently cannot reach docs.scipy.org and friends. That + warning is emitted without a Sphinx warning ``type``, so it cannot be + silenced through ``suppress_warnings``; without this filter it turns + ``sphinx-build -W`` into a hard failure. Unresolved cross-references simply + render as plain text when an inventory is missing. + """ + + _PREFIX = "failed to reach any of the inventories" + + def filter(self, record: logging.LogRecord) -> bool: + return not str(record.msg).startswith(self._PREFIX) + + +def setup(app: Sphinx) -> None: + """Install the intersphinx warning filter.""" + + # Sphinx prefixes its logger names with "sphinx."; the intersphinx logger + # has been "sphinx.sphinx.ext.intersphinx" through Sphinx 9. + logging.getLogger("sphinx.sphinx.ext.intersphinx").addFilter( + _IgnoreUnreachableInventories() + ) + html_theme = "furo" html_title = "jitr documentation"