Skip to content

Commit 70eabb7

Browse files
committed
Introduce a restricted subset of Config, _InvConfig
1 parent 619a10e commit 70eabb7

File tree

3 files changed

+44
-18
lines changed

3 files changed

+44
-18
lines changed

sphinx/ext/intersphinx/_cli.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import sys
66
from pathlib import Path
77

8-
from sphinx.ext.intersphinx._load import _fetch_inventory
8+
from sphinx.ext.intersphinx._load import _fetch_inventory, _InvConfig
99

1010

1111
def inspect_main(argv: list[str], /) -> int:
@@ -18,18 +18,20 @@ def inspect_main(argv: list[str], /) -> int:
1818
)
1919
return 1
2020

21-
class MockConfig:
22-
intersphinx_timeout: int | None = None
23-
tls_verify = False
24-
tls_cacerts: str | dict[str, str] | None = None
25-
user_agent: str = ''
21+
filename = argv[0]
22+
config = _InvConfig(
23+
intersphinx_cache_limit=5,
24+
intersphinx_timeout=None,
25+
tls_verify=False,
26+
tls_cacerts=None,
27+
user_agent='',
28+
)
2629

2730
try:
28-
filename = argv[0]
2931
inv_data = _fetch_inventory(
3032
target_uri='',
3133
inv_location=filename,
32-
config=MockConfig(), # type: ignore[arg-type]
34+
config=config,
3335
srcdir=Path(''),
3436
)
3537
for key in sorted(inv_data or {}):

sphinx/ext/intersphinx/_load.py

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from __future__ import annotations
44

55
import concurrent.futures
6+
import dataclasses
67
import io
78
import os.path
89
import posixpath
@@ -169,14 +170,15 @@ def load_mappings(app: Sphinx) -> None:
169170
# This happens when the URI in `intersphinx_mapping` is changed.
170171
del intersphinx_cache[uri]
171172

173+
inv_config = _InvConfig.from_config(app.config)
172174
with concurrent.futures.ThreadPoolExecutor() as pool:
173175
futures = [
174176
pool.submit(
175177
_fetch_inventory_group,
176178
project=project,
177179
cache=intersphinx_cache,
178180
now=now,
179-
config=app.config,
181+
config=inv_config,
180182
srcdir=app.srcdir,
181183
)
182184
for project in projects
@@ -201,12 +203,31 @@ def load_mappings(app: Sphinx) -> None:
201203
inventories.main_inventory.setdefault(objtype, {}).update(objects)
202204

203205

206+
@dataclasses.dataclass(frozen=True, kw_only=True, slots=True)
207+
class _InvConfig:
208+
intersphinx_cache_limit: int
209+
intersphinx_timeout: int | float | None
210+
tls_verify: bool
211+
tls_cacerts: str | dict[str, str] | None
212+
user_agent: str
213+
214+
@classmethod
215+
def from_config(cls, config: Config) -> _InvConfig:
216+
return cls(
217+
intersphinx_cache_limit=config.intersphinx_cache_limit,
218+
intersphinx_timeout=config.intersphinx_timeout,
219+
tls_verify=config.tls_verify,
220+
tls_cacerts=config.tls_cacerts,
221+
user_agent=config.user_agent,
222+
)
223+
224+
204225
def _fetch_inventory_group(
205226
*,
206227
project: _IntersphinxProject,
207228
cache: dict[InventoryURI, InventoryCacheEntry],
208229
now: int,
209-
config: Config,
230+
config: _InvConfig,
210231
srcdir: Path,
211232
) -> bool:
212233
if config.intersphinx_cache_limit >= 0:
@@ -283,13 +304,13 @@ def fetch_inventory(app: Sphinx, uri: InventoryURI, inv: str) -> Inventory:
283304
return _fetch_inventory(
284305
target_uri=uri,
285306
inv_location=inv,
286-
config=app.config,
307+
config=_InvConfig.from_config(app.config),
287308
srcdir=app.srcdir,
288309
)
289310

290311

291312
def _fetch_inventory(
292-
*, target_uri: InventoryURI, inv_location: str, config: Config, srcdir: Path
313+
*, target_uri: InventoryURI, inv_location: str, config: _InvConfig, srcdir: Path
293314
) -> Inventory:
294315
"""Fetch, parse and return an intersphinx inventory file."""
295316
# both *target_uri* (base URI of the links to generate)
@@ -315,7 +336,7 @@ def _fetch_inventory(
315336

316337

317338
def _fetch_inventory_url(
318-
*, target_uri: InventoryURI, inv_location: str, config: Config
339+
*, target_uri: InventoryURI, inv_location: str, config: _InvConfig
319340
) -> tuple[bytes, str]:
320341
try:
321342
with requests.get(

tests/test_extensions/test_ext_intersphinx.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
_fetch_inventory,
2626
_fetch_inventory_group,
2727
_get_safe_url,
28+
_InvConfig,
2829
_strip_basic_auth,
2930
)
3031
from sphinx.ext.intersphinx._shared import _IntersphinxProject
@@ -67,6 +68,7 @@ def set_config(app, mapping):
6768
app.config.intersphinx_mapping = mapping.copy()
6869
app.config.intersphinx_cache_limit = 0
6970
app.config.intersphinx_disabled_reftypes = []
71+
app.config.intersphinx_timeout = None
7072

7173

7274
@mock.patch('sphinx.ext.intersphinx._load.InventoryFile')
@@ -82,7 +84,7 @@ def test_fetch_inventory_redirection(get_request, InventoryFile, app):
8284
_fetch_inventory(
8385
target_uri='https://hostname/',
8486
inv_location='https://hostname/' + INVENTORY_FILENAME,
85-
config=app.config,
87+
config=_InvConfig.from_config(app.config),
8688
srcdir=app.srcdir,
8789
)
8890
assert 'intersphinx inventory has moved' not in app.status.getvalue()
@@ -96,7 +98,7 @@ def test_fetch_inventory_redirection(get_request, InventoryFile, app):
9698
_fetch_inventory(
9799
target_uri='https://hostname/',
98100
inv_location='https://hostname/' + INVENTORY_FILENAME,
99-
config=app.config,
101+
config=_InvConfig.from_config(app.config),
100102
srcdir=app.srcdir,
101103
)
102104
assert app.status.getvalue() == (
@@ -114,7 +116,7 @@ def test_fetch_inventory_redirection(get_request, InventoryFile, app):
114116
_fetch_inventory(
115117
target_uri='https://hostname/',
116118
inv_location='https://hostname/new/' + INVENTORY_FILENAME,
117-
config=app.config,
119+
config=_InvConfig.from_config(app.config),
118120
srcdir=app.srcdir,
119121
)
120122
assert 'intersphinx inventory has moved' not in app.status.getvalue()
@@ -128,7 +130,7 @@ def test_fetch_inventory_redirection(get_request, InventoryFile, app):
128130
_fetch_inventory(
129131
target_uri='https://hostname/',
130132
inv_location='https://hostname/new/' + INVENTORY_FILENAME,
131-
config=app.config,
133+
config=_InvConfig.from_config(app.config),
132134
srcdir=app.srcdir,
133135
)
134136
assert app.status.getvalue() == (
@@ -761,6 +763,7 @@ def test_intersphinx_cache_limit(app, monkeypatch, cache_limit, expected_expired
761763
app.config.intersphinx_mapping = {
762764
'inv': (url, None),
763765
}
766+
app.config.intersphinx_timeout = None
764767
# load the inventory and check if it's done correctly
765768
intersphinx_cache: dict[str, InventoryCacheEntry] = {
766769
url: ('inv', 0, {}), # Timestamp of last cache write is zero.
@@ -785,7 +788,7 @@ def test_intersphinx_cache_limit(app, monkeypatch, cache_limit, expected_expired
785788
project=project,
786789
cache=intersphinx_cache,
787790
now=now,
788-
config=app.config,
791+
config=_InvConfig.from_config(app.config),
789792
srcdir=app.srcdir,
790793
)
791794
# If we hadn't mocked `_fetch_inventory`, it would've made

0 commit comments

Comments
 (0)