mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge pull request #2825 from AWhetter/link_container_types
Looks great, thanks again for the work! (BTW, I just noticed "Squash and Merge" is enabled for this repo. Sorry to make you do the extra work, I really do appreciate it)
This commit is contained in:
commit
a8375dd5b4
@ -359,6 +359,18 @@ single word, like this::
|
||||
:param int priority: The priority of the message, can be a number 1-5
|
||||
|
||||
|
||||
.. versionadded:: 1.5
|
||||
|
||||
Container types such as lists and dictionaries can be linked automatically
|
||||
using the following syntax::
|
||||
|
||||
:type priorities: list(int)
|
||||
:type priorities: list[int]
|
||||
:type mapping: dict(str, int)
|
||||
:type mapping: dict[str, int]
|
||||
:type point: tuple(float, float)
|
||||
:type point: tuple[float, float]
|
||||
|
||||
.. _python-roles:
|
||||
|
||||
Cross-referencing Python objects
|
||||
|
@ -211,14 +211,14 @@ class ExampleClass(object):
|
||||
param1 (str): Description of `param1`.
|
||||
param2 (:obj:`int`, optional): Description of `param2`. Multiple
|
||||
lines are supported.
|
||||
param3 (:obj:`list` of :obj:`str`): Description of `param3`.
|
||||
param3 (list(str)): Description of `param3`.
|
||||
|
||||
"""
|
||||
self.attr1 = param1
|
||||
self.attr2 = param2
|
||||
self.attr3 = param3 #: Doc comment *inline* with attribute
|
||||
|
||||
#: list of str: Doc comment *before* attribute, with type specified
|
||||
#: list(str): Doc comment *before* attribute, with type specified
|
||||
self.attr4 = ['attr4']
|
||||
|
||||
self.attr5 = None
|
||||
@ -231,7 +231,7 @@ class ExampleClass(object):
|
||||
|
||||
@property
|
||||
def readwrite_property(self):
|
||||
""":obj:`list` of :obj:`str`: Properties with both a getter and setter
|
||||
"""list(str): Properties with both a getter and setter
|
||||
should only be documented in their getter method.
|
||||
|
||||
If the setter method contains notable behavior, it should be
|
||||
|
@ -260,7 +260,7 @@ class ExampleClass(object):
|
||||
----------
|
||||
param1 : str
|
||||
Description of `param1`.
|
||||
param2 : :obj:`list` of :obj:`str`
|
||||
param2 : list(str)
|
||||
Description of `param2`. Multiple
|
||||
lines are supported.
|
||||
param3 : :obj:`int`, optional
|
||||
@ -271,7 +271,7 @@ class ExampleClass(object):
|
||||
self.attr2 = param2
|
||||
self.attr3 = param3 #: Doc comment *inline* with attribute
|
||||
|
||||
#: list of str: Doc comment *before* attribute, with type specified
|
||||
#: list(str): Doc comment *before* attribute, with type specified
|
||||
self.attr4 = ["attr4"]
|
||||
|
||||
self.attr5 = None
|
||||
@ -284,7 +284,7 @@ class ExampleClass(object):
|
||||
|
||||
@property
|
||||
def readwrite_property(self):
|
||||
""":obj:`list` of :obj:`str`: Properties with both a getter and setter
|
||||
"""list(str): Properties with both a getter and setter
|
||||
should only be documented in their getter method.
|
||||
|
||||
If the setter method contains notable behavior, it should be
|
||||
|
@ -101,6 +101,27 @@ class PyXrefMixin(object):
|
||||
break
|
||||
return result
|
||||
|
||||
def make_xrefs(self, rolename, domain, target, innernode=nodes.emphasis,
|
||||
contnode=None):
|
||||
delims = '(\s*[\[\]\(\),]\s*)'
|
||||
delims_re = re.compile(delims)
|
||||
sub_targets = re.split(delims, target)
|
||||
|
||||
split_contnode = bool(contnode and contnode.astext() == target)
|
||||
|
||||
results = []
|
||||
for sub_target in sub_targets:
|
||||
if split_contnode:
|
||||
contnode = nodes.Text(sub_target)
|
||||
|
||||
if delims_re.match(sub_target):
|
||||
results.append(contnode or innernode(sub_target, sub_target))
|
||||
else:
|
||||
results.append(self.make_xref(rolename, domain, sub_target,
|
||||
innernode, contnode))
|
||||
|
||||
return results
|
||||
|
||||
|
||||
class PyField(PyXrefMixin, Field):
|
||||
pass
|
||||
|
@ -24,7 +24,7 @@ from sphinx.util.pycompat import UnicodeMixin
|
||||
|
||||
_directive_regex = re.compile(r'\.\. \S+::')
|
||||
_google_section_regex = re.compile(r'^(\s|\w)+:\s*$')
|
||||
_google_typed_arg_regex = re.compile(r'\s*(.+?)\s*\(\s*(.+?)\s*\)')
|
||||
_google_typed_arg_regex = re.compile(r'\s*(.+?)\s*\(\s*(.*[^\s]+)\s*\)')
|
||||
_numpy_section_regex = re.compile(r'^[=\-`:\'"~^_*+#<>]{2,}\s*$')
|
||||
_single_colon_regex = re.compile(r'(?<!:):(?!:)')
|
||||
_xref_regex = re.compile(r'(:\w+:\S+:`.+?`|:\S+:`.+?`|`.+?`)')
|
||||
@ -172,7 +172,7 @@ class GoogleDocstring(UnicodeMixin):
|
||||
|
||||
Returns
|
||||
-------
|
||||
:obj:`list` of :obj:`str`
|
||||
list(str)
|
||||
The lines of the docstring in a list.
|
||||
|
||||
"""
|
||||
@ -254,12 +254,7 @@ class GoogleDocstring(UnicodeMixin):
|
||||
else:
|
||||
_desc = lines[1:]
|
||||
|
||||
match = _google_typed_arg_regex.match(before)
|
||||
if match:
|
||||
_name = match.group(1)
|
||||
_type = match.group(2)
|
||||
else:
|
||||
_type = before
|
||||
_type = before
|
||||
|
||||
_desc = self.__class__(_desc, self._config).lines()
|
||||
return [(_name, _type, _desc,)]
|
||||
@ -817,7 +812,7 @@ class NumpyDocstring(GoogleDocstring):
|
||||
|
||||
Returns
|
||||
-------
|
||||
:obj:`list` of :obj:`str`
|
||||
list(str)
|
||||
The lines of the docstring in a list.
|
||||
|
||||
"""
|
||||
|
@ -62,6 +62,10 @@ class Field(object):
|
||||
refnode += contnode or innernode(target, target)
|
||||
return refnode
|
||||
|
||||
def make_xrefs(self, rolename, domain, target,
|
||||
innernode=addnodes.literal_emphasis, contnode=None):
|
||||
return [self.make_xref(rolename, domain, target, innernode, contnode)]
|
||||
|
||||
def make_entry(self, fieldarg, content):
|
||||
return (fieldarg, content)
|
||||
|
||||
@ -70,14 +74,15 @@ class Field(object):
|
||||
fieldname = nodes.field_name('', self.label)
|
||||
if fieldarg:
|
||||
fieldname += nodes.Text(' ')
|
||||
fieldname += self.make_xref(self.rolename, domain,
|
||||
fieldarg, nodes.Text)
|
||||
fieldname.extend(self.make_xrefs(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])]
|
||||
content = self.make_xrefs(self.bodyrolename, domain,
|
||||
content[0].astext(), contnode=content[0])
|
||||
fieldbody = nodes.field_body('', nodes.paragraph('', '', *content))
|
||||
return nodes.field('', fieldname, fieldbody)
|
||||
|
||||
@ -108,14 +113,16 @@ class GroupedField(Field):
|
||||
listnode = self.list_type()
|
||||
for fieldarg, content in items:
|
||||
par = nodes.paragraph()
|
||||
par += self.make_xref(self.rolename, domain, fieldarg,
|
||||
addnodes.literal_strong)
|
||||
par.extend(self.make_xrefs(self.rolename, domain, fieldarg,
|
||||
addnodes.literal_strong))
|
||||
par += nodes.Text(' -- ')
|
||||
par += content
|
||||
listnode += nodes.list_item('', par)
|
||||
|
||||
if len(items) == 1 and self.can_collapse:
|
||||
fieldbody = nodes.field_body('', listnode[0][0])
|
||||
return nodes.field('', fieldname, fieldbody)
|
||||
|
||||
fieldbody = nodes.field_body('', listnode)
|
||||
return nodes.field('', fieldname, fieldbody)
|
||||
|
||||
@ -150,8 +157,8 @@ class TypedField(GroupedField):
|
||||
def make_field(self, types, domain, items):
|
||||
def handle_item(fieldarg, content):
|
||||
par = nodes.paragraph()
|
||||
par += self.make_xref(self.rolename, domain, fieldarg,
|
||||
addnodes.literal_strong)
|
||||
par.extend(self.make_xrefs(self.rolename, domain, fieldarg,
|
||||
addnodes.literal_strong))
|
||||
if fieldarg in types:
|
||||
par += nodes.Text(' (')
|
||||
# NOTE: using .pop() here to prevent a single type node to be
|
||||
@ -160,8 +167,8 @@ class TypedField(GroupedField):
|
||||
fieldtype = types.pop(fieldarg)
|
||||
if len(fieldtype) == 1 and isinstance(fieldtype[0], nodes.Text):
|
||||
typename = u''.join(n.astext() for n in fieldtype)
|
||||
par += self.make_xref(self.typerolename, domain, typename,
|
||||
addnodes.literal_emphasis)
|
||||
par.extend(self.make_xrefs(self.typerolename, domain, typename,
|
||||
addnodes.literal_emphasis))
|
||||
else:
|
||||
par += fieldtype
|
||||
par += nodes.Text(')')
|
||||
|
@ -222,6 +222,24 @@ class GoogleDocstringTest(BaseDocstringTest):
|
||||
"""
|
||||
Single line summary
|
||||
|
||||
Args:
|
||||
arg1 (list(int)): Description
|
||||
arg2 (list[int]): Description
|
||||
arg3 (dict(str, int)): Description
|
||||
arg4 (dict[str, int]): Description
|
||||
""",
|
||||
"""
|
||||
Single line summary
|
||||
|
||||
:Parameters: * **arg1** (*list(int)*) -- Description
|
||||
* **arg2** (*list[int]*) -- Description
|
||||
* **arg3** (*dict(str, int)*) -- Description
|
||||
* **arg4** (*dict[str, int]*) -- Description
|
||||
"""
|
||||
), (
|
||||
"""
|
||||
Single line summary
|
||||
|
||||
Yield:
|
||||
str:Extended
|
||||
description of yielded value
|
||||
|
Loading…
Reference in New Issue
Block a user