summaryrefslogtreecommitdiff
path: root/sphinx/ext/linkcode.py
diff options
context:
space:
mode:
authorPauli Virtanen <pav@iki.fi>2012-03-11 17:48:51 +0100
committerPauli Virtanen <pav@iki.fi>2012-03-11 17:48:51 +0100
commit135bb6f6c8c7b75f16939a725173aa26f3896d25 (patch)
tree5c2fc418a1845dd24722b1e5917a35b45ea52bb0 /sphinx/ext/linkcode.py
parent0c01c6e9a79f9e5eb6d230337430dcf3f110d2b8 (diff)
downloadsphinx-git-135bb6f6c8c7b75f16939a725173aa26f3896d25.tar.gz
ENH: add a linkcode extension
Diffstat (limited to 'sphinx/ext/linkcode.py')
-rw-r--r--sphinx/ext/linkcode.py72
1 files changed, 72 insertions, 0 deletions
diff --git a/sphinx/ext/linkcode.py b/sphinx/ext/linkcode.py
new file mode 100644
index 000000000..ffe5b9c09
--- /dev/null
+++ b/sphinx/ext/linkcode.py
@@ -0,0 +1,72 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.ext.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 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 callable(env.config.linkcode_resolve):
+ 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, 'env')