summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorg Brandl <georg@python.org>2014-11-12 11:32:21 +0100
committerGeorg Brandl <georg@python.org>2014-11-12 11:32:21 +0100
commit8637a62828683512d8ef080b5ad23094815d2eed (patch)
tree94351db179c2c404c94408d5b63b6d0b0a8afdfa
parent216804f3142da96f350bf9e5cb86a0682bd241fb (diff)
downloadsphinx-8637a62828683512d8ef080b5ad23094815d2eed.tar.gz
Closes #1623: Return types specified with ``:rtype:`` are now turned into links if possible.
-rw-r--r--CHANGES2
-rw-r--r--doc/domains.rst4
-rw-r--r--sphinx/domains/python.py39
-rw-r--r--sphinx/util/docfields.py23
-rw-r--r--tests/root/objects.txt2
-rw-r--r--tests/test_build_html.py3
6 files changed, 49 insertions, 24 deletions
diff --git a/CHANGES b/CHANGES
index f35e7ed5..07b4c314 100644
--- a/CHANGES
+++ b/CHANGES
@@ -123,6 +123,8 @@ Features added
to Jeppe Pihl.
* PR#299: add various options to sphinx-quickstart. Quiet mode option
``--quiet`` will skips wizard mode. Thanks to WAKAYAMA shirou.
+* #1623: Return types specified with ``:rtype:`` are now turned into links if
+ possible.
Bugs fixed
----------
diff --git a/doc/domains.rst b/doc/domains.rst
index 15f8c7a3..59050020 100644
--- a/doc/domains.rst
+++ b/doc/domains.rst
@@ -310,12 +310,12 @@ are recognized and formatted nicely:
* ``param``, ``parameter``, ``arg``, ``argument``, ``key``, ``keyword``:
Description of a parameter.
-* ``type``: Type of a parameter.
+* ``type``: Type of a parameter. Creates a link if possible.
* ``raises``, ``raise``, ``except``, ``exception``: That (and when) a specific
exception is raised.
* ``var``, ``ivar``, ``cvar``: Description of a variable.
* ``returns``, ``return``: Description of the return value.
-* ``rtype``: Return type.
+* ``rtype``: Return type. Creates a link if possible.
The field names must consist of one of these keywords and an argument (except
for ``returns`` and ``rtype``, which do not need an argument). This is best
diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py
index 4e08eba9..692010c1 100644
--- a/sphinx/domains/python.py
+++ b/sphinx/domains/python.py
@@ -84,13 +84,14 @@ def _pseudo_parse_arglist(signode, arglist):
# This override allows our inline type specifiers to behave like :class: link
# when it comes to handling "." and "~" prefixes.
-class PyTypedField(TypedField):
- def make_xref(self, rolename, domain, target, innernode=nodes.emphasis):
- result = super(PyTypedField, self).make_xref(rolename, domain, target,
- innernode)
+class PyXrefMixin(object):
+ def make_xref(self, rolename, domain, target, innernode=nodes.emphasis,
+ contnode=None):
+ result = super(PyXrefMixin, self).make_xref(rolename, domain, target,
+ innernode, contnode)
+ result['refspecific'] = True
if target.startswith('.'):
result['reftarget'] = target[1:]
- result['refspecific'] = True
result[0][0] = nodes.Text(target[1:])
if target.startswith('~'):
result['reftarget'] = target[1:]
@@ -99,6 +100,14 @@ class PyTypedField(TypedField):
return result
+class PyField(PyXrefMixin, Field):
+ pass
+
+
+class PyTypedField(PyXrefMixin, TypedField):
+ pass
+
+
class PyObject(ObjectDescription):
"""
Description of a general Python object.
@@ -111,21 +120,21 @@ class PyObject(ObjectDescription):
doc_field_types = [
PyTypedField('parameter', label=l_('Parameters'),
- names=('param', 'parameter', 'arg', 'argument',
- 'keyword', 'kwarg', 'kwparam'),
- typerolename='obj', typenames=('paramtype', 'type'),
- can_collapse=True),
- TypedField('variable', label=l_('Variables'), rolename='obj',
- names=('var', 'ivar', 'cvar'),
- typerolename='obj', typenames=('vartype',),
- can_collapse=True),
+ names=('param', 'parameter', 'arg', 'argument',
+ 'keyword', 'kwarg', 'kwparam'),
+ typerolename='obj', typenames=('paramtype', 'type'),
+ can_collapse=True),
+ PyTypedField('variable', label=l_('Variables'), rolename='obj',
+ names=('var', 'ivar', 'cvar'),
+ typerolename='obj', typenames=('vartype',),
+ can_collapse=True),
GroupedField('exceptions', label=l_('Raises'), rolename='exc',
names=('raises', 'raise', 'exception', 'except'),
can_collapse=True),
Field('returnvalue', label=l_('Returns'), has_arg=False,
names=('returns', 'return')),
- Field('returntype', label=l_('Return type'), has_arg=False,
- names=('rtype',)),
+ PyField('returntype', label=l_('Return type'), has_arg=False,
+ names=('rtype',), bodyrolename='obj'),
]
def get_signature_prefix(self, sig):
diff --git a/sphinx/util/docfields.py b/sphinx/util/docfields.py
index abb73288..46f89430 100644
--- a/sphinx/util/docfields.py
+++ b/sphinx/util/docfields.py
@@ -29,11 +29,13 @@ def _is_single_paragraph(node):
class Field(object):
- """
- A doc field that is never grouped. It can have an argument or not, the
+ """A doc field that is never grouped. It can have an argument or not, the
argument can be linked using a specified *rolename*. Field should be used
for doc fields that usually don't occur more than once.
+ The body can be linked using a specified *bodyrolename* if the content is
+ just a single inline or text node.
+
Example::
:returns: description of the return value
@@ -42,19 +44,22 @@ class Field(object):
is_grouped = False
is_typed = False
- def __init__(self, name, names=(), label=None, has_arg=True, rolename=None):
+ def __init__(self, name, names=(), label=None, has_arg=True, rolename=None,
+ bodyrolename=None):
self.name = name
self.names = names
self.label = label
self.has_arg = has_arg
self.rolename = rolename
+ self.bodyrolename = bodyrolename
- def make_xref(self, rolename, domain, target, innernode=nodes.emphasis):
+ def make_xref(self, rolename, domain, target, innernode=nodes.emphasis,
+ contnode=None):
if not rolename:
- return innernode(target, target)
+ return contnode or innernode(target, target)
refnode = addnodes.pending_xref('', refdomain=domain, refexplicit=False,
reftype=rolename, reftarget=target)
- refnode += innernode(target, target)
+ refnode += contnode or innernode(target, target)
return refnode
def make_entry(self, fieldarg, content):
@@ -67,6 +72,12 @@ class Field(object):
fieldname += nodes.Text(' ')
fieldname += self.make_xref(self.rolename, domain,
fieldarg, nodes.Text)
+ if len(content) == 1 and (
+ isinstance(content[0], nodes.Text) or
+ (isinstance(content[0], nodes.inline) and len(content[0]) == 1
+ and isinstance(content[0][0], nodes.Text))):
+ content = [self.make_xref(self.bodyrolename, domain,
+ content[0].astext(), contnode=content[0])]
fieldbody = nodes.field_body('', nodes.paragraph('', '', *content))
return nodes.field('', fieldname, fieldbody)
diff --git a/tests/root/objects.txt b/tests/root/objects.txt
index ebed06ea..cbc6281d 100644
--- a/tests/root/objects.txt
+++ b/tests/root/objects.txt
@@ -92,7 +92,7 @@ Referring to :func:`nothing <>`.
:type isdst: * some complex
* expression
:returns: a new :class:`Time` instance
- :rtype: :class:`Time`
+ :rtype: Time
:raises ValueError: if the values are out of range
:ivar int hour: like *hour*
:ivar minute: like *minute*
diff --git a/tests/test_build_html.py b/tests/test_build_html.py
index 47c30b2e..63bdeff1 100644
--- a/tests/test_build_html.py
+++ b/tests/test_build_html.py
@@ -200,6 +200,9 @@ HTML_XPATH = {
(".//dl[@class='userdesc']", ''),
(".//dt[@id='userdesc-myobj']", ''),
(".//a[@href='#userdesc-myobj'][@class='reference internal']", ''),
+ # docfields
+ (".//a[@class='reference internal'][@href='#TimeInt']/em", 'TimeInt'),
+ (".//a[@class='reference internal'][@href='#Time']", 'Time'),
# C references
(".//span[@class='pre']", 'CFunction()'),
(".//a[@href='#c.Sphinx_DoSomething']", ''),