diff --git a/doc/source/conf.py b/doc/source/conf.py index 0fa2b19..51f7abd 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -52,9 +52,9 @@ master_doc = "index" # General information about the project. -project = u"docconvert" -copyright = u"2018, Ashley Whetter, Cameron Billingham" -author = u"2018, Cameron Billingham" +project = "docconvert" +copyright = "2018, Ashley Whetter, Cameron Billingham" +author = "2018, Cameron Billingham" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -197,8 +197,8 @@ ( master_doc, "docconvert.tex", - u"docconvert Documentation", - u"Cameron Billingham", + "docconvert Documentation", + "Cameron Billingham", "manual", ) ] diff --git a/doc/source/intro.rst b/doc/source/intro.rst index 4cbcca4..e8e3f55 100644 --- a/doc/source/intro.rst +++ b/doc/source/intro.rst @@ -259,9 +259,10 @@ use\_types "use_types": true Use types in argument output. Defaults to True. If False, argument, -keyword-argument, and attribute type definitions will be skipped. -This could be turned False for Python 3, where Sphinx recognizes -annotations. +keyword-argument, attribute, and return type definitions will be skipped +for output formats that support it (google and reST). +This can be turned False for Python 3, where Sphinx recognizes type +annotations from source code. See `type annotations`_. separate\_keywords '''''''''''''''''' @@ -272,3 +273,6 @@ separate\_keywords Separate keyword-arguments into their own docstring section. Defaults to False. If set to False, all keyword-arguments are documented with the other arguments. + + +.. _`type annotations`: https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html#type-annotations diff --git a/src/docconvert/parser/module.py b/src/docconvert/parser/module.py index 98af412..ebae4b4 100644 --- a/src/docconvert/parser/module.py +++ b/src/docconvert/parser/module.py @@ -342,10 +342,10 @@ def _visit_assign(self, node): start, end = _get_string_start_end(next_sibling.value) self.docstrings.append(default_docstring(start, end, self.lines[start:end])) next(siblings) # Consume the next sibling since we already processed it - + def _visit_children(self, node): """Iterate children of this node and process them. - + Args: node (ast.Node): An AST node to iterate under. """ @@ -460,7 +460,7 @@ def _get_string_start_end(node): class _Peekable(object): """Make a peekable version of a generator. - + Can peek at next item without incrementing main iterator. """ diff --git a/src/docconvert/writer/base.py b/src/docconvert/writer/base.py index f122356..d36ad87 100644 --- a/src/docconvert/writer/base.py +++ b/src/docconvert/writer/base.py @@ -348,6 +348,8 @@ def remove_back_ticks(self, text): Returns: str: The string with replaceable back ticks removed. """ + if not text: + return text removal_option = BackTickRemovalOption.from_bool_or_str( self.config.output.remove_type_back_ticks ) diff --git a/src/docconvert/writer/google.py b/src/docconvert/writer/google.py index c698caf..f26e0ba 100644 --- a/src/docconvert/writer/google.py +++ b/src/docconvert/writer/google.py @@ -132,8 +132,12 @@ def write_returns(self, element): Args: element (tuple): The docstring element. """ + kind = self.doc.return_field.kind if self.config.output.use_types else "" + kind = self.remove_back_ticks(kind) + if not kind and not self.doc.return_field.desc: + return + self.write_section_header("Returns") - kind = self.remove_back_ticks(self.doc.return_field.kind) if self.doc.return_field.desc: header = "{0}:".format(kind) if kind else None self.write_desc(self.doc.return_field.desc, header=header, hanging=False) diff --git a/src/docconvert/writer/rest.py b/src/docconvert/writer/rest.py index 6968419..79942a5 100644 --- a/src/docconvert/writer/rest.py +++ b/src/docconvert/writer/rest.py @@ -103,7 +103,8 @@ def write_returns(self, element): Args: element (tuple): The docstring element. """ - kind = self.remove_back_ticks(self.doc.return_field.kind) + kind = self.doc.return_field.kind if self.config.output.use_types else "" + kind = self.remove_back_ticks(kind) if self.doc.return_field.desc: header = self._field_token.format("returns") self.write_desc(self.doc.return_field.desc, header=header, indent=0) diff --git a/tests/test_google_writer.py b/tests/test_google_writer.py index 66d421e..da95306 100644 --- a/tests/test_google_writer.py +++ b/tests/test_google_writer.py @@ -63,6 +63,28 @@ def test_write_args(self): '"""\n', ] + def test_write_args_without_types(self): + self.doc.add_element(("start_quote", '"""')) + self.doc.add_element(("raw", ["This is a docstring."])) + self.doc.add_arg("arg1", kind="str") + self.doc.add_arg( + "arg2", + kind="int", + desc=["Description.", "More description."], + optional=True, + ) + self.doc.add_element(("end_quote", '"""')) + self.config.output.use_types = False + writer = docconvert.writer.GoogleWriter(self.doc, "", self.config) + assert writer.write() == [ + '"""This is a docstring.\n', + "\n", + "Args:\n", + " arg1\n", + " arg2: Description. More description.\n", + '"""\n', + ] + def test_write_args_with_optional(self): self.doc.add_element(("start_quote", '"""')) self.doc.add_element(("raw", ["This is a docstring."])) @@ -158,6 +180,19 @@ def test_write_returns(self): '"""\n', ] + def test_write_returns_without_types(self): + self.doc.add_element(("start_quote", '"""')) + self.doc.add_return("str", desc=["Description.", "More description."]) + self.doc.add_element(("end_quote", '"""')) + self.config.output.use_types = False + writer = docconvert.writer.GoogleWriter(self.doc, "", self.config) + assert writer.write() == [ + '"""\n', + "Returns:\n", + " Description. More description.\n", + '"""\n', + ] + def test_write_directives(self): self.doc.add_element(("start_quote", '"""')) self.doc.add_element(("note", ["Description.", "More description."])) diff --git a/tests/test_numpy_writer.py b/tests/test_numpy_writer.py index 6cf4242..6ea84d0 100644 --- a/tests/test_numpy_writer.py +++ b/tests/test_numpy_writer.py @@ -69,6 +69,30 @@ def test_write_args(self): '"""\n', ] + def test_write_args_without_types(self): + self.doc.add_element(("start_quote", '"""')) + self.doc.add_element(("raw", ["This is a docstring."])) + self.doc.add_arg("arg1", kind="str") + self.doc.add_arg( + "arg2", + kind="int", + desc=["Description.", "More description."], + optional=True, + ) + self.doc.add_element(("end_quote", '"""')) + self.config.output.use_types = False + writer = docconvert.writer.NumpyWriter(self.doc, "", self.config) + assert writer.write() == [ + '"""This is a docstring.\n', + "\n", + "Parameters\n", + "----------\n", + "arg1\n", + "arg2\n", + " Description. More description.\n", + '"""\n', + ] + def test_write_args_with_optional(self): self.doc.add_element(("start_quote", '"""')) self.doc.add_element(("raw", ["This is a docstring."])) diff --git a/tests/test_rest_writer.py b/tests/test_rest_writer.py index 69c7b5a..3573631 100644 --- a/tests/test_rest_writer.py +++ b/tests/test_rest_writer.py @@ -61,6 +61,26 @@ def test_write_args(self): '"""\n', ] + def test_write_args_without_types(self): + self.doc.add_element(("start_quote", '"""')) + self.doc.add_element(("raw", ["This is a docstring."])) + self.doc.add_arg("arg1", kind="str") + self.doc.add_arg( + "arg2", + kind="int", + desc=["Description.", "More description."], + optional=True, + ) + self.doc.add_element(("end_quote", '"""')) + self.config.output.use_types = False + writer = docconvert.writer.RestWriter(self.doc, "", self.config) + assert writer.write() == [ + '"""This is a docstring.\n', + ":param arg1:\n", + ":param arg2: Description. More description.\n", + '"""\n', + ] + def test_write_args_with_optional(self): self.doc.add_element(("start_quote", '"""')) self.doc.add_element(("raw", ["This is a docstring."])) @@ -153,6 +173,18 @@ def test_write_returns(self): '"""\n', ] + def test_write_returns_without_types(self): + self.doc.add_element(("start_quote", '"""')) + self.doc.add_return("str", desc=["Description.", "More description."]) + self.doc.add_element(("end_quote", '"""')) + self.config.output.use_types = False + writer = docconvert.writer.RestWriter(self.doc, "", self.config) + assert writer.write() == [ + '"""\n', + ":returns: Description. More description.\n", + '"""\n', + ] + def test_write_directives(self): self.doc.add_element(("start_quote", '"""')) self.doc.add_element(("note", ["Description.", "More description."]))