mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Python domain can now link container types automatically
Google types now greedily match the closing parenthesis. Also removed name from returns section in Google docstrings. Instead, everything before the colon is treated as the type.
This commit is contained in:
parent
86c9767ced
commit
cfd4e51802
@ -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