diff options
author | Georg Brandl <georg@python.org> | 2014-11-12 11:32:21 +0100 |
---|---|---|
committer | Georg Brandl <georg@python.org> | 2014-11-12 11:32:21 +0100 |
commit | 8637a62828683512d8ef080b5ad23094815d2eed (patch) | |
tree | 94351db179c2c404c94408d5b63b6d0b0a8afdfa | |
parent | 216804f3142da96f350bf9e5cb86a0682bd241fb (diff) | |
download | sphinx-8637a62828683512d8ef080b5ad23094815d2eed.tar.gz |
Closes #1623: Return types specified with ``:rtype:`` are now turned into links if possible.
-rw-r--r-- | CHANGES | 2 | ||||
-rw-r--r-- | doc/domains.rst | 4 | ||||
-rw-r--r-- | sphinx/domains/python.py | 39 | ||||
-rw-r--r-- | sphinx/util/docfields.py | 23 | ||||
-rw-r--r-- | tests/root/objects.txt | 2 | ||||
-rw-r--r-- | tests/test_build_html.py | 3 |
6 files changed, 49 insertions, 24 deletions
@@ -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']", ''), |