[rtems-central commit] sphinxcontent: Improve SphinxInterfaceMapper

Sebastian Huber sebh at rtems.org
Tue Oct 4 08:18:01 UTC 2022


Module:    rtems-central
Branch:    master
Commit:    fe6dc94f3c9e6ea06ad259a4f69e388a64a486e2
Changeset: http://git.rtems.org/rtems-central/commit/?id=fe6dc94f3c9e6ea06ad259a4f69e388a64a486e2

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Tue Oct  4 09:22:23 2022 +0200

sphinxcontent: Improve SphinxInterfaceMapper

---

 rtems_spec_to_x.py                     |  7 -----
 rtemsspec/applconfig.py                |  5 ++--
 rtemsspec/glossary.py                  | 29 +++++++++++--------
 rtemsspec/interfacedoc.py              | 53 +++++++---------------------------
 rtemsspec/sphinxcontent.py             | 32 +++++++++++++++++++-
 rtemsspec/tests/spec-sphinx/f.yml      | 12 ++++++++
 rtemsspec/tests/test_applconfig.py     |  2 +-
 rtemsspec/tests/test_content_sphinx.py |  1 +
 rtemsspec/tests/test_glossary.py       |  4 +--
 spec2modules.py                        |  8 +++--
 10 files changed, 83 insertions(+), 70 deletions(-)

diff --git a/rtems_spec_to_x.py b/rtems_spec_to_x.py
index 10ccc787..2e76b60b 100755
--- a/rtems_spec_to_x.py
+++ b/rtems_spec_to_x.py
@@ -32,10 +32,7 @@ import string
 import rtemsspec.applconfig
 import rtemsspec.build
 from rtemsspec.items import ItemCache
-import rtemsspec.glossary
-import rtemsspec.interface
 import rtemsspec.util
-import rtemsspec.validation
 
 
 def _run_pre_qualified_only_build(config: dict, item_cache: ItemCache) -> None:
@@ -76,10 +73,6 @@ def main() -> None:
     logging.basicConfig(level="DEBUG")
     config = rtemsspec.util.load_config("config.yml")
     item_cache = ItemCache(config["spec"])
-    rtemsspec.glossary.generate(config["glossary"], item_cache)
-    rtemsspec.applconfig.generate(config["appl-config"], item_cache)
-    rtemsspec.interface.generate(config["interface"], item_cache)
-    rtemsspec.validation.generate(config["validation"], item_cache)
     _run_pre_qualified_only_build(config["build"], item_cache)
     _run_pre_qualified_doxygen(config["build"])
 
diff --git a/rtemsspec/applconfig.py b/rtemsspec/applconfig.py
index e79873c8..cbaf7d13 100644
--- a/rtemsspec/applconfig.py
+++ b/rtemsspec/applconfig.py
@@ -313,7 +313,8 @@ def _add_doxygen_get_values(mapper: ItemMapper) -> None:
                          _get_value_doxygen_unspecfied_type)
 
 
-def generate(config: dict, item_cache: ItemCache) -> None:
+def generate(config: dict, group_uids: List[str],
+             item_cache: ItemCache) -> None:
     """
     Generates application configuration documentation sources according to the
     configuration.
@@ -322,7 +323,7 @@ def generate(config: dict, item_cache: ItemCache) -> None:
     :param item_cache: The specification item cache containing the application
                        configuration groups and options.
     """
-    sphinx_mapper = SphinxInterfaceMapper(EmptyItem())
+    sphinx_mapper = SphinxInterfaceMapper(EmptyItem(), group_uids)
     doxygen_mapper = ItemMapper(EmptyItem())
     _add_doxygen_get_values(doxygen_mapper)
     doxygen_content = _DoxygenContentAdaptor(doxygen_mapper)
diff --git a/rtemsspec/glossary.py b/rtemsspec/glossary.py
index f42781b1..b3a3e7b7 100644
--- a/rtemsspec/glossary.py
+++ b/rtemsspec/glossary.py
@@ -26,7 +26,7 @@
 
 import glob
 import re
-from typing import Any, Dict, NamedTuple
+from typing import Any, Dict, List, NamedTuple
 
 from rtemsspec.sphinxcontent import SphinxContent, SphinxInterfaceMapper
 from rtemsspec.items import Item, ItemCache, ItemGetValueContext, ItemMapper
@@ -50,8 +50,8 @@ def _gather_glossary_terms(item: Item, glossary: _Glossary) -> None:
         glossary.term_to_item[term] = item
 
 
-def _generate_glossary_content(terms: ItemMap, header: str,
-                               target: str) -> None:
+def _generate_glossary_content(terms: ItemMap, header: str, target: str,
+                               group_uids: List[str]) -> None:
     content = SphinxContent()
     content.add_header(header, level=1)
     content.add(".. glossary::")
@@ -59,7 +59,8 @@ def _generate_glossary_content(terms: ItemMap, header: str,
         content.add(":sorted:")
         for item in sorted(terms.values(), key=lambda x: x["term"].lower()):
             content.register_license_and_copyrights_of_item(item)
-            text = SphinxInterfaceMapper(item).substitute(item["text"])
+            text = SphinxInterfaceMapper(item,
+                                         group_uids).substitute(item["text"])
             content.add_definition_item(item["term"], text)
     content.add_licence_and_copyrights()
     content.write(target)
@@ -104,22 +105,25 @@ def _resolve_glossary_terms(document_terms: ItemMap) -> None:
         _GlossaryMapper(term, document_terms).substitute(term["text"])
 
 
-def _generate_project_glossary(glossary: _Glossary, header: str,
-                               target: str) -> None:
+def _generate_project_glossary(glossary: _Glossary, header: str, target: str,
+                               group_uids: List[str]) -> None:
     if target:
-        _generate_glossary_content(glossary.uid_to_item, header, target)
+        _generate_glossary_content(glossary.uid_to_item, header, target,
+                                   group_uids)
 
 
-def _generate_document_glossary(config: dict, glossary: _Glossary) -> None:
+def _generate_document_glossary(config: dict, group_uids: List[str],
+                                glossary: _Glossary) -> None:
     document_terms = {}  # type: ItemMap
     for path in config["rest-source-paths"]:
         _find_glossary_terms(path, document_terms, glossary)
     _resolve_glossary_terms(document_terms)
     _generate_glossary_content(document_terms, config["header"],
-                               config["target"])
+                               config["target"], group_uids)
 
 
-def generate(config: dict, item_cache: ItemCache) -> None:
+def generate(config: dict, group_uids: List[str],
+             item_cache: ItemCache) -> None:
     """
     Generates glossaries of terms according to the configuration.
 
@@ -137,7 +141,8 @@ def generate(config: dict, item_cache: ItemCache) -> None:
         _gather_glossary_terms(groups[group], project_glossary)
 
     _generate_project_glossary(project_glossary, config["project-header"],
-                               config["project-target"])
+                               config["project-target"], group_uids)
 
     for document_config in config["documents"]:
-        _generate_document_glossary(document_config, project_glossary)
+        _generate_document_glossary(document_config, group_uids,
+                                    project_glossary)
diff --git a/rtemsspec/interfacedoc.py b/rtemsspec/interfacedoc.py
index d0666c25..fe0a7f67 100644
--- a/rtemsspec/interfacedoc.py
+++ b/rtemsspec/interfacedoc.py
@@ -31,26 +31,20 @@ import os
 from typing import Any, Dict, List, Tuple
 
 from rtemsspec.content import CContent, get_value_compound, \
-     get_value_forward_declaration
-from rtemsspec.sphinxcontent import get_label, get_reference, SphinxContent, \
-     SphinxInterfaceMapper
+    get_value_forward_declaration
+from rtemsspec.sphinxcontent import get_label, get_reference, sanitize_name, \
+    SphinxContent, SphinxInterfaceMapper
 from rtemsspec.items import Item, ItemCache, ItemGetValueContext, ItemMapper
 
 ItemMap = Dict[str, Item]
 
-INTERFACE = "Interface"
-
-
-def _sanitize_name(name: str) -> str:
-    return name.lstrip("_")
-
 
 def _get_reference(name: str) -> str:
-    return get_reference(get_label(f"{INTERFACE} {name}"))
+    return get_reference(get_label(f"Interface {name}"))
 
 
 def _get_code_param(ctx: ItemGetValueContext) -> Any:
-    return _sanitize_name(ctx.value[ctx.key])
+    return sanitize_name(ctx.value[ctx.key])
 
 
 class _CodeMapper(ItemMapper):
@@ -63,33 +57,6 @@ class _CodeMapper(ItemMapper):
         self.add_get_value("interface/macro:/params/name", _get_code_param)
 
 
-def _get_param(ctx: ItemGetValueContext) -> Any:
-    return f"``{_sanitize_name(ctx.value[ctx.key])}``"
-
-
-class _Mapper(SphinxInterfaceMapper):
-    def __init__(self, item: Item, group_uids: List[str]):
-        super().__init__(item)
-        self._group_uids = set(group_uids)
-        self.add_get_value("interface/function:/name", self._get_function)
-        self.add_get_value("interface/function:/params/name", _get_param)
-        self.add_get_value("interface/group:/name", self._get_group)
-        self.add_get_value("interface/macro:/name", self._get_function)
-        self.add_get_value("interface/macro:/params/name", _get_param)
-
-    def _get_function(self, ctx: ItemGetValueContext) -> Any:
-        name = ctx.value[ctx.key]
-        for group in ctx.item.parents("interface-ingroup"):
-            if group.uid in self._group_uids:
-                return _get_reference(name)
-        return f":c:func:`{name}`"
-
-    def _get_group(self, ctx: ItemGetValueContext) -> Any:
-        if ctx.item.uid in self._group_uids:
-            return get_reference(ctx.value["identifier"])
-        return ctx.value[ctx.key]
-
-
 def _generate_introduction(target: str, group: Item, group_uids: List[str],
                            items: List[Item]) -> None:
     content = SphinxContent()
@@ -106,7 +73,7 @@ def _generate_introduction(target: str, group: Item, group_uids: List[str],
 
         content.append("")
         content.gap = False
-        mapper = _Mapper(group, group_uids)
+        mapper = SphinxInterfaceMapper(group, group_uids)
         content.wrap(mapper.substitute(group["brief"]))
         content.wrap(mapper.substitute(group["description"]))
         content.paste(f"The directives provided by the {group_name} are:")
@@ -114,7 +81,7 @@ def _generate_introduction(target: str, group: Item, group_uids: List[str],
         for item in items:
             content.register_license_and_copyrights_of_item(item)
             name = item["name"]
-            mapper = _Mapper(item, group_uids)
+            mapper = SphinxInterfaceMapper(item, group_uids)
             brief = mapper.substitute(item["brief"])
             if brief:
                 brief = f" - {brief}"
@@ -154,7 +121,7 @@ def _add_definition(content: CContent, mapper: ItemMapper, item: Item,
         add_definition(content, mapper, item, definition)
 
 
-def _generate_directive(content: SphinxContent, mapper: _Mapper,
+def _generate_directive(content: SphinxContent, mapper: SphinxInterfaceMapper,
                         code_mapper: _CodeMapper, item: Item,
                         enabled: List[str]) -> None:
     content.wrap(mapper.substitute(item["brief"]))
@@ -170,7 +137,7 @@ def _generate_directive(content: SphinxContent, mapper: _Mapper,
             description = param["description"]
             if description:
                 content.add_definition_item(
-                    f"``{_sanitize_name(param['name'])}``",
+                    f"``{sanitize_name(param['name'])}``",
                     mapper.substitute(f"This parameter {description}"),
                     wrap=True)
     if item["description"]:
@@ -219,7 +186,7 @@ def _generate_directives(target: str, group: Item, group_uids: List[str],
             content.register_license_and_copyrights_of_item(item)
             name = item["name"]
             code_mapper = _CodeMapper(item)
-            mapper = _Mapper(item, group_uids)
+            mapper = SphinxInterfaceMapper(item, group_uids)
             content.add(f".. Generated from spec:{item.uid}")
             with content.directive("raw", "latex"):
                 content.add("\\clearpage")
diff --git a/rtemsspec/sphinxcontent.py b/rtemsspec/sphinxcontent.py
index f919511d..d9a73564 100644
--- a/rtemsspec/sphinxcontent.py
+++ b/rtemsspec/sphinxcontent.py
@@ -306,10 +306,23 @@ class SphinxMapper(ItemMapper):
                            _get_value_sphinx_unspecified_type)
 
 
+def sanitize_name(name: str) -> str:
+    """ Removes leading underscores from the name. """
+    return name.lstrip("_")
+
+
+def _get_param(ctx: ItemGetValueContext) -> Any:
+    return f"``{sanitize_name(ctx.value[ctx.key])}``"
+
+
 class SphinxInterfaceMapper(SphinxMapper):
     """ Sphinx item mapper for the interface documentation. """
-    def __init__(self, item: Item, recursive: bool = False):
+    def __init__(self,
+                 item: Item,
+                 group_uids: List[str],
+                 recursive: bool = False):
         super().__init__(item, recursive)
+        self._group_uids = set(group_uids)
         self.add_get_value("interface/appl-config-option/feature-enable:/name",
                            _get_appl_config_option)
         self.add_get_value("interface/appl-config-option/feature:/name",
@@ -318,3 +331,20 @@ class SphinxInterfaceMapper(SphinxMapper):
                            _get_appl_config_option)
         self.add_get_value("interface/appl-config-option/integer:/name",
                            _get_appl_config_option)
+        self.add_get_value("interface/function:/name", self._get_function)
+        self.add_get_value("interface/function:/params/name", _get_param)
+        self.add_get_value("interface/group:/name", self._get_group)
+        self.add_get_value("interface/macro:/name", self._get_function)
+        self.add_get_value("interface/macro:/params/name", _get_param)
+
+    def _get_function(self, ctx: ItemGetValueContext) -> Any:
+        name = ctx.value[ctx.key]
+        for group in ctx.item.parents("interface-ingroup"):
+            if group.uid in self._group_uids:
+                return get_reference(get_label(f"Interface {name}"))
+        return f":c:func:`{name}`"
+
+    def _get_group(self, ctx: ItemGetValueContext) -> Any:
+        if ctx.item.uid in self._group_uids:
+            return get_reference(ctx.value["identifier"])
+        return ctx.value[ctx.key]
diff --git a/rtemsspec/tests/spec-sphinx/f.yml b/rtemsspec/tests/spec-sphinx/f.yml
new file mode 100644
index 00000000..d4dc74be
--- /dev/null
+++ b/rtemsspec/tests/spec-sphinx/f.yml
@@ -0,0 +1,12 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+default: default f
+description: description f
+index-entries: []
+name: f
+notes: null
+copyrights:
+- Copyright (C) 2022 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+interface-type: function
+links: []
+type: interface
diff --git a/rtemsspec/tests/test_applconfig.py b/rtemsspec/tests/test_applconfig.py
index 2d02c368..fb68ccb1 100644
--- a/rtemsspec/tests/test_applconfig.py
+++ b/rtemsspec/tests/test_applconfig.py
@@ -43,7 +43,7 @@ def test_applconfig(tmpdir):
     applconfig_config["groups"] = [{"uid": "/g", "target": g_rst}]
     doxygen_h = os.path.join(tmpdir, "doxygen.h")
     applconfig_config["doxygen-target"] = doxygen_h
-    generate(applconfig_config, item_cache)
+    generate(applconfig_config, [], item_cache)
 
     with open(g_rst, "r") as src:
         content = """.. SPDX-License-Identifier: CC-BY-SA-4.0
diff --git a/rtemsspec/tests/test_content_sphinx.py b/rtemsspec/tests/test_content_sphinx.py
index 20fa258a..35e7282a 100644
--- a/rtemsspec/tests/test_content_sphinx.py
+++ b/rtemsspec/tests/test_content_sphinx.py
@@ -301,3 +301,4 @@ def test_substitute(tmpdir):
     mapper.add_get_value("other:/name", lambda ctx: ctx.value[ctx.key])
     assert mapper.substitute("${y:/name}") == "foobar"
     assert mapper.substitute("${a:/name}") == ":c:data:`a`"
+    assert mapper.substitute("${f:/name}") == ":c:func:`f`"
diff --git a/rtemsspec/tests/test_glossary.py b/rtemsspec/tests/test_glossary.py
index 62383f32..55b78aa4 100644
--- a/rtemsspec/tests/test_glossary.py
+++ b/rtemsspec/tests/test_glossary.py
@@ -37,7 +37,7 @@ def test_empty_glossary():
     glossary_config["project-header"] = None
     glossary_config["project-target"] = None
     glossary_config["documents"] = []
-    generate(glossary_config, EmptyItemCache())
+    generate(glossary_config, [], EmptyItemCache())
 
 
 def test_glossary(tmpdir):
@@ -56,7 +56,7 @@ def test_glossary(tmpdir):
     document_glossary = os.path.join(tmpdir, "document", "glossary.rst")
     doc["target"] = document_glossary
     glossary_config["documents"] = [doc]
-    generate(glossary_config, item_cache)
+    generate(glossary_config, [], item_cache)
 
     with open(project_glossary, "r") as src:
         content = """.. SPDX-License-Identifier: CC-BY-SA-4.0
diff --git a/spec2modules.py b/spec2modules.py
index 921a72ff..4153fc53 100755
--- a/spec2modules.py
+++ b/spec2modules.py
@@ -72,10 +72,14 @@ def main() -> None:
                                   args.targets)
 
     if not args.targets:
+        group_uids = [
+            doc["group"] for doc in config["interface-documentation"]["groups"]
+        ]
         rtemsspec.interface.generate(config["interface"], item_cache)
-        rtemsspec.applconfig.generate(config["appl-config"], item_cache)
+        rtemsspec.applconfig.generate(config["appl-config"], group_uids,
+                                      item_cache)
         rtemsspec.specdoc.document(config["spec-documentation"], item_cache)
-        rtemsspec.glossary.generate(config["glossary"], item_cache)
+        rtemsspec.glossary.generate(config["glossary"], group_uids, item_cache)
         rtemsspec.interfacedoc.generate(config["interface-documentation"],
                                         item_cache)
 



More information about the vc mailing list