Skip to content

Commit fae9362

Browse files
committed
intersphinx: Allow strict prefix matching
Strictly using prefix for intersphinx links gives a better control on external links - only links explicitely declared will point to the external documentation. Fixes #2068
1 parent f7768d8 commit fae9362

File tree

3 files changed

+33
-0
lines changed

3 files changed

+33
-0
lines changed

doc/usage/extensions/intersphinx.rst

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,20 @@ linking:
148148
exception is raised if the server has not issued a response for timeout
149149
seconds.
150150

151+
.. confval:: intersphinx_strict_prefix
152+
153+
.. versionadded:: 3.6.0
154+
155+
Turn on strict matching of references in Sphinx - all intersphinx links
156+
needs to have a prefix. This disables looking up the non-prefixed targets in
157+
intersphinx and will fail the build if such target is not present.
158+
159+
.. hint::
160+
161+
Strictly using prefix for intersphinx links gives a better control on
162+
external links - only links explicitely declared will point to the
163+
external documentation.
164+
151165

152166
Showing all links of an Intersphinx mapping file
153167
------------------------------------------------

sphinx/ext/intersphinx.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,8 @@ def missing_reference(app: Sphinx, env: BuildEnvironment, node: Element, contnod
301301
full_qualified_name = env.get_domain(domain).get_full_qualified_name(node)
302302
if full_qualified_name:
303303
to_try.append((inventories.named_inventory[setname], full_qualified_name))
304+
elif app.config.intersphinx_strict_prefix:
305+
return None
304306
for inventory, target in to_try:
305307
for objtype in objtypes:
306308
if objtype not in inventory or target not in inventory[objtype]:
@@ -366,6 +368,7 @@ def setup(app: Sphinx) -> Dict[str, Any]:
366368
app.add_config_value('intersphinx_mapping', {}, True)
367369
app.add_config_value('intersphinx_cache_limit', 5, False)
368370
app.add_config_value('intersphinx_timeout', None, False)
371+
app.add_config_value('intersphinx_strict_prefix', False, True)
369372
app.connect('config-inited', normalize_intersphinx_mapping, priority=800)
370373
app.connect('builder-inited', load_mappings)
371374
app.connect('missing-reference', missing_reference)
@@ -386,6 +389,7 @@ def inspect_main(argv: List[str]) -> None:
386389

387390
class MockConfig:
388391
intersphinx_timeout = None # type: int
392+
intersphinx_strict_prefix = False
389393
tls_verify = False
390394
user_agent = None
391395

tests/test_ext_intersphinx.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ def test_missing_reference(tempdir, app, status, warning):
9797
'py3krelparent': ('../../py3k', inv_file), # relative path, parent dir
9898
}
9999
app.config.intersphinx_cache_limit = 0
100+
app.config.intersphinx_strict_prefix = False
100101

101102
# load the inventory and check if it's done correctly
102103
normalize_intersphinx_mapping(app, app.config)
@@ -165,6 +166,13 @@ def test_missing_reference(tempdir, app, status, warning):
165166
rn = reference_check(app, 'std', 'doc', 'docname', 'docname')
166167
assert rn['refuri'] == 'https://docs.python.org/docname.html'
167168

169+
# check resolution when strict prefix is enabled
170+
app.config.intersphinx_strict_prefix = True
171+
rn = reference_check(app, 'py', 'func', 'module1.func', 'foo')
172+
assert rn is None
173+
rn = reference_check(app, 'py', 'func', 'py3k:module1.func', 'foo')
174+
assert rn is not None
175+
168176

169177
def test_missing_reference_pydomain(tempdir, app, status, warning):
170178
inv_file = tempdir / 'inventory'
@@ -173,6 +181,7 @@ def test_missing_reference_pydomain(tempdir, app, status, warning):
173181
'https://docs.python.org/': inv_file,
174182
}
175183
app.config.intersphinx_cache_limit = 0
184+
app.config.intersphinx_strict_prefix = False
176185

177186
# load the inventory and check if it's done correctly
178187
normalize_intersphinx_mapping(app, app.config)
@@ -204,6 +213,7 @@ def test_missing_reference_stddomain(tempdir, app, status, warning):
204213
'cmd': ('https://docs.python.org/', inv_file),
205214
}
206215
app.config.intersphinx_cache_limit = 0
216+
app.config.intersphinx_strict_prefix = False
207217

208218
# load the inventory and check if it's done correctly
209219
normalize_intersphinx_mapping(app, app.config)
@@ -236,6 +246,7 @@ def test_missing_reference_cppdomain(tempdir, app, status, warning):
236246
'https://docs.python.org/': inv_file,
237247
}
238248
app.config.intersphinx_cache_limit = 0
249+
app.config.intersphinx_strict_prefix = False
239250

240251
# load the inventory and check if it's done correctly
241252
normalize_intersphinx_mapping(app, app.config)
@@ -263,6 +274,7 @@ def test_missing_reference_jsdomain(tempdir, app, status, warning):
263274
'https://docs.python.org/': inv_file,
264275
}
265276
app.config.intersphinx_cache_limit = 0
277+
app.config.intersphinx_strict_prefix = False
266278

267279
# load the inventory and check if it's done correctly
268280
normalize_intersphinx_mapping(app, app.config)
@@ -289,6 +301,7 @@ def test_inventory_not_having_version(tempdir, app, status, warning):
289301
'https://docs.python.org/': inv_file,
290302
}
291303
app.config.intersphinx_cache_limit = 0
304+
app.config.intersphinx_strict_prefix = False
292305

293306
# load the inventory and check if it's done correctly
294307
normalize_intersphinx_mapping(app, app.config)
@@ -318,6 +331,7 @@ def test_load_mappings_warnings(tempdir, app, status, warning):
318331
}
319332

320333
app.config.intersphinx_cache_limit = 0
334+
app.config.intersphinx_strict_prefix = False
321335
# load the inventory and check if it's done correctly
322336
normalize_intersphinx_mapping(app, app.config)
323337
load_mappings(app)
@@ -328,6 +342,7 @@ def test_load_mappings_fallback(tempdir, app, status, warning):
328342
inv_file = tempdir / 'inventory'
329343
inv_file.write_bytes(inventory_v2)
330344
app.config.intersphinx_cache_limit = 0
345+
app.config.intersphinx_strict_prefix = False
331346

332347
# connect to invalid path
333348
app.config.intersphinx_mapping = {

0 commit comments

Comments
 (0)