Skip to content

Commit 32c5467

Browse files
committed
Generalize to disable specific refs as well.
1 parent fe6f2d0 commit 32c5467

File tree

4 files changed

+73
-43
lines changed

4 files changed

+73
-43
lines changed

CHANGES

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,11 @@ Features added
2222
* #9691: C, added new info-field ``retval``
2323
for :rst:dir:`c:function` and :rst:dir:`c:macro`.
2424
* C++, added new info-field ``retval`` for :rst:dir:`cpp:function`.
25-
* #2068, add :confval:`intersphinx_disabled_domains` for disabling
26-
interphinx resolution of cross-references in specific domains when they
27-
do not have an explicit inventory specification.
25+
* #2068, add :confval:`intersphinx_disabled_refs` for disabling
26+
interphinx resolution of cross-references that do not have an explicit
27+
inventory specification. Specific types of cross-references can be disabled,
28+
e.g., ``std:doc`` or all cross-references in a specific domain,
29+
e.g., ``std``.
2830

2931
Bugs fixed
3032
----------

doc/usage/extensions/intersphinx.rst

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

151-
.. confval:: intersphinx_disabled_domains
151+
.. confval:: intersphinx_disabled_refs
152152

153-
.. versionadded:: 4.2
153+
.. versionadded:: 4.3
154+
155+
A list of strings being either:
156+
157+
- the name of a specific reference type,
158+
e.g., ``std:doc``, ``py:func``, or ``cpp:class``,
159+
- the name of a whole domain, e.g., ``std``, ``py``, or ``cpp``, or
160+
- the special name ``all``.
154161

155-
A list of strings being the name of a domain, or the special name ``all``.
156162
When a cross-reference without an explicit inventory specification is being
157-
resolved by intersphinx, skip resolution if either the domain of the
158-
cross-reference is in this list or the special name ``all`` is in the list.
159-
160-
For example, with ``intersphinx_disabled_domains = ['std']`` a cross-reference
161-
``:doc:`installation``` will not be attempted to be resolved by intersphinx, but
162-
``:doc:`otherbook:installation``` will be attempted to be resolved in the
163-
inventory named ``otherbook`` in :confval:`intersphinx_mapping`.
164-
At the same time, all cross-references generated in, e.g., Python, declarations
165-
will still be attempted to be resolved by intersphinx.
163+
resolved by intersphinx, skip resolution it matches one of the
164+
specifications in this list.
165+
166+
For example, with ``intersphinx_disabled_refs = ['std:doc']``
167+
a cross-reference ``:doc:`installation``` will not be attempted to be
168+
resolved by intersphinx, but ``:doc:`otherbook:installation``` will be
169+
attempted to be resolved in the inventory named ``otherbook`` in
170+
:confval:`intersphinx_mapping`.
171+
At the same time, all cross-references generated in, e.g., Python,
172+
declarations will still be attempted to be resolved by intersphinx.
166173

167174
If ``all`` is in the list of domains, then no references without an explicit
168175
inventory will be resolved by intersphinx.

sphinx/ext/intersphinx.py

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,9 @@ def _resolve_reference_in_domain_by_target(
321321
return None
322322

323323

324-
def _resolve_reference_in_domain(inv_name: Optional[str], inventory: Inventory,
324+
def _resolve_reference_in_domain(env: BuildEnvironment,
325+
inv_name: Optional[str], inventory: Inventory,
326+
honor_disabled_refs: bool,
325327
domain: Domain, objtypes: List[str],
326328
node: pending_xref, contnode: TextElement
327329
) -> Optional[Element]:
@@ -336,6 +338,11 @@ def _resolve_reference_in_domain(inv_name: Optional[str], inventory: Inventory,
336338
# the inventory contains domain:type as objtype
337339
objtypes = ["{}:{}".format(domain.name, t) for t in objtypes]
338340

341+
# now that the objtypes list is complete we can remove the disabled ones
342+
if honor_disabled_refs:
343+
disabled = env.config.intersphinx_disabled_refs
344+
objtypes = [o for o in objtypes if o not in disabled]
345+
339346
# without qualification
340347
res = _resolve_reference_in_domain_by_target(inv_name, inventory, domain, objtypes,
341348
node['reftarget'], node, contnode)
@@ -351,22 +358,23 @@ def _resolve_reference_in_domain(inv_name: Optional[str], inventory: Inventory,
351358

352359

353360
def _resolve_reference(env: BuildEnvironment, inv_name: Optional[str], inventory: Inventory,
354-
honor_disabled_domains: bool,
361+
honor_disabled_refs: bool,
355362
node: pending_xref, contnode: TextElement) -> Optional[Element]:
356363
# disabling should only be done if no inventory is given
357-
honor_disabled_domains = honor_disabled_domains and inv_name is None
364+
honor_disabled_refs = honor_disabled_refs and inv_name is None
358365

359-
if honor_disabled_domains and 'all' in env.config.intersphinx_disabled_domains:
366+
if honor_disabled_refs and 'all' in env.config.intersphinx_disabled_refs:
360367
return None
361368

362369
typ = node['reftype']
363370
if typ == 'any':
364371
for domain_name, domain in env.domains.items():
365-
if honor_disabled_domains \
366-
and domain_name in env.config.intersphinx_disabled_domains:
372+
if honor_disabled_refs \
373+
and domain_name in env.config.intersphinx_disabled_refs:
367374
continue
368375
objtypes = list(domain.object_types)
369-
res = _resolve_reference_in_domain(inv_name, inventory,
376+
res = _resolve_reference_in_domain(env, inv_name, inventory,
377+
honor_disabled_refs,
370378
domain, objtypes,
371379
node, contnode)
372380
if res is not None:
@@ -377,14 +385,15 @@ def _resolve_reference(env: BuildEnvironment, inv_name: Optional[str], inventory
377385
if not domain_name:
378386
# only objects in domains are in the inventory
379387
return None
380-
if honor_disabled_domains \
381-
and domain_name in env.config.intersphinx_disabled_domains:
388+
if honor_disabled_refs \
389+
and domain_name in env.config.intersphinx_disabled_refs:
382390
return None
383391
domain = env.get_domain(domain_name)
384392
objtypes = domain.objtypes_for_role(typ)
385393
if not objtypes:
386394
return None
387-
return _resolve_reference_in_domain(inv_name, inventory,
395+
return _resolve_reference_in_domain(env, inv_name, inventory,
396+
honor_disabled_refs,
388397
domain, objtypes,
389398
node, contnode)
390399

@@ -409,20 +418,20 @@ def resolve_reference_in_inventory(env: BuildEnvironment,
409418

410419

411420
def resolve_reference_any_inventory(env: BuildEnvironment,
412-
honor_disabled_domains: bool,
421+
honor_disabled_refs: bool,
413422
node: pending_xref, contnode: TextElement
414423
) -> Optional[Element]:
415424
"""Attempt to resolve a missing reference via intersphinx references.
416425
417426
Resolution is tried with the target as is in any inventory.
418427
"""
419428
return _resolve_reference(env, None, InventoryAdapter(env).main_inventory,
420-
honor_disabled_domains,
429+
honor_disabled_refs,
421430
node, contnode)
422431

423432

424433
def resolve_reference_detect_inventory(env: BuildEnvironment,
425-
honor_disabled_domains: bool,
434+
honor_disabled_refs: bool,
426435
node: pending_xref, contnode: TextElement
427436
) -> Optional[Element]:
428437
"""Attempt to resolve a missing reference via intersphinx references.
@@ -434,7 +443,7 @@ def resolve_reference_detect_inventory(env: BuildEnvironment,
434443
"""
435444

436445
# ordinary direct lookup, use data as is
437-
res = resolve_reference_any_inventory(env, honor_disabled_domains, node, contnode)
446+
res = resolve_reference_any_inventory(env, honor_disabled_refs, node, contnode)
438447
if res is not None:
439448
return res
440449

@@ -486,7 +495,7 @@ def setup(app: Sphinx) -> Dict[str, Any]:
486495
app.add_config_value('intersphinx_mapping', {}, True)
487496
app.add_config_value('intersphinx_cache_limit', 5, False)
488497
app.add_config_value('intersphinx_timeout', None, False)
489-
app.add_config_value('intersphinx_disabled_domains', [], True)
498+
app.add_config_value('intersphinx_disabled_refs', [], True)
490499
app.connect('config-inited', normalize_intersphinx_mapping, priority=800)
491500
app.connect('builder-inited', load_mappings)
492501
app.connect('missing-reference', missing_reference)

tests/test_ext_intersphinx.py

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def reference_check(app, *args, **kwds):
4545
def set_config(app, mapping):
4646
app.config.intersphinx_mapping = mapping
4747
app.config.intersphinx_cache_limit = 0
48-
app.config.intersphinx_disabled_domains = []
48+
app.config.intersphinx_disabled_refs = []
4949

5050

5151
@mock.patch('sphinx.ext.intersphinx.InventoryFile')
@@ -303,7 +303,7 @@ def test_missing_reference_disabled_domain(tempdir, app, status, warning):
303303
normalize_intersphinx_mapping(app, app.config)
304304
load_mappings(app)
305305

306-
def case(std_without, std_with, py_without, py_with):
306+
def case(*, term, doc, py):
307307
def assert_(rn, expected):
308308
if expected is None:
309309
assert rn is None
@@ -312,34 +312,46 @@ def assert_(rn, expected):
312312

313313
kwargs = {}
314314

315+
node, contnode = fake_node('std', 'term', 'a term', 'a term', **kwargs)
316+
rn = missing_reference(app, app.env, node, contnode)
317+
assert_(rn, 'a term' if term else None)
318+
319+
node, contnode = fake_node('std', 'term', 'inv:a term', 'a term', **kwargs)
320+
rn = missing_reference(app, app.env, node, contnode)
321+
assert_(rn, 'a term')
322+
315323
node, contnode = fake_node('std', 'doc', 'docname', 'docname', **kwargs)
316324
rn = missing_reference(app, app.env, node, contnode)
317-
assert_(rn, std_without)
325+
assert_(rn, 'docname' if doc else None)
318326

319327
node, contnode = fake_node('std', 'doc', 'inv:docname', 'docname', **kwargs)
320328
rn = missing_reference(app, app.env, node, contnode)
321-
assert_(rn, std_with)
329+
assert_(rn, 'docname')
322330

323331
# an arbitrary ref in another domain
324332
node, contnode = fake_node('py', 'func', 'module1.func', 'func()', **kwargs)
325333
rn = missing_reference(app, app.env, node, contnode)
326-
assert_(rn, py_without)
334+
assert_(rn, 'func()' if py else None)
327335

328336
node, contnode = fake_node('py', 'func', 'inv:module1.func', 'func()', **kwargs)
329337
rn = missing_reference(app, app.env, node, contnode)
330-
assert_(rn, py_with)
338+
assert_(rn, 'func()')
331339

332340
# the base case, everything should resolve
333-
assert app.config.intersphinx_disabled_domains == []
334-
case('docname', 'docname', 'func()', 'func()')
341+
assert app.config.intersphinx_disabled_refs == []
342+
case(term=True, doc=True, py=True)
343+
344+
# disabled a single ref type
345+
app.config.intersphinx_disabled_refs = ['std:doc']
346+
case(term=True, doc=False, py=True)
335347

336-
# disabled one domain
337-
app.config.intersphinx_disabled_domains = ['std']
338-
case(None, 'docname', 'func()', 'func()')
348+
# disabled a whole domain
349+
app.config.intersphinx_disabled_refs = ['std']
350+
case(term=False, doc=False, py=True)
339351

340352
# disabled all domains
341-
app.config.intersphinx_disabled_domains = ['all']
342-
case(None, 'docname', None, 'func()')
353+
app.config.intersphinx_disabled_refs = ['all']
354+
case(term=False, doc=False, py=False)
343355

344356

345357
@pytest.mark.xfail(os.name != 'posix', reason="Path separator mismatch issue")

0 commit comments

Comments
 (0)