mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merged in pv/sphinx-work/ext-linkcode (pull request #47)
This commit is contained in:
commit
201883d209
46
doc/ext/linkcode.rst
Normal file
46
doc/ext/linkcode.rst
Normal 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
|
@ -53,6 +53,7 @@ These extensions are built in and can be activated by respective entries in the
|
|||||||
ext/todo
|
ext/todo
|
||||||
ext/extlinks
|
ext/extlinks
|
||||||
ext/viewcode
|
ext/viewcode
|
||||||
|
ext/linkcode
|
||||||
ext/oldcmarkup
|
ext/oldcmarkup
|
||||||
|
|
||||||
|
|
||||||
|
72
sphinx/ext/linkcode.py
Normal file
72
sphinx/ext/linkcode.py
Normal 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')
|
@ -67,6 +67,28 @@ extlinks = {'issue': ('http://bugs.python.org/issue%s', 'issue '),
|
|||||||
# modify tags from conf.py
|
# modify tags from conf.py
|
||||||
tags.add('confpytag')
|
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
|
# -- extension API
|
||||||
|
|
||||||
|
28
tests/test_linkcode.py
Normal file
28
tests/test_linkcode.py
Normal 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
|
Loading…
Reference in New Issue
Block a user