source: rtems-central/rtemsspec/glossary.py @ d9fa7d6

Last change on this file since d9fa7d6 was e49c759, checked in by Sebastian Huber <sebastian.huber@…>, on 07/15/20 at 08:04:25

Rename "rtemsqual" in "rtemsspec"

  • Property mode set to 100644
File size: 5.5 KB
Line 
1# SPDX-License-Identifier: BSD-2-Clause
2""" This module provides functions for glossary of terms 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
27import glob
28import re
29from typing import Any, Dict, NamedTuple
30
31from rtemsspec.sphinxcontent import SphinxContent, SphinxMapper
32from rtemsspec.items import Item, ItemCache, ItemGetValueContext, ItemMapper
33
34ItemMap = Dict[str, Item]
35
36
37class _Glossary(NamedTuple):
38    """ A glossary of terms. """
39    uid_to_item: ItemMap = {}
40    term_to_item: ItemMap = {}
41
42
43def _gather_glossary_groups(item: Item, glossary_groups: ItemMap) -> None:
44    for child in item.children():
45        _gather_glossary_groups(child, glossary_groups)
46    if item["type"] == "glossary" and item["glossary-type"] == "group":
47        glossary_groups[item.uid] = item
48
49
50def _gather_glossary_terms(item: Item, glossary: _Glossary) -> None:
51    for child in item.children():
52        _gather_glossary_terms(child, glossary)
53    if item["type"] == "glossary" and item["glossary-type"] == "term":
54        glossary.uid_to_item[item.uid] = item
55        term = item["term"]
56        assert term not in glossary.term_to_item
57        glossary.term_to_item[term] = item
58
59
60def _generate_glossary_content(terms: ItemMap) -> SphinxContent:
61    content = SphinxContent()
62    content.add_header("Glossary", level=1)
63    content.add(".. glossary::")
64    with content.indent():
65        content.add(":sorted:")
66        for item in sorted(terms.values(), key=lambda x: x["term"].lower()):
67            content.register_license_and_copyrights_of_item(item)
68            text = SphinxMapper(item).substitute(item["text"])
69            content.add_definition_item(item["term"], text)
70    content.add_licence_and_copyrights()
71    return content
72
73
74def _find_glossary_terms(path: str, document_terms: ItemMap,
75                         glossary: _Glossary) -> None:
76    for src in glob.glob(path + "/**/*.rst", recursive=True):
77        if src.endswith("glossary.rst"):
78            continue
79        with open(src, "r") as out:
80            for term in re.findall(":term:`([^`]+)`", out.read()):
81                item = glossary.term_to_item[term]
82                document_terms[item.uid] = item
83
84
85class _GlossaryMapper(ItemMapper):
86    def __init__(self, item: Item, document_terms: ItemMap):
87        super().__init__(item)
88        self._document_terms = document_terms
89
90    def get_value(self, ctx: ItemGetValueContext) -> Any:
91        """ Recursively adds glossary terms to the document terms. """
92        if ctx.type_path_key == "glossary/term:/term":
93            if ctx.item.uid not in self._document_terms:
94                self._document_terms[ctx.item.uid] = ctx.item
95                _GlossaryMapper(ctx.item, self._document_terms).substitute(
96                    ctx.item["text"])
97        # The value of this substitute is unused.
98        return ""
99
100
101def _resolve_glossary_terms(document_terms: ItemMap) -> None:
102    for term in list(document_terms.values()):
103        _GlossaryMapper(term, document_terms).substitute(term["text"])
104
105
106def _generate_project_glossary(target: str, glossary: _Glossary) -> None:
107    content = _generate_glossary_content(glossary.uid_to_item)
108    content.write(target)
109
110
111def _generate_document_glossary(config: dict, glossary: _Glossary) -> None:
112    document_terms = {}  # type: ItemMap
113    for path in config["rest-source-paths"]:
114        _find_glossary_terms(path, document_terms, glossary)
115    _resolve_glossary_terms(document_terms)
116    content = _generate_glossary_content(document_terms)
117    content.write(config["target"])
118
119
120def generate(config: dict, item_cache: ItemCache) -> None:
121    """
122    Generates glossaries of terms according to the configuration.
123
124    :param config: A dictionary with configuration entries.
125    :param item_cache: The specification item cache containing the glossary
126                       groups and terms.
127    """
128    groups = {}  # type: ItemMap
129    for item in item_cache.top_level.values():
130        _gather_glossary_groups(item, groups)
131
132    project_glossary = _Glossary()
133    for group in config["project-groups"]:
134        _gather_glossary_terms(groups[group], project_glossary)
135
136    _generate_project_glossary(config["project-target"], project_glossary)
137
138    for document_config in config["documents"]:
139        _generate_document_glossary(document_config, project_glossary)
Note: See TracBrowser for help on using the repository browser.