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.
85 lines
2.4 KiB
85 lines
2.4 KiB
2 years ago
|
# -*- coding: utf-8 -*-
|
||
|
"""
|
||
|
linkcode
|
||
|
~~~~~~~~
|
||
|
|
||
|
Add external links to module code in Python object descriptions.
|
||
|
|
||
|
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
|
||
|
:license: BSD, see LICENSE for details.
|
||
|
|
||
|
"""
|
||
|
from __future__ import division, absolute_import, print_function
|
||
|
|
||
|
import warnings
|
||
|
import collections
|
||
|
|
||
|
warnings.warn(
|
||
|
"This extension has been accepted to Sphinx upstream. "
|
||
|
"Use the version from there (Sphinx >= 1.2) "
|
||
|
"https://bitbucket.org/birkenfeld/sphinx/pull-request/47/sphinxextlinkcode",
|
||
|
FutureWarning,
|
||
|
stacklevel=1,
|
||
|
)
|
||
|
|
||
|
|
||
|
from docutils import nodes
|
||
|
|
||
|
from sphinx import addnodes
|
||
|
from sphinx.locale import _
|
||
|
from sphinx.errors import SphinxError
|
||
|
|
||
|
|
||
|
class LinkcodeError(SphinxError):
|
||
|
category = "linkcode error"
|
||
|
|
||
|
|
||
|
def doctree_read(app, doctree):
|
||
|
env = app.builder.env
|
||
|
|
||
|
resolve_target = getattr(env.config, "linkcode_resolve", None)
|
||
|
if not isinstance(env.config.linkcode_resolve, collections.Callable):
|
||
|
raise LinkcodeError("Function `linkcode_resolve` is not given in conf.py")
|
||
|
|
||
|
domain_keys = dict(
|
||
|
py=["module", "fullname"], c=["names"], cpp=["names"], js=["object", "fullname"]
|
||
|
)
|
||
|
|
||
|
for objnode in doctree.traverse(addnodes.desc):
|
||
|
domain = objnode.get("domain")
|
||
|
uris = set()
|
||
|
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)
|
||
|
|
||
|
onlynode = addnodes.only(expr="html")
|
||
|
onlynode += nodes.reference("", "", internal=False, refuri=uri)
|
||
|
onlynode[0] += nodes.inline("", _("[source]"), classes=["viewcode-link"])
|
||
|
signode += onlynode
|
||
|
|
||
|
|
||
|
def setup(app):
|
||
|
app.connect("doctree-read", doctree_read)
|
||
|
app.add_config_value("linkcode_resolve", None, "")
|