Merged in pv/sphinx-work/ext-linkcode (pull request #47)

This commit is contained in:
Georg Brandl 2012-10-28 18:21:57 +01:00
commit 201883d209
5 changed files with 169 additions and 0 deletions

46
doc/ext/linkcode.rst Normal file
View File

@ -0,0 +1,46 @@
:mod:`sphinx.ext.linkcode` -- Add external links to source code
===============================================================
.. module:: sphinx.ext.linkcode
:synopsis: Add external links to source code.
.. moduleauthor:: Pauli Virtanen
.. versionadded:: 1.1
This extension looks at your object descriptions (``.. class::``,
``.. function::`` etc.) and adds external links to code hosted
somewhere on the web. The intent is similar to the
``sphinx.ext.viewcode`` extension, but assumes the source code can be
found somewhere on the Internet.
In your configuration, you need to specify a :confval:`linkcode_resolve`
function that returns an URL based on the object.
.. confval:: linkcode_resolve
This is a function ``linkcode_resolve(domain, info)``,
which should return the URL to source code corresponding to
the object in given domain with given information.
The function should return ``None`` if no link is to be added.
The argument ``domain`` specifies the language domain the object is
in. ``info`` is a dictionary with the following keys guaranteed to
be present (dependent on the domain):
- ``py``: ``module`` (name of the module), ``fullname`` (name of the object)
- ``c``: ``names`` (list of names for the object)
- ``cpp``: ``names`` (list of names for the object)
- ``javascript``: ``object`` (name of the object), ``fullname`` (name of the item)
Example:
.. code-block:: python
def linkcode_resolve(domain, info):
if domain != 'py':
return None
if not info['module']:
return None
filename = info['module'].replace('.', '/')
return "http://somesite/sourcerepo/%s.py" % filename

View File

@ -53,6 +53,7 @@ These extensions are built in and can be activated by respective entries in the
ext/todo
ext/extlinks
ext/viewcode
ext/linkcode
ext/oldcmarkup

72
sphinx/ext/linkcode.py Normal file
View File

@ -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')

View File

@ -67,6 +67,28 @@ extlinks = {'issue': ('http://bugs.python.org/issue%s', 'issue '),
# modify tags from conf.py
tags.add('confpytag')
# -- linkcode
if 'test_linkcode' in tags:
import glob
extensions.remove('sphinx.ext.viewcode')
extensions.append('sphinx.ext.linkcode')
exclude_patterns.extend(glob.glob('*.txt') + glob.glob('*/*.txt'))
exclude_patterns.remove('contents.txt')
exclude_patterns.remove('objects.txt')
def linkcode_resolve(domain, info):
if domain == 'py':
fn = info['module'].replace('.', '/')
return "http://foobar/source/%s.py" % fn
elif domain == "js":
return "http://foobar/js/" + info['fullname']
elif domain in ("c", "cpp"):
return "http://foobar/%s/%s" % (domain, "".join(info['names']))
else:
raise AssertionError()
# -- extension API

28
tests/test_linkcode.py Normal file
View File

@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
"""
test_linkcode
~~~~~~~~~~~~~
Test the sphinx.ext.linkcode extension.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import os
from util import *
@with_app(srcdir='(temp)', buildername='html', tags=['test_linkcode'])
def test_html(app):
app.builder.build_all()
fp = open(os.path.join(app.outdir, 'objects.html'), 'rb')
try:
stuff = fp.read()
finally:
fp.close()
assert 'http://foobar/source/foolib.py' in stuff
assert 'http://foobar/js/' in stuff
assert 'http://foobar/c/' in stuff
assert 'http://foobar/cpp/' in stuff