From 1ece62ca10e39e5ba4fce8b98243faee17e12db7 Mon Sep 17 00:00:00 2001 From: Sam Tygier Date: Mon, 19 Jul 2021 12:01:52 +0100 Subject: [PATCH] operation docs: extract from doc strings Use the class docstring plus the parameter list from the filter_func. --- docs/ext/operations_user_doc.py | 64 ++++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/docs/ext/operations_user_doc.py b/docs/ext/operations_user_doc.py index 006543b1841..624824726c9 100644 --- a/docs/ext/operations_user_doc.py +++ b/docs/ext/operations_user_doc.py @@ -1,8 +1,13 @@ # Copyright (C) 2021 ISIS Rutherford Appleton Laboratory UKRI # SPDX - License - Identifier: GPL-3.0-or-later +from typing import List + from docutils import nodes +from docutils.nodes import Node +from docutils.statemachine import ViewList from docutils.parsers.rst import Directive +from sphinx.util.nodes import nested_parse_with_titles """Custom extension to add nicely formatted documentation for the operations. Use: @@ -12,20 +17,71 @@ """ +def make_heading(s: str, char: str) -> List[str]: + return [s, len(s) * char, ""] + + +def split_lines(s: str) -> List[str]: + s = s.replace("\n\n", "DOUBLE_NEW_LINE") + s = s.replace("\n", " ") + s = s.replace("DOUBLE_NEW_LINE", "\n\n") + return s.split("\n") + + +PARAM_SKIP_LIST = ["images", "cores", "chunksize", "progress"] + + +def get_params(s: str) -> List[str]: + ret = [] + for line in s.split("\n"): + if line.strip().startswith(":param"): + param_name = line.strip().split()[1].strip(':') + if param_name in PARAM_SKIP_LIST: + continue + ret.append(line.strip()) + elif line.strip().startswith(":return"): + pass + elif line.strip() and ret: + ret[-1] = ret[-1] + " " + line.strip() + + return ret + + class OperationsUserDoc(Directive): - def run(self): + def run(self) -> List[Node]: - paragraphs = [] try: from mantidimaging.core.operations.loader import load_filter_packages except ImportError: raise ValueError("operations_user_doc could not import load_filter_packages") + rst_lines = [] + operations = load_filter_packages() for op in operations: - paragraphs.append(nodes.paragraph(text=op.filter_name)) + # Title + rst_lines += make_heading(op.filter_name, "-") + + # Description from class doc string + rst_lines += split_lines(op.__doc__) + rst_lines.append("") + + # parameters from filter_func + if op.filter_func.__doc__ is not None: + rst_lines += get_params(op.filter_func.__doc__) + rst_lines.append("") + + rst = ViewList() + for n, rst_line in enumerate(rst_lines): + rst.append(rst_line, "generated.rst", n) + print(n, ">", rst_line) + + node = nodes.section() + node.document = self.state.document + + nested_parse_with_titles(self.state, rst, node) - return paragraphs + return node.children def setup(app):