source: rtems-central/rtemsqual/applconfig.py @ b11b567

Last change on this file since b11b567 was b11b567, checked in by Sebastian Huber <sebastian.huber@…>, on 03/30/20 at 08:01:20

applconfig: Support initializer options

  • Property mode set to 100644
File size: 8.2 KB
Line 
1# SPDX-License-Identifier: BSD-2-Clause
2""" Functions for application configuration documentation generation. """
3
4# Copyright (C) 2019, 2020 embedded brains GmbH (http://www.embedded-brains.de)
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9# 1. Redistributions of source code must retain the above copyright
10#    notice, this list of conditions and the following disclaimer.
11# 2. Redistributions in binary form must reproduce the above copyright
12#    notice, this list of conditions and the following disclaimer in the
13#    documentation and/or other materials provided with the distribution.
14#
15# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25# POSSIBILITY OF SUCH DAMAGE.
26
27from typing import Any, Dict, List
28
29from rtemsqual.content import SphinxContent
30from rtemsqual.items import Item, ItemCache
31
32ItemMap = Dict[str, Item]
33
34
35def _gather_groups(item: Item, groups: ItemMap) -> None:
36    for child in item.children:
37        _gather_groups(child, groups)
38    if item["type"] == "interface" and item[
39            "interface-type"] == "appl-config-group":
40        groups[item.uid] = item
41
42
43def _gather_options(item: Item, options: ItemMap) -> None:
44    for child in item.children:
45        _gather_options(child, options)
46    if item["type"] == "interface" and item[
47            "interface-type"] == "appl-config-option":
48        options[item.uid] = item
49
50
51_FEATURE = "This configuration option is a boolean feature define."
52
53_OPTION_TYPES = {
54    "feature": _FEATURE,
55    "feature-enable": _FEATURE,
56    "integer": "This configuration option is an integer define.",
57    "initializer": "This configuration option is an initializer define."
58}
59
60_OPTION_DEFAULT_CONFIG = {
61    "feature":
62    lambda item: item["appl-config-option-default"],
63    "feature-enable":
64    lambda item:
65    """If this configuration option is undefined, then the described feature is not
66enabled."""
67}
68
69
70def _generate_feature(content: SphinxContent, item: Item,
71                      option_type: str) -> None:
72    content.add_definition_item("DEFAULT CONFIGURATION:",
73                                _OPTION_DEFAULT_CONFIG[option_type](item))
74
75
76def _generate_min_max(lines: List[str], value: str, word: str) -> None:
77    lines.append("The value of this configuration option must be "
78                 f"{word} than or equal to {value}.")
79
80
81def _generate_set(lines: List[str], values: List[Any]) -> None:
82    value_set = "{" + ", ".join([str(x) for x in values]) + "}"
83    lines.append("The value of this configuration option must be")
84    lines.append(f"an element of {value_set}.")
85
86
87def _start_constraint_list(lines: List[str]) -> None:
88    lines.append("The value of this configuration option must "
89                 "satisfy all of the following")
90    lines.append("constraints:")
91
92
93def _generate_item_min(lines: List[str], constraint: Dict[str, Any]) -> None:
94    if "min" in constraint:
95        value = constraint["min"]
96        lines.append("")
97        lines.append(f"* It must be greater than or equal to {value}.")
98
99
100def _generate_item_max(lines: List[str], constraint: Dict[str, Any]) -> None:
101    if "max" in constraint:
102        value = constraint["max"]
103        lines.append("")
104        lines.append(f"* It must be less than or equal to {value}.")
105
106
107def _generate_item_custom(lines: List[str], constraint: Dict[str,
108                                                             Any]) -> None:
109    for custom in constraint.get("custom", []):
110        lines.append("")
111        custom = custom.strip().split("\n")
112        lines.append(f"* {custom[0]}")
113        lines.extend([f"  {x}" for x in custom[1:]])
114
115
116def _generate_constraint(content: SphinxContent, item: Item) -> None:
117    constraint = item["appl-config-option-constraint"]
118    count = len(constraint)
119    lines = []  # type: List[str]
120    if count == 1:
121        if "min" in constraint:
122            _generate_min_max(lines, constraint["min"], "greater")
123        elif "max" in constraint:
124            _generate_min_max(lines, constraint["max"], "less")
125        elif "set" in constraint:
126            _generate_set(lines, constraint["set"])
127        elif "custom" in constraint:
128            if len(constraint["custom"]) == 1:
129                lines.extend(constraint["custom"][0].strip().split("\n"))
130            else:
131                _start_constraint_list(lines)
132                _generate_item_custom(lines, constraint)
133        else:
134            raise ValueError
135    elif count == 2 and "min" in constraint and "max" in constraint:
136        minimum = constraint["min"]
137        maximum = constraint["max"]
138        lines.append("The value of this configuration option must be "
139                     f"greater than or equal to {minimum}")
140        lines.append(f"and less than or equal to {maximum}.")
141    else:
142        _start_constraint_list(lines)
143        _generate_item_min(lines, constraint)
144        _generate_item_max(lines, constraint)
145        _generate_item_custom(lines, constraint)
146    content.add_definition_item("VALUE CONSTRAINTS:", lines)
147
148
149def _generate_initializer_or_integer(content: SphinxContent, item: Item,
150                                     _option_type: str) -> None:
151    default_value = item["appl-config-option-default-value"]
152    if not isinstance(default_value, str) or " " not in default_value:
153        default_value = f"The default value is {default_value}."
154    content.add_definition_item("DEFAULT VALUE:", default_value)
155    _generate_constraint(content, item)
156
157
158_OPTION_GENERATORS = {
159    "feature": _generate_feature,
160    "feature-enable": _generate_feature,
161    "initializer": _generate_initializer_or_integer,
162    "integer": _generate_initializer_or_integer
163}
164
165
166def _generate_content(group: Item, options: ItemMap) -> SphinxContent:
167    content = SphinxContent()
168    group.register_license_and_copyrights(content)
169    content.add_header(group["appl-config-group-name"], level="=")
170    content.add_blank_line()
171    content.add_lines(group["appl-config-group-description"])
172    for item in sorted(options.values(), key=lambda x: x.uid):
173        name = item["appl-config-option-name"]
174        item.register_license_and_copyrights(content)
175        content.add_index_entries([name] + item["appl-config-option-index"])
176        content.add_blank_line()
177        content.add_label(name)
178        content.add_blank_line()
179        content.add_header(name, level="-")
180        content.add_definition_item("CONSTANT:", f"``{name}``")
181        option_type = item["appl-config-option-type"]
182        content.add_definition_item("OPTION TYPE:", _OPTION_TYPES[option_type])
183        _OPTION_GENERATORS[option_type](content, item, option_type)
184        content.add_definition_item("DESCRIPTION:",
185                                    item["appl-config-option-description"])
186        content.add_definition_item("NOTES:", item["appl-config-option-notes"])
187    content.add_licence_and_copyrights()
188    return content
189
190
191def generate(config: dict, item_cache: ItemCache) -> None:
192    """
193    Generates application configuration documentation sources according to the
194    configuration.
195
196    :param config: A dictionary with configuration entries.
197    :param item_cache: The specification item cache containing the application
198                       configuration groups and options.
199    """
200    groups = {}  # type: ItemMap
201    for item in item_cache.top_level.values():
202        _gather_groups(item, groups)
203
204    for group_config in config["groups"]:
205        group = groups[group_config["uid"]]
206        options = {}  # type: ItemMap
207        _gather_options(group, options)
208        content = _generate_content(group, options)
209        content.write(group_config["target"])
Note: See TracBrowser for help on using the repository browser.