Skip to content

Commit 5fc7c1a

Browse files
committed
Path parsing of Returns block by Napoleon extension
1 parent beab9ef commit 5fc7c1a

File tree

1 file changed

+56
-0
lines changed

1 file changed

+56
-0
lines changed

doc/conf.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from datetime import datetime
1010

1111
from sphinx.ext.autodoc import FunctionDocumenter
12+
from sphinx.ext.napoleon import NumpyDocstring, docstring
1213

1314
from dpnp.dpnp_algo.dpnp_elementwise_common import DPNPBinaryFunc, DPNPUnaryFunc
1415

@@ -231,3 +232,58 @@ def _can_document_member(member, *args, **kwargs):
231232
napoleon_use_ivar = True
232233
napoleon_include_special_with_doc = True
233234
napoleon_custom_sections = ["limitations"]
235+
236+
237+
# Napoleon extension can't properly render "Returns" section in case of
238+
# namedtuple as a return type. That patch proposes to extend the parse logic
239+
# which allows text in a header of "Returns" section.
240+
def _parse_returns_section_patched(self, section: str) -> list[str]:
241+
fields = self._consume_returns_section()
242+
multi = len(fields) > 1
243+
use_rtype = False if multi else self._config.napoleon_use_rtype
244+
lines: list[str] = []
245+
246+
for _name, _type, _desc in fields:
247+
is_header_block = False
248+
if _name == "" and (not _desc or len(_desc) == 1 and _desc[0] == ""):
249+
# self._consume_returns_section() stores the header block
250+
# into `_type` argument, while `_name` and `_desc` have to be empty
251+
is_header_block = True
252+
if not lines:
253+
docstring.logger.info(
254+
"parse a header block of 'Returns' section",
255+
location=self._get_location(),
256+
)
257+
258+
if use_rtype:
259+
field = self._format_field(_name, "", _desc)
260+
elif not is_header_block:
261+
field = self._format_field(_name, _type, _desc)
262+
else:
263+
# assign processing field to `_type` value
264+
field = _type
265+
266+
if multi:
267+
if lines:
268+
if is_header_block:
269+
# add the next line of header text
270+
lines.append(field)
271+
else:
272+
lines.extend(self._format_block(" * ", field))
273+
else:
274+
if is_header_block:
275+
# add a beginning of header text
276+
lines.extend([":returns:", "", field])
277+
else:
278+
lines.extend(self._format_block(":returns: * ", field))
279+
else:
280+
if any(field): # only add :returns: if there's something to say
281+
lines.extend(self._format_block(":returns: ", field))
282+
if _type and use_rtype:
283+
lines.extend([f":rtype: {_type}", ""])
284+
if lines and lines[-1]:
285+
lines.append("")
286+
return lines
287+
288+
289+
NumpyDocstring._parse_returns_section = _parse_returns_section_patched

0 commit comments

Comments
 (0)