Skip to content

Commit

Permalink
Allow extensions to define the keys returned by linkcode (#11824)
Browse files Browse the repository at this point in the history
Co-authored-by: Adam Turner <[email protected]>
  • Loading branch information
n-peugnet and AA-Turner authored Jan 3, 2025
1 parent 20c1c7f commit 0fbf88a
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 8 deletions.
3 changes: 3 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ Features added
* Add a new ``duplicate_declaration`` warning type,
with ``duplicate_declaration.c`` and ``duplicate_declaration.cpp`` subtypes.
Patch by Julien Lecomte and Adam Turner.
* #11824: linkcode: Allow extensions to add support for a domain by defining
the keys that should be present.
Patch by Nicolas Peugnet.

Bugs fixed
----------
Expand Down
18 changes: 18 additions & 0 deletions doc/usage/extensions/linkcode.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,21 @@ Configuration
return None
filename = info['module'].replace('.', '/')
return "https://somesite/sourcerepo/%s.py" % filename
Third-party domains
-------------------

Support for other domains can be added by extensions with
:py:func:`.add_linkcode_domain()`.
For example, a Sphinx extension that provides a ``php`` domain
could use the following code to support :mod:`~sphinx.ext.linkcode`:

.. code-block:: python
from sphinx.ext.linkcode import add_linkcode_domain
def setup(app):
add_linkcode_domain('php', ['namespace', 'class', 'fullname'])
.. autofunction:: add_linkcode_domain
26 changes: 18 additions & 8 deletions sphinx/ext/linkcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,23 @@
from sphinx.util.typing import ExtensionMetadata


_DOMAIN_KEYS = {
'py': ['module', 'fullname'],
'c': ['names'],
'cpp': ['names'],
'js': ['object', 'fullname'],
}


def add_linkcode_domain(domain: str, keys: list[str], override: bool = False) -> None:
"""Register a new list of keys to use for a domain.
.. versionadded:: 8.2
"""
if override or domain not in _DOMAIN_KEYS:
_DOMAIN_KEYS[domain] = list(keys)


class LinkcodeError(SphinxError):
category = 'linkcode error'

Expand All @@ -37,13 +54,6 @@ def doctree_read(app: Sphinx, doctree: Node) -> None:
# ``supported_linkcode`` attribute.
node_only_expr = getattr(app.builder, 'supported_linkcode', 'html')

domain_keys = {
'py': ['module', 'fullname'],
'c': ['names'],
'cpp': ['names'],
'js': ['object', 'fullname'],
}

for objnode in list(doctree.findall(addnodes.desc)):
domain = objnode.get('domain')
uris: set[str] = set()
Expand All @@ -53,7 +63,7 @@ def doctree_read(app: Sphinx, doctree: Node) -> None:

# Convert signode to a specified format
info = {}
for key in domain_keys.get(domain, []):
for key in _DOMAIN_KEYS.get(domain, []):
value = signode.get(key)
if not value:
value = ''
Expand Down
7 changes: 7 additions & 0 deletions tests/roots/test-ext-viewcode/conf.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import sys
from pathlib import Path

from sphinx.ext.linkcode import add_linkcode_domain

sys.path.insert(0, str(Path.cwd().resolve()))

extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode']
Expand All @@ -19,5 +21,10 @@ def linkcode_resolve(domain, info):
return 'https://foobar/js/' + info['fullname']
elif domain in {'c', 'cpp'}:
return f'https://foobar/{domain}/{"".join(info["names"])}'
elif domain == 'rst':
return 'http://foobar/rst/{fullname}'.format(**info)
else:
raise AssertionError

def setup(app):
add_linkcode_domain('rst', ['fullname'])
7 changes: 7 additions & 0 deletions tests/roots/test-ext-viewcode/objects.rst
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,10 @@ CPP domain

.. cpp:function:: T& operator[]( unsigned j )
const T& operator[]( unsigned j ) const

rST domain
==========

.. rst:role:: foo
Foo description.
1 change: 1 addition & 0 deletions tests/test_extensions/test_ext_viewcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ def test_linkcode(app):
assert 'https://foobar/js/' in stuff
assert 'https://foobar/c/' in stuff
assert 'https://foobar/cpp/' in stuff
assert 'http://foobar/rst/' in stuff


@pytest.mark.sphinx('html', testroot='ext-viewcode-find', freshenv=True)
Expand Down

0 comments on commit 0fbf88a

Please sign in to comment.