From cfd4e51802724b77250f76aeb62ab6e4908534a9 Mon Sep 17 00:00:00 2001 From: Ashley Whetter Date: Tue, 2 Aug 2016 21:29:07 +0100 Subject: [PATCH] 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. --- doc/domains.rst | 12 ++++++++++++ doc/ext/example_google.py | 6 +++--- doc/ext/example_numpy.py | 6 +++--- sphinx/domains/python.py | 21 +++++++++++++++++++++ sphinx/ext/napoleon/docstring.py | 13 ++++--------- sphinx/util/docfields.py | 27 +++++++++++++++++---------- tests/test_ext_napoleon_docstring.py | 18 ++++++++++++++++++ 7 files changed, 78 insertions(+), 25 deletions(-) diff --git a/doc/domains.rst b/doc/domains.rst index 2aaf218c0..a259cbccd 100644 --- a/doc/domains.rst +++ b/doc/domains.rst @@ -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 diff --git a/doc/ext/example_google.py b/doc/ext/example_google.py index c3ba273b8..34a720e36 100644 --- a/doc/ext/example_google.py +++ b/doc/ext/example_google.py @@ -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 diff --git a/doc/ext/example_numpy.py b/doc/ext/example_numpy.py index 0e71008e1..7a2db94cc 100644 --- a/doc/ext/example_numpy.py +++ b/doc/ext/example_numpy.py @@ -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 diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py index 06a6b3002..3d7e10467 100644 --- a/sphinx/domains/python.py +++ b/sphinx/domains/python.py @@ -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 diff --git a/sphinx/ext/napoleon/docstring.py b/sphinx/ext/napoleon/docstring.py index c3d5bb3d0..f306b4ddc 100644 --- a/sphinx/ext/napoleon/docstring.py +++ b/sphinx/ext/napoleon/docstring.py @@ -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'(?