You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
80 lines
2.3 KiB
80 lines
2.3 KiB
"""
|
|
sphinx.ext.linkcode
|
|
~~~~~~~~~~~~~~~~~~~
|
|
|
|
Add external links to module code in Python object descriptions.
|
|
|
|
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
|
|
:license: BSD, see LICENSE for details.
|
|
"""
|
|
|
|
from typing import Any, Dict, Set
|
|
|
|
from docutils import nodes
|
|
from docutils.nodes import Node
|
|
|
|
import sphinx
|
|
from sphinx import addnodes
|
|
from sphinx.application import Sphinx
|
|
from sphinx.errors import SphinxError
|
|
from sphinx.locale import _
|
|
|
|
|
|
class LinkcodeError(SphinxError):
|
|
category = "linkcode error"
|
|
|
|
|
|
def doctree_read(app: Sphinx, doctree: Node) -> None:
|
|
env = app.builder.env
|
|
|
|
resolve_target = getattr(env.config, 'linkcode_resolve', None)
|
|
if not callable(env.config.linkcode_resolve):
|
|
raise LinkcodeError(
|
|
"Function `linkcode_resolve` is not given in conf.py")
|
|
|
|
domain_keys = {
|
|
'py': ['module', 'fullname'],
|
|
'c': ['names'],
|
|
'cpp': ['names'],
|
|
'js': ['object', 'fullname'],
|
|
}
|
|
|
|
for objnode in doctree.traverse(addnodes.desc):
|
|
domain = objnode.get('domain')
|
|
uris = set() # type: Set[str]
|
|
for signode in objnode:
|
|
if not isinstance(signode, addnodes.desc_signature):
|
|
continue
|
|
|
|
# Convert signode to a specified format
|
|
info = {}
|
|
for key in domain_keys.get(domain, []):
|
|
value = signode.get(key)
|
|
if not value:
|
|
value = ''
|
|
info[key] = value
|
|
if not info:
|
|
continue
|
|
|
|
# Call user code to resolve the link
|
|
uri = resolve_target(domain, info)
|
|
if not uri:
|
|
# no source
|
|
continue
|
|
|
|
if uri in uris or not uri:
|
|
# only one link per name, please
|
|
continue
|
|
uris.add(uri)
|
|
|
|
inline = nodes.inline('', _('[source]'), classes=['viewcode-link'])
|
|
onlynode = addnodes.only(expr='html')
|
|
onlynode += nodes.reference('', '', inline, internal=False, refuri=uri)
|
|
signode += onlynode
|
|
|
|
|
|
def setup(app: Sphinx) -> Dict[str, Any]:
|
|
app.connect('doctree-read', doctree_read)
|
|
app.add_config_value('linkcode_resolve', None, '')
|
|
return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
|