Skip to content

Commit

Permalink
Fixed possible incorrect indentation in generated documentation.
Browse files Browse the repository at this point in the history
Closes #299.
  • Loading branch information
AWhetter committed Aug 1, 2021
1 parent 3545351 commit 7d7f042
Show file tree
Hide file tree
Showing 8 changed files with 51 additions and 11 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ Changelog

Versions follow `Semantic Versioning <https://semver.org/>`_ (``<major>.<minor>.<patch>``).

v1.8.3 (TBC)
-------------------

Bug Fixes
^^^^^^^^^
* `#299 <https://github.com/readthedocs/sphinx-autoapi/issues/299>`: (Python)
Fixed incorrect indentation in generated documentation when a class with no
constructor has a summary line spanning multiple lines.


v1.8.2 (2021-07-26)
-------------------

Expand Down
3 changes: 1 addition & 2 deletions autoapi/mappers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import sphinx.util
from sphinx.util.console import darkgreen, bold
from sphinx.util.osutil import ensuredir
from sphinx.util.docstrings import prepare_docstring
import sphinx.util.logging
import unidecode

Expand Down Expand Up @@ -190,7 +189,7 @@ def __init__(self, app, template_dir=None, url_root=None):
)

def _wrapped_prepare(value):
return "\n".join(prepare_docstring(value))
return value

self.jinja_env.filters["prepare_docstring"] = _wrapped_prepare
if self.app.config.autoapi_prepare_jinja_env:
Expand Down
3 changes: 2 additions & 1 deletion autoapi/mappers/python/mapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,8 @@ def create_class(self, data, options=None, **kwargs):
# Some objects require children to establish their docstring
# or type annotations (eg classes with inheritance),
# so do this after all children have been created.
lines = sphinx.util.docstrings.prepare_docstring(obj.docstring)
lines = obj.docstring.splitlines()
lines.append("") # Add back the trailing newline that .splitlines removes
if lines and "autodoc-process-docstring" in self.app.events.events:
self.app.emit(
"autodoc-process-docstring", cls.type, obj.name, None, None, lines
Expand Down
10 changes: 6 additions & 4 deletions autoapi/mappers/python/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ def __init__(self, obj, class_content="class", **kwargs):

# Optional
self.children = []
self.docstring = obj["doc"]
self._docstring = obj["doc"]
self._docstring_resolved = False
self.imported = "original_path" in obj
self.inherited = obj.get("inherited", False)
"""Whether this was inherited from an ancestor of the parent class.
Expand Down Expand Up @@ -79,6 +80,7 @@ def docstring(self):
@docstring.setter
def docstring(self, value):
self._docstring = value
self._docstring_resolved = True

@property
def is_undoc_member(self):
Expand Down Expand Up @@ -386,9 +388,9 @@ def overloads(self):

@property
def docstring(self):
docstring = super(PythonClass, self).docstring
docstring = super().docstring

if self._class_content in ("both", "init"):
if not self._docstring_resolved and self._class_content in ("both", "init"):
constructor_docstring = self.constructor_docstring

if constructor_docstring:
Expand All @@ -401,7 +403,7 @@ def docstring(self):

@docstring.setter
def docstring(self, value):
self._docstring = value
super(PythonClass, self.__class__).docstring.fset(self, value)

@property
def methods(self):
Expand Down
14 changes: 10 additions & 4 deletions autoapi/mappers/python/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,15 @@

import astroid
import astroid.builder
import sphinx.util.docstrings

from . import astroid_utils


def _prepare_docstring(doc):
return "\n".join(sphinx.util.docstrings.prepare_docstring(doc))


class Parser:
def __init__(self):
self._name_stack = []
Expand Down Expand Up @@ -72,7 +78,7 @@ def parse_assign(self, node):
"type": type_,
"name": target,
"full_name": self._get_full_name(target),
"doc": doc,
"doc": _prepare_docstring(doc),
"value": value,
"from_line_no": node.fromlineno,
"to_line_no": node.tolineno,
Expand All @@ -93,7 +99,7 @@ def parse_classdef(self, node, data=None):
"name": node.name,
"full_name": self._get_full_name(node.name),
"bases": basenames,
"doc": astroid_utils.get_class_docstring(node),
"doc": _prepare_docstring(astroid_utils.get_class_docstring(node)),
"from_line_no": node.fromlineno,
"to_line_no": node.tolineno,
"children": [],
Expand Down Expand Up @@ -162,7 +168,7 @@ def parse_functiondef(self, node): # pylint: disable=too-many-branches
"name": node.name,
"full_name": self._get_full_name(node.name),
"args": astroid_utils.get_args_info(node.args),
"doc": astroid_utils.get_func_docstring(node),
"doc": _prepare_docstring(astroid_utils.get_func_docstring(node)),
"from_line_no": node.fromlineno,
"to_line_no": node.tolineno,
"return_annotation": astroid_utils.get_return_annotation(node),
Expand Down Expand Up @@ -218,7 +224,7 @@ def parse_module(self, node):
"type": type_,
"name": node.name,
"full_name": node.name,
"doc": node.doc or "",
"doc": _prepare_docstring(node.doc or ""),
"children": [],
"file_path": path,
"encoding": node.file_encoding,
Expand Down
1 change: 1 addition & 0 deletions tests/python/pyexample/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@
autoapi_type = "python"
autoapi_dirs = ["example"]
autoapi_file_pattern = "*.py"
autoapi_python_class_content = "both"
17 changes: 17 additions & 0 deletions tests/python/pyexample/example/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,20 @@ def method_okay(self, foo=None, bar=None):

class ClassWithNoInit:
pass


class One:
"""One."""

def __init__(self):
"""One __init__."""
super().__init__()


class MultilineOne(One):
"""This is a naughty summary line
that exists on two lines."""


class Two(One):
"""Two."""
4 changes: 4 additions & 0 deletions tests/python/test_pyintegration.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ def check_integration(self, example_path):

assert not os.path.exists("_build/text/autoapi/method_multiline")

# Inherited constructor docstrings should be included in a merged
# (autoapi_python_class_content="both") class docstring only once.
assert example_file.count("One __init__.") == 3

index_path = "_build/text/index.txt"
with io.open(index_path, encoding="utf8") as index_handle:
index_file = index_handle.read()
Expand Down

0 comments on commit 7d7f042

Please sign in to comment.