Skip to content

Commit cc1b13c

Browse files
intersphinx: fix flipped use of intersphinx_cache_limit. (#12905)
Co-authored-by: Nico Madysa <[email protected]> Co-authored-by: Adam Turner <[email protected]>
1 parent b2d69a7 commit cc1b13c

File tree

3 files changed

+43
-8
lines changed

3 files changed

+43
-8
lines changed

CHANGES.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@ Bugs fixed
135135
``SOURCE_DATE_EPOCH`` for entries that match the current system clock year,
136136
and disallow substitution of future years.
137137
Patch by James Addison and Adam Turner.
138+
* #12905: intersphinx: fix flipped use of :confval:`intersphinx_cache_limit`,
139+
which always kept the cache for positive values, and always refreshed it for
140+
negative ones.
141+
Patch by Nico Madysa.
138142

139143
Testing
140144
-------

sphinx/ext/intersphinx/_load.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,9 +210,13 @@ def _fetch_inventory_group(
210210
config: Config,
211211
srcdir: Path,
212212
) -> bool:
213-
if config.intersphinx_cache_limit < 0:
213+
if config.intersphinx_cache_limit >= 0:
214+
# Positive value: cache is expired if its timestamp is below
215+
# `now - X days`.
214216
cache_time = now - config.intersphinx_cache_limit * 86400
215217
else:
218+
# Negative value: cache is expired if its timestamp is below
219+
# zero, which is impossible.
216220
cache_time = 0
217221

218222
updated = False

tests/test_extensions/test_ext_intersphinx.py

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -745,30 +745,57 @@ def test_intersphinx_role(app):
745745

746746

747747
@pytest.mark.sphinx('html', testroot='root')
748-
def test_intersphinx_cache_limit(app):
748+
@pytest.mark.parametrize(
749+
('cache_limit', 'expected_expired'),
750+
[
751+
(5, False),
752+
(1, True),
753+
(0, True),
754+
(-1, False),
755+
],
756+
)
757+
def test_intersphinx_cache_limit(app, monkeypatch, cache_limit, expected_expired):
749758
url = 'https://example.org/'
750-
app.config.intersphinx_cache_limit = -1
759+
app.config.intersphinx_cache_limit = cache_limit
751760
app.config.intersphinx_mapping = {
752761
'inv': (url, None),
753762
}
754763
# load the inventory and check if it's done correctly
755764
intersphinx_cache: dict[str, InventoryCacheEntry] = {
756-
url: ('', 0, {}), # 0 is a timestamp, make sure the entry is expired
765+
url: ('inv', 0, {}), # Timestamp of last cache write is zero.
757766
}
758767
validate_intersphinx_mapping(app, app.config)
759-
load_mappings(app)
760768

761-
now = int(time.time())
769+
# The test's `now` is two days after the cache was created.
770+
now = 2 * 86400
771+
monkeypatch.setattr('time.time', lambda: now)
772+
773+
# `_fetch_inventory_group` calls `_fetch_inventory`.
774+
# We replace it with a mock to test whether it has been called.
775+
# If it has been called, it means the cache had expired.
776+
mock_fetch_inventory = mock.Mock(return_value=('inv', now, {}))
777+
monkeypatch.setattr(
778+
'sphinx.ext.intersphinx._load._fetch_inventory', mock_fetch_inventory
779+
)
780+
762781
for name, (uri, locations) in app.config.intersphinx_mapping.values():
763782
project = _IntersphinxProject(name=name, target_uri=uri, locations=locations)
764-
# no need to read from remote
765-
assert not _fetch_inventory_group(
783+
updated = _fetch_inventory_group(
766784
project=project,
767785
cache=intersphinx_cache,
768786
now=now,
769787
config=app.config,
770788
srcdir=app.srcdir,
771789
)
790+
# If we hadn't mocked `_fetch_inventory`, it would've made
791+
# a request to `https://example.org/` and found no inventory
792+
# file. That would've been an error, and `updated` would've been
793+
# False even if the cache had expired. The mock makes it behave
794+
# "correctly".
795+
assert updated is expected_expired
796+
# Double-check: If the cache was expired, `mock_fetch_inventory`
797+
# must've been called.
798+
assert mock_fetch_inventory.called is expected_expired
772799

773800

774801
def test_intersphinx_fetch_inventory_group_url():

0 commit comments

Comments
 (0)