|
9 | 9 | from datetime import datetime
|
10 | 10 |
|
11 | 11 | from sphinx.ext.autodoc import FunctionDocumenter
|
| 12 | +from sphinx.ext.napoleon import NumpyDocstring, docstring |
12 | 13 |
|
13 | 14 | from dpnp.dpnp_algo.dpnp_elementwise_common import DPNPBinaryFunc, DPNPUnaryFunc
|
14 | 15 |
|
@@ -231,3 +232,58 @@ def _can_document_member(member, *args, **kwargs):
|
231 | 232 | napoleon_use_ivar = True
|
232 | 233 | napoleon_include_special_with_doc = True
|
233 | 234 | 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