From d648dbac3028347e8a3a22996004732615e4fecf Mon Sep 17 00:00:00 2001 From: Shengyu Zhang Date: Sun, 7 Jul 2024 21:40:19 +0800 Subject: [PATCH] intersphinx: Handle the case where intersphinx_cache_limit is negative The documentation said: Set this (intersphinx_cache_limit) to a negative value to cache inventories for unlimited time. In the current implementation, a negative intersphinx_cache_limit causes inventories always expire, this patch ensures that it behaves as documented. --- CHANGES.rst | 4 ++ sphinx/ext/intersphinx/_load.py | 5 ++- tests/test_extensions/test_ext_intersphinx.py | 39 ++++++++++++++++++- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 4f881ac175c..cd0a856e3c9 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -95,6 +95,10 @@ Features added Bugs fixed ---------- +* #12514: intersphinx: fix the meaning of a negative value for + :confval:`intersphinx_cache_limit`. + Patch by Shengyu Zhang. + Testing ------- diff --git a/sphinx/ext/intersphinx/_load.py b/sphinx/ext/intersphinx/_load.py index 518a0062cac..1973de379be 100644 --- a/sphinx/ext/intersphinx/_load.py +++ b/sphinx/ext/intersphinx/_load.py @@ -201,7 +201,10 @@ def _fetch_inventory_group( config: Config, srcdir: Path, ) -> bool: - cache_time = now - config.intersphinx_cache_limit * 86400 + if config.intersphinx_cache_limit < 0: + cache_time = now - config.intersphinx_cache_limit * 86400 + else: + cache_time = 0 updated = False failures = [] diff --git a/tests/test_extensions/test_ext_intersphinx.py b/tests/test_extensions/test_ext_intersphinx.py index 61ac18a81ec..306f4f2fcaf 100644 --- a/tests/test_extensions/test_ext_intersphinx.py +++ b/tests/test_extensions/test_ext_intersphinx.py @@ -3,6 +3,7 @@ from __future__ import annotations import http.server +import time from typing import TYPE_CHECKING from unittest import mock @@ -19,7 +20,13 @@ validate_intersphinx_mapping, ) from sphinx.ext.intersphinx import setup as intersphinx_setup -from sphinx.ext.intersphinx._load import _fetch_inventory, _get_safe_url, _strip_basic_auth +from sphinx.ext.intersphinx._load import ( + _fetch_inventory, + _fetch_inventory_group, + _get_safe_url, + _strip_basic_auth, +) +from sphinx.ext.intersphinx._shared import _IntersphinxProject from sphinx.util.console import strip_colors from tests.test_util.intersphinx_data import ( @@ -665,3 +672,33 @@ def test_intersphinx_role(app): # explicit title assert html.format('index.html#foons') in content + + +if TYPE_CHECKING: + from sphinx.ext.intersphinx._shared import InventoryCacheEntry + + +def test_intersphinx_cache_limit(app): + url = 'https://example.org/' + app.config.intersphinx_cache_limit = -1 + app.config.intersphinx_mapping = { + 'inv': (url, None), + } + # load the inventory and check if it's done correctly + intersphinx_cache: dict[str, InventoryCacheEntry] = { + url: ('', 0, {}), # 0 is a timestamp, make sure the entry is expired + } + validate_intersphinx_mapping(app, app.config) + load_mappings(app) + + now = int(time.time()) + for name, (uri, locations) in app.config.intersphinx_mapping.values(): + project = _IntersphinxProject(name=name, target_uri=uri, locations=locations) + # no need to read from remote + assert not _fetch_inventory_group( + project=project, + cache=intersphinx_cache, + now=now, + config=app.config, + srcdir=app.srcdir, + )