Test Failed
Push — master ( e26e75...729ab1 )
by Nicola
01:26 queued 17s
created

create_plugin_template_doc   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 219
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 115
dl 0
loc 219
rs 10
c 0
b 0
f 0
wmc 19

6 Functions

Rating   Name   Duplication   Size   Complexity  
C create_template_class_dict() 0 45 9
A _get_download_string() 0 2 1
B create_plugin_template_downloads() 0 74 5
A generate_template_files() 0 30 2
A _get_include_string() 0 4 1
A filter_template_numbers() 0 11 1
1
# Copyright 2014 Diamond Light Source Ltd.
2
#
3
# Licensed under the Apache License, Version 2.0 (the "License");
4
# you may not use this file except in compliance with the License.
5
# You may obtain a copy of the License at
6
#
7
#     http://www.apache.org/licenses/LICENSE-2.0
8
#
9
# Unless required by applicable law or agreed to in writing, software
10
# distributed under the License is distributed on an "AS IS" BASIS,
11
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
# See the License for the specific language governing permissions and
13
# limitations under the License.
14
15
"""
16
.. module:: create_plugin_template_doc
17
   :platform: Unix
18
   :synopsis: A module to create plugin template rst files for documentation
19
20
.. moduleauthor:: Jessica Verschoyle <[email protected]>
21
22
"""
23
24
import os
25
import re
26
27
from collections import OrderedDict
28
29
import savu.plugins.utils as pu
30
import doc.create_plugin_doc as pdoc
31
32
33
def create_plugin_template_downloads(savu_base_path):
34
    """Inside plugin_examples/plugin_templates/general
35
    If the file begins with 'plugin_template' then select it
36
    Read the lines of the files docstring and set as a descriptor
37
    """
38
    dev_file_path = f"{savu_base_path}doc/source/dev_guides/"
39
    doc_template_file = f"{dev_file_path}dev_plugin_templates.rst"
40
41
    # Populate dictionary with template class and template class docstring
42
    docstring_text = create_template_class_dict(savu_base_path)
43
    if docstring_text:
44
        with open(doc_template_file, "w") as doc_template:
45
            doc_template.write(".. _plugin_templates:\n")
46
            doc_template.write("\n")
47
            doc_template.write(f"Plugin templates {pdoc.set_underline(6 ,23)}")
48
            doc_template.write("\n")
49
50
            doc_name = "plugin_template1_with_detailed_notes"
51
            detailed_template = docstring_text.get(doc_name)
52
53
            if detailed_template:
54
                docstring_text.pop(doc_name)
55
                title = pdoc.convert_title(doc_name)
56
                title, number = filter_template_numbers(title)
57
                # Create the restructured text page for the plugin template
58
                # python code
59
                generate_template_files(doc_name, title)
60
                inner_file_str = \
61
                    "../../../plugin_examples/plugin_templates/general"
62
                doc_template.write(f"{title}{pdoc.set_underline(3 ,66)}")
63
                doc_template.write(
64
                    "\nA template to create a simple plugin "
65
                    "that takes one dataset as input and returns "
66
                    "a similar dataset as output"
67
                )
68
                doc_template.write("\n")
69
                doc_template.write(
70
                    """
71
.. list-table::  
72
   :widths: 10
73
74
   * - :ref:`"""
75
                    + doc_name
76
                    + """`
77
78
"""
79
                )
80
            doc_template.write(f"Further Examples{pdoc.set_underline(3 ,66)}")
81
            # Begin the table layout
82
            doc_template.write(
83
                """
84
.. list-table::  
85
   :widths: 10 90
86
   :header-rows: 1
87
88
   * - Link
89
     - Description"""
90
            )
91
92
            for doc_name, doc_str in docstring_text.items():
93
                title = pdoc.convert_title(doc_name)
94
                title, number = filter_template_numbers(title)
95
                desc_str = doc_str["desc"]
96
                # Create a link to the restructured text page view of
97
                # the python code for the template
98
                doc_template.write("\n   * - :ref:`" + doc_name + "`")
99
                # The template description from the docstring
100
                doc_template.write("\n     - " + desc_str)
101
                doc_template.write("\n")
102
                # Create the restructured text page for the plugin template
103
                # python code
104
                generate_template_files(doc_name, title)
105
106
            doc_template.write("\n")
107
108
109
def generate_template_files(doc_name, title):
110
    """Create a restructured text file which will include the python
111
     code for the plugin template 'doc_name'
112
113
    :param doc_name: The name of the template file
114
    :param title:
115
    :return:
116
    """
117
    inner_file_str = "../../../../plugin_examples/plugin_templates/general"
118
    template_file_path = \
119
        f"{savu_base_path}doc/source/dev_guides/templates/{doc_name}.rst"
120
121
    with open(template_file_path, "w") as tfile:
122
        # Add the orphan instruction as this file is not inside a toctree
123
        tfile.write(":orphan:\n")
124
        tfile.write("\n.. _" + doc_name + ":\n")
125
        tfile.write("\n")
126
        tfile.write(f"{title}{pdoc.set_underline(4, 39)}")
127
        tfile.write("\n")
128
        tfile.write(_get_download_string(title, inner_file_str, doc_name))
129
        tfile.write("\n")
130
        tfile.write(_get_download_string(f"{title} Tools",
131
                                         inner_file_str,
132
                                         f"{doc_name}_tools"))
133
        tfile.write("\n")
134
        tfile.write(_get_include_string(doc_name))
135
        tfile.write("\n    :language: python\n")
136
        tfile.write("\n")
137
        tfile.write(_get_include_string(f"{doc_name}_tools"))
138
        tfile.write("\n    :language: python\n")
139
140
141
def _get_download_string(label, inner_file, doc_name):
142
    return f":download:`Download {label}<{inner_file}/{doc_name}.py>`\n\n"
143
144
145
def _get_include_string(doc_name):
146
    include_str = f".. literalinclude:: " \
147
                  f"/../../plugin_examples/plugin_templates/general/{doc_name}.py"
148
    return include_str
149
150
151
def filter_template_numbers(name_string):
152
    """
153
    :param name_string: The name of the template
154
    :return: A string with the template number seperated by a space
155
    """
156
    number = "".join(l for l in name_string if l.isdigit())
157
    letters = "".join(l for l in name_string if l.isalpha())
158
    split_uppercase = [l for l in re.split("([A-Z][^A-Z]*)", letters) if l]
159
    title = " ".join(split_uppercase)
160
    name = title + " " + number
161
    return name, number
162
163
164
def create_template_class_dict(savu_base_path):
165
    """Iterate through the plugin example folder and store the class
166
    and it's class docstring into a dictionary docstring_text
167
168
    :param savu_base_path:
169
    :return: docstring_text dictionary of class and docstring
170
    """
171
    docstring_text = {}
172
    plugin_ex_path = \
173
        f"{savu_base_path}plugin_examples/plugin_templates/general"
174
175
    for t_root, t_dirs, template_files \
176
            in os.walk(plugin_ex_path, topdown=True):
177
        template_files[:] = [fi for fi in template_files
178
                             if fi.split(".")[-1] == "py"
179
                             and "tools" not in fi]
180
        if "__" not in t_root:
181
            pkg_path = t_root.split("Savu/")[1]
182
            module_name = pkg_path.replace("/", ".")
183
184
        for fi in template_files:
185
            file_name = fi.split(".py")[0]
186
            cls_module = module_name + "." + file_name
0 ignored issues
show
introduced by
The variable module_name does not seem to be defined for all execution paths.
Loading history...
187
            try:
188
                cls_loaded = pu.load_class(cls_module)()
189
            except AttributeError as e:
190
                cls_loaded = None
191
192
            if cls_loaded:
193
                tools = cls_loaded.get_plugin_tools()
194
                doc = tools.get_doc() if tools else ""
195
                desc = doc.get("verbose") if isinstance(doc ,dict) else ""
196
                title = pdoc.convert_title(file_name)
197
                name, number = filter_template_numbers(title)
198
                docstring_text[file_name] = {
199
                    "desc": desc,
200
                    "number": int(number),
201
                }
202
203
    # Order templates by number
204
    docstring_text = OrderedDict(
205
        sorted(docstring_text.items(), key=lambda i: i[1]["number"])
206
    )
207
208
    return docstring_text
209
210
211
if __name__ == "__main__":
212
    # determine Savu base path
213
    main_dir = \
214
        os.path.dirname(os.path.realpath(__file__)).split("/Savu/")[0]
215
    savu_base_path = f"{main_dir}/Savu/"
216
217
    # Create template download page
218
    create_plugin_template_downloads(savu_base_path)
219