From 2ddd68a9db4dc56f1d35a4a30691bc1dc987266c Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Tue, 21 Nov 2023 11:13:16 +0100 Subject: sphinxbuilder: New --- rtemsspec/packagebuildfactory.py | 3 + rtemsspec/sphinxbuilder.py | 466 +++++++++++++++++++++ .../tests/spec-packagebuild/glossary/term.yml | 12 + .../tests/spec-packagebuild/qdp/build/doc-2.yml | 13 + .../tests/spec-packagebuild/qdp/build/doc.yml | 13 + .../spec-packagebuild/qdp/deployment/doc-2.yml | 13 + .../tests/spec-packagebuild/qdp/deployment/doc.yml | 13 + .../tests/spec-packagebuild/qdp/package-build.yml | 4 + .../spec-packagebuild/qdp/source/doc-section.yml | 13 + .../qdp/source/doc-subsection.yml | 15 + .../tests/spec-packagebuild/qdp/source/doc.yml | 19 + .../tests/spec-packagebuild/qdp/steps/doc-2.yml | 36 ++ .../tests/spec-packagebuild/qdp/steps/doc.yml | 102 +++++ rtemsspec/tests/spec-packagebuild/rtems/if.yml | 3 +- .../pkg/build/src/doc/copy-and-substitute.rst | 21 + .../tests/test-files/pkg/build/src/doc/copy.rst | 5 + .../tests/test-files/pkg/build/src/doc/index.rst | 19 + .../tests/test-files/pkg/build/src/doc/some.txt | 1 + rtemsspec/tests/test_packagebuild.py | 215 ++++++++++ spec-qdp/spec/qdp-document-license-map.yml | 25 ++ spec-qdp/spec/qdp-sphinx-build.yml | 98 +++++ .../qdp-sphinx-component-copy-and-substitute.yml | 34 ++ spec-qdp/spec/qdp-sphinx-component-copy-files.yml | 38 ++ spec-qdp/spec/qdp-sphinx-component-copy.yml | 33 ++ spec-qdp/spec/qdp-sphinx-component-generic.yml | 52 +++ spec-qdp/spec/qdp-sphinx-component-glossary.yml | 32 ++ spec-qdp/spec/qdp-sphinx-component-list.yml | 16 + spec-qdp/spec/qdp-sphinx-component.yml | 34 ++ .../spec/qdp-sphinx-contributor-action-list.yml | 16 + spec-qdp/spec/qdp-sphinx-contributor-action.yml | 26 ++ spec-qdp/spec/qdp-sphinx-contributor-list.yml | 16 + spec-qdp/spec/qdp-sphinx-contributor.yml | 26 ++ spec-qdp/spec/qdp-sphinx-release-list.yml | 16 + spec-qdp/spec/qdp-sphinx-release.yml | 31 ++ spec-qdp/spec/qdp-sphinx-section.yml | 34 ++ spec-qdp/spec/qdp-sphinx-types.yml | 23 + 36 files changed, 1535 insertions(+), 1 deletion(-) create mode 100644 rtemsspec/sphinxbuilder.py create mode 100644 rtemsspec/tests/spec-packagebuild/glossary/term.yml create mode 100644 rtemsspec/tests/spec-packagebuild/qdp/build/doc-2.yml create mode 100644 rtemsspec/tests/spec-packagebuild/qdp/build/doc.yml create mode 100644 rtemsspec/tests/spec-packagebuild/qdp/deployment/doc-2.yml create mode 100644 rtemsspec/tests/spec-packagebuild/qdp/deployment/doc.yml create mode 100644 rtemsspec/tests/spec-packagebuild/qdp/source/doc-section.yml create mode 100644 rtemsspec/tests/spec-packagebuild/qdp/source/doc-subsection.yml create mode 100644 rtemsspec/tests/spec-packagebuild/qdp/source/doc.yml create mode 100644 rtemsspec/tests/spec-packagebuild/qdp/steps/doc-2.yml create mode 100644 rtemsspec/tests/spec-packagebuild/qdp/steps/doc.yml create mode 100644 rtemsspec/tests/test-files/pkg/build/src/doc/copy-and-substitute.rst create mode 100644 rtemsspec/tests/test-files/pkg/build/src/doc/copy.rst create mode 100644 rtemsspec/tests/test-files/pkg/build/src/doc/index.rst create mode 100644 rtemsspec/tests/test-files/pkg/build/src/doc/some.txt create mode 100644 spec-qdp/spec/qdp-document-license-map.yml create mode 100644 spec-qdp/spec/qdp-sphinx-build.yml create mode 100644 spec-qdp/spec/qdp-sphinx-component-copy-and-substitute.yml create mode 100644 spec-qdp/spec/qdp-sphinx-component-copy-files.yml create mode 100644 spec-qdp/spec/qdp-sphinx-component-copy.yml create mode 100644 spec-qdp/spec/qdp-sphinx-component-generic.yml create mode 100644 spec-qdp/spec/qdp-sphinx-component-glossary.yml create mode 100644 spec-qdp/spec/qdp-sphinx-component-list.yml create mode 100644 spec-qdp/spec/qdp-sphinx-component.yml create mode 100644 spec-qdp/spec/qdp-sphinx-contributor-action-list.yml create mode 100644 spec-qdp/spec/qdp-sphinx-contributor-action.yml create mode 100644 spec-qdp/spec/qdp-sphinx-contributor-list.yml create mode 100644 spec-qdp/spec/qdp-sphinx-contributor.yml create mode 100644 spec-qdp/spec/qdp-sphinx-release-list.yml create mode 100644 spec-qdp/spec/qdp-sphinx-release.yml create mode 100644 spec-qdp/spec/qdp-sphinx-section.yml create mode 100644 spec-qdp/spec/qdp-sphinx-types.yml diff --git a/rtemsspec/packagebuildfactory.py b/rtemsspec/packagebuildfactory.py index 0d959f91..4e7567e0 100644 --- a/rtemsspec/packagebuildfactory.py +++ b/rtemsspec/packagebuildfactory.py @@ -33,6 +33,7 @@ from rtemsspec.reposubset import RepositorySubset from rtemsspec.rtems import RTEMSItemCache from rtemsspec.runactions import RunActions from rtemsspec.runtests import RunTests, TestLog +from rtemsspec.sphinxbuilder import SphinxBuilder, SphinxSection from rtemsspec.testrunner import DummyTestRunner, GRMONManualTestRunner, \ SubprocessTestRunner @@ -49,11 +50,13 @@ def create_build_item_factory() -> BuildItemFactory: factory.add_constructor("qdp/build-step/rtems-item-cache", RTEMSItemCache) factory.add_constructor("qdp/build-step/run-actions", RunActions) factory.add_constructor("qdp/build-step/run-tests", RunTests) + factory.add_constructor("qdp/build-step/sphinx/generic", SphinxBuilder) factory.add_constructor("qdp/directory-state/generic", DirectoryState) factory.add_constructor("qdp/directory-state/repository", DirectoryState) factory.add_constructor("qdp/directory-state/test-log", TestLog) factory.add_constructor("qdp/directory-state/unpacked-archive", DirectoryState) + factory.add_constructor("qdp/sphinx-section", SphinxSection) factory.add_constructor("qdp/test-runner/dummy", DummyTestRunner) factory.add_constructor("qdp/test-runner/grmon-manual", GRMONManualTestRunner) diff --git a/rtemsspec/sphinxbuilder.py b/rtemsspec/sphinxbuilder.py new file mode 100644 index 00000000..298bce26 --- /dev/null +++ b/rtemsspec/sphinxbuilder.py @@ -0,0 +1,466 @@ +# SPDX-License-Identifier: BSD-2-Clause +""" Contains the SphinxBuilder class. """ + +# Copyright (C) 2020, 2023 embedded brains GmbH & Co. KG +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +from contextlib import contextmanager +import logging +import os +import re +import shutil +from typing import Any, Callable, Dict, Iterator, List, Optional, Tuple +import yaml + +from rtemsspec.content import BSD_2_CLAUSE_LICENSE, Copyrights +from rtemsspec.directorystate import DirectoryState +from rtemsspec.packagebuild import BuildItem, BuildItemFactory, \ + PackageBuildDirector +from rtemsspec.items import is_enabled, Item, ItemGetValueContext, Link +from rtemsspec import glossary +from rtemsspec.sphinxcontent import SphinxContent +from rtemsspec.util import run_command + +_BREAK = "\\break" + +_PUSH_ENABLED_BY = re.compile(r"^\${\.:/push-enabled-by:(.+)}$") + +_POP_ENABLED_BY = re.compile(r"^\${\.:/pop-enabled-by") + +_RST_HEADERS = re.compile( + r"^\.\. SPDX-License-Identifier: (.+)\n\n((\.\. Copyright \(C\).*\n)+)\n", + flags=re.MULTILINE) + + +def _get_normal_title(ctx: ItemGetValueContext) -> Any: + return ctx.item["document-title"].replace(_BREAK, " ") + + +def _get_sphinx_title(ctx: ItemGetValueContext) -> Any: + content = SphinxContent() + content.add_header(_get_normal_title(ctx), level=1) + return "\n".join(content.lines) + + +def _get_release(ctx: ItemGetValueContext) -> Any: + return str(len(ctx.item["document-releases"])) + + +def _no_action(_component: Dict[str, Any]) -> None: + pass + + +def _sep(seps: Tuple[str, ...], maxi: Tuple[int, ...]) -> str: + return "+" + "+".join(f"{sep * (val + 2)}" + for sep, val in zip(seps, maxi)) + "+" + + +def _row(row: Tuple[str, ...], maxi: Tuple[int, ...]) -> str: + return "|" + "|".join(f" {cell:{width}} " + for cell, width in zip(row, maxi)) + "|" + + +def _get_contributors(ctx: ItemGetValueContext) -> Any: + rows = [("Action", "Name", "Organization", "Signature")] + maxi = tuple(map(len, rows[0])) + for action in ctx.item["document-contributors"]: + for contributor in action["contributors"]: + row = (action["action"], contributor["name"], + contributor["organization"], "") + rows.append(row) + row_lengths = tuple(map(len, row)) + maxi = tuple(map(max, zip(maxi, row_lengths))) + sep_0 = _sep(("-", "-", "-", "-"), maxi) + sep_1 = _sep(("=", "=", "=", "="), maxi) + sep_2 = _sep((" ", "-", "-", "-"), maxi) + lines = [sep_0, _row(rows[0], maxi)] + last_action = rows[0][0] + for row in rows[1:]: + if last_action == "Action": + lines.append(sep_1) + last_action = row[0] + elif last_action == row[0]: + lines.append(sep_2) + row = ("", row[1], row[2], row[3]) + else: + lines.append(sep_0) + last_action = row[0] + lines.append(_row(row, maxi)) + lines.append(sep_0) + content = SphinxContent() + with content.directive( + "table", options=[":class: longtable", ":widths: 16 26 30 28"]): + content.add(lines) + return "\n".join(content.lines) + + +def _latex_escape(value: str) -> str: + return value.replace("_", "\\_").replace("&", "\\&") + + +_COPYRIGHT = re.compile(r"^\s*Copyright\s+\(C\)\s+", re.IGNORECASE) +_YEARS = re.compile(r"^[0-9, ]*") + + +def _get_document_copyright(ctx: ItemGetValueContext) -> Any: + copyrights = ctx.item["document-copyrights"] + main = _COPYRIGHT.sub("", copyrights[0]) + if len(copyrights) == 1: + return main + return f"{main} and contributors" + + +def _get_document_author(ctx: ItemGetValueContext) -> Any: + return _YEARS.sub("", _get_document_copyright(ctx)) + + +def _get_document_year(ctx: ItemGetValueContext) -> Any: + match = _YEARS.search(_get_document_copyright(ctx)) + assert match + return match.group(0).split(",")[-1] + + +class SphinxBuilder(BuildItem): + """ Base class for Sphinx document builds. """ + + # pylint: disable=too-many-instance-attributes + @classmethod + def prepare_factory(cls, factory: BuildItemFactory, + type_name: str) -> None: + BuildItem.prepare_factory(factory, type_name) + factory.add_get_value(f"{type_name}:/document-release", _get_release) + factory.add_get_value(f"{type_name}:/document-year", + _get_document_year) + + def __init__(self, director: PackageBuildDirector, item: Item): + super().__init__(director, item) + source = self.input("source") + assert isinstance(source, DirectoryState) + + build = self.output("build") + assert isinstance(build, DirectoryState) + + self._index: List[str] = [] + self._section_level = 2 + self.source_dir = source.directory + self.build_dir = build.directory + self.file_path = self.build_dir + my_type = self.item.type + self.mapper.add_get_value(f"{my_type}:/document-author", + _get_document_author) + self.mapper.add_get_value(f"{my_type}:/document-contract-html", + self._get_contract_html) + self.mapper.add_get_value(f"{my_type}:/document-contract-latex", + self._get_contract_latex) + self.mapper.add_get_value(f"{my_type}:/document-copyright", + _get_document_copyright) + self.mapper.add_get_value(f"{my_type}:/document-copyrights", + self._get_document_copyrights) + self.mapper.add_get_value( + f"{my_type}:/document-bsd-2-clause-copyrights", + self._get_document_bsd_2_clause_copyrights) + self.mapper.add_get_value(f"{my_type}:/document-normal-title", + _get_normal_title) + self.mapper.add_get_value(f"{my_type}:/document-latex-copyright", + self._get_latex_copyright) + self.mapper.add_get_value(f"{my_type}:/document-latex-title", + self._get_latex_title) + self.mapper.add_get_value(f"{my_type}:/document-title-page-title", + self._get_title_page_title) + self.mapper.add_get_value(f"{my_type}:/document-sphinx-title", + _get_sphinx_title) + self.mapper.add_get_value(f"{my_type}:/document-index", + self._get_index) + self.mapper.add_get_value(f"{my_type}:/document-releases", + self._get_releases) + self.mapper.add_get_value(f"{my_type}:/document-contributors", + _get_contributors) + for name in [my_type, "qdp/sphinx-section"]: + self.mapper.add_get_value(f"{name}:/sections", self._get_sections) + self._actions = { + "add-to-index": _no_action, + "copy": self._copy, + "copy-and-substitute": self._copy_and_substitute, + "copy-files": self._copy_files, + "glossary": self._glossary + } + + def run(self) -> None: + self.mapper.copyrights_by_license.clear() + + destination = self.output("destination") + assert isinstance(destination, DirectoryState) + destination.clear() + + os.makedirs(os.path.join(self.build_dir, "source"), exist_ok=True) + status = run_command( + ["python3", "-msphinx", "-M", "clean", "source", "build"], + self.build_dir) + assert status == 0 + enabled_set = self.enabled_set + for component in self["document-components"]: + if is_enabled(enabled_set, component.get("enabled-by", True)): + self.file_path = os.path.join( + self.build_dir, component.get("destination", ".")) + self._actions[component["action"]](component) + self._add_to_index(component) + output = self["output-pdf"] + if output: + status = run_command( + ["python3", "-msphinx", "-M", "latexpdf", "source", "build"], + self.build_dir) + assert status == 0 + src_path = os.path.join(self.build_dir, "build", "latex", + "document.pdf") + destination.copy_file(src_path, output) + output = self["output-html"] + if output: + status = run_command( + ["python3", "-msphinx", "-M", "html", "source", "build"], + self.build_dir) + assert status == 0 + src_path = os.path.join(self.build_dir, "build", "html") + destination.copy_tree(src_path, output) + + my_license = self["document-license"] + destination["copyrights-by-license"] = dict( + (key, value.get_statements()) + for key, value in self._get_copyrights().items() + if key != my_license) + + def add_component_action(self, name: str, + action: Callable[[Dict[str, Any]], None]) -> None: + """ Adds a component action. """ + self._actions[name] = action + + def _get_releases(self, ctx: ItemGetValueContext) -> Any: + content = SphinxContent() + releases = ctx.item["document-releases"] + count = len(releases) + for idx, release in enumerate(reversed(releases)): + date = release["date"] + status = release["status"] + line = f"Release: {count - idx}, Date: {date}, Status: {status}" + with content.directive("topic", line): + lines = self._push_pop_enabled_by( + release["changes"].splitlines()) + content.add(self.mapper.substitute("\n".join(lines), ctx.item)) + return "\n".join(content.lines) + + def _add_to_index(self, component: Dict[str, Any]) -> None: + if component.get("add-to-index", False): + self._index.append( + os.path.basename(component["destination"]).replace(".rst", "")) + + def _get_index(self, ctx: ItemGetValueContext) -> Any: + content = SphinxContent() + maxdepth = f":maxdepth: {ctx.item['document-toctree-maxdepth']}" + with content.directive("toctree", options=[maxdepth, ":numbered:"]): + content.add(self._index) + return "\n".join(content.lines) + + def _get_contract_html(self, ctx: ItemGetValueContext) -> Any: + contract = self.mapper.substitute(ctx.item["document-contract"]) + dot = ". " if contract else "" + return f"{dot}{contract.replace(_BREAK, ' ')}" + + def _get_contract_latex(self, ctx: ItemGetValueContext) -> Any: + return _latex_escape( + self.mapper.substitute(ctx.item["document-contract"]).replace( + _BREAK, " \\vspace{-4pt} \\break ")) + + def _get_latex_copyright(self, ctx: ItemGetValueContext) -> Any: + return _latex_escape( + self.mapper.substitute(_get_document_copyright(ctx))) + + def _get_copyrights(self) -> Dict[str, Copyrights]: + my_license = self["document-license"] + copyrights: Dict[str, Copyrights] = {} + copyrights.setdefault(my_license, Copyrights()).register( + self["document-copyrights"]) + license_map = self["document-license-map"] + for key, value in self.mapper.copyrights_by_license.items(): + the_license = license_map.get(key, key) + copyrights.setdefault(the_license, Copyrights()).register(value) + return copyrights + + def _get_document_copyrights(self, ctx: ItemGetValueContext) -> Any: + my_license = self["document-license"] + assert " OR " not in my_license + copyrights = self._get_copyrights() + prefix = ctx.args if ctx.args else "" + return "\n".join(copyrights[my_license].get_statements(f"{prefix}| ©")) + + def _get_document_bsd_2_clause_copyrights( + self, _ctx: ItemGetValueContext) -> Any: + copyrights = self._get_copyrights() + the_license = "BSD-2-Clause" + if the_license not in copyrights: + return "" + statements = "\n".join(copyrights[the_license].get_statements("| ©")) + return f"""{statements} + +{BSD_2_CLAUSE_LICENSE}""" + + def _get_latex_title(self, ctx: ItemGetValueContext) -> Any: + return _latex_escape( + self.mapper.substitute(ctx.item["document-title"].replace( + _BREAK, " "))) + + def _get_title_page_title(self, ctx: ItemGetValueContext) -> Any: + return _latex_escape( + self.mapper.substitute(ctx.item["document-title"].replace( + _BREAK, " \\break \\break "))) + + @contextmanager + def section_level( + self, + ctx: ItemGetValueContext) -> Iterator[Tuple[int, Optional[str]]]: + """ Opens a section level with optional additional arguments. """ + if ctx.args: + colon = ctx.args.find(":") + if colon >= 0: + level_change = int(ctx.args[:colon]) + args: Optional[str] = ctx.args[colon + 1:] + else: + level_change = int(ctx.args) + args = None + else: + level_change = 1 + args = None + section_level = self._section_level + new_section_level = section_level + level_change + self._section_level = new_section_level + yield new_section_level, args + self._section_level = section_level + + def _get_sections(self, ctx: ItemGetValueContext) -> Any: + with self.section_level(ctx) as (section_level, args): + assert args + content = SphinxContent(section_level) + build_item = self.director[ctx.item.uid] + for section in build_item.inputs(args): + with content.section(section.item["header"], + label=section.item["label"]): + content.add(section.item["content"].strip()) + return "\n".join(content.lines) + + def _register_text_copyrights(self, text: str) -> None: + match = _RST_HEADERS.match(text) + assert match + the_license = match.group(1) + statements = [ + statement[3:] for statement in match.group(2).split("\n")[:-1] + ] + logging.info("%s: register license %s with copyrights %s", self.uid, + the_license, statements) + self.mapper.copyrights_by_license.setdefault(the_license, + set()).update(statements) + + def _do_copy(self, src_file: str, dst_file: str) -> None: + os.makedirs(os.path.dirname(dst_file), exist_ok=True) + if dst_file.endswith(".rst"): + logging.info("%s: read: %s", self.uid, src_file) + with open(src_file, "r", encoding="utf-8") as src: + text = src.read() + self._register_text_copyrights(text) + logging.info("%s: write: %s", self.uid, dst_file) + with open(dst_file, "w+", encoding="utf-8") as dst: + dst.write(text) + else: + logging.info("%s: copy '%s' to '%s'", self.uid, src_file, dst_file) + shutil.copy2(src_file, dst_file) + + def _copy(self, component: Dict[str, Any]) -> None: + self._do_copy(os.path.join(self.source_dir, component["source"]), + os.path.join(self.build_dir, component["destination"])) + + def _push_pop_enabled_by(self, lines: List[str]) -> List[str]: + filtered_lines: List[str] = [] + enabled: List[bool] = [True] + for line in lines: + push_match = _PUSH_ENABLED_BY.search(line) + if push_match is not None: + data = push_match.group(1) + enabled_by = yaml.load(data, yaml.SafeLoader) + enabled.append(enabled[-1] + and is_enabled(self.enabled_set, enabled_by)) + continue + if _POP_ENABLED_BY.search(line) is not None: + enabled.pop() + elif enabled[-1]: + filtered_lines.append(line) + return filtered_lines + + def _copy_and_substitute(self, component: Dict[str, Any]) -> None: + src_path = os.path.join(self.source_dir, component["source"]) + dst_path = os.path.join(self.build_dir, component["destination"]) + logging.info("%s: read: %s", self.uid, src_path) + with open(src_path, "r", encoding="utf-8") as src: + logging.info("%s: process push/pop enabled by", self.uid) + text = "".join(self._push_pop_enabled_by(src.readlines())) + if dst_path.endswith(".rst"): + self._register_text_copyrights(text) + logging.info("%s: substitute", self.uid) + text = self.mapper.substitute(text) + logging.info("%s: write: %s", self.uid, dst_path) + os.makedirs(os.path.dirname(dst_path), exist_ok=True) + with open(dst_path, "w+", encoding="utf-8") as dst: + dst.write(text) + + def _copy_files(self, component: Dict[str, Any]) -> None: + src_dir = os.path.join(self.source_dir, component["source"]) + dst_dir = os.path.join(self.build_dir, component["destination"]) + for a_file in component["files"]: + self._do_copy(os.path.join(src_dir, a_file), + os.path.join(dst_dir, a_file)) + + def _glossary(self, component: Dict[str, Any]) -> None: + config = { + "project-groups": + component["glossary-groups"], + "project-header": + None, + "project-target": + None, + "documents": [{ + "header": + "Terms, definitions and abbreviated terms", + "rest-source-paths": [ + str(os.path.join(self.build_dir, "source")), + str(os.path.join(self.build_dir, "include")) + ], + "target": + str(os.path.join(self.build_dir, component["destination"])), + }] + } + glossary.generate(config, self.item.cache, self.mapper) + + +class SphinxSection(BuildItem): + """ This class represents a Sphinx section. """ + + def has_changed(self, link: Link) -> bool: + if self.is_build_necessary(): + return True + return super().has_changed(link) diff --git a/rtemsspec/tests/spec-packagebuild/glossary/term.yml b/rtemsspec/tests/spec-packagebuild/glossary/term.yml new file mode 100644 index 00000000..aa4e1432 --- /dev/null +++ b/rtemsspec/tests/spec-packagebuild/glossary/term.yml @@ -0,0 +1,12 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2023 Alice +- Copyright (C) 2020 embedded brains GmbH & Co. KG +enabled-by: true +glossary-type: term +links: +- role: glossary-member + uid: ../glossary-general +term: Term +text: This is the term. +type: glossary diff --git a/rtemsspec/tests/spec-packagebuild/qdp/build/doc-2.yml b/rtemsspec/tests/spec-packagebuild/qdp/build/doc-2.yml new file mode 100644 index 00000000..87634f3f --- /dev/null +++ b/rtemsspec/tests/spec-packagebuild/qdp/build/doc-2.yml @@ -0,0 +1,13 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2023 embedded brains GmbH & Co. KG +copyrights-by-license: {} +directory: ${../variant:/build-directory}/doc-2 +directory-state-type: generic +enabled-by: true +files: [] +hash: null +links: [] +patterns: [] +qdp-type: directory-state +type: qdp diff --git a/rtemsspec/tests/spec-packagebuild/qdp/build/doc.yml b/rtemsspec/tests/spec-packagebuild/qdp/build/doc.yml new file mode 100644 index 00000000..ec7d11dd --- /dev/null +++ b/rtemsspec/tests/spec-packagebuild/qdp/build/doc.yml @@ -0,0 +1,13 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2023 embedded brains GmbH & Co. KG +copyrights-by-license: {} +directory: ${../variant:/build-directory}/doc +directory-state-type: generic +enabled-by: true +files: [] +hash: null +links: [] +patterns: [] +qdp-type: directory-state +type: qdp diff --git a/rtemsspec/tests/spec-packagebuild/qdp/deployment/doc-2.yml b/rtemsspec/tests/spec-packagebuild/qdp/deployment/doc-2.yml new file mode 100644 index 00000000..a252bf6e --- /dev/null +++ b/rtemsspec/tests/spec-packagebuild/qdp/deployment/doc-2.yml @@ -0,0 +1,13 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2023 embedded brains GmbH & Co. KG +copyrights-by-license: {} +directory: ${../variant:/deployment-directory}/doc-2 +directory-state-type: generic +enabled-by: true +files: [] +hash: null +links: [] +patterns: [] +qdp-type: directory-state +type: qdp diff --git a/rtemsspec/tests/spec-packagebuild/qdp/deployment/doc.yml b/rtemsspec/tests/spec-packagebuild/qdp/deployment/doc.yml new file mode 100644 index 00000000..ca375bca --- /dev/null +++ b/rtemsspec/tests/spec-packagebuild/qdp/deployment/doc.yml @@ -0,0 +1,13 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2023 embedded brains GmbH & Co. KG +copyrights-by-license: {} +directory: ${../variant:/deployment-directory}/doc +directory-state-type: generic +enabled-by: true +files: [] +hash: null +links: [] +patterns: [] +qdp-type: directory-state +type: qdp diff --git a/rtemsspec/tests/spec-packagebuild/qdp/package-build.yml b/rtemsspec/tests/spec-packagebuild/qdp/package-build.yml index 4686460e..4147fd6f 100644 --- a/rtemsspec/tests/spec-packagebuild/qdp/package-build.yml +++ b/rtemsspec/tests/spec-packagebuild/qdp/package-build.yml @@ -21,6 +21,10 @@ links: uid: steps/gcda-producer - role: build-step uid: steps/membench +- role: build-step + uid: steps/doc +- role: build-step + uid: steps/doc-2 - role: build-step uid: steps/archive qdp-type: package-build diff --git a/rtemsspec/tests/spec-packagebuild/qdp/source/doc-section.yml b/rtemsspec/tests/spec-packagebuild/qdp/source/doc-section.yml new file mode 100644 index 00000000..8dc66d45 --- /dev/null +++ b/rtemsspec/tests/spec-packagebuild/qdp/source/doc-section.yml @@ -0,0 +1,13 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +content: | + Section content: + + ${.:/sections:2:subsection} +copyrights: +- Copyright (C) 2023 embedded brains GmbH & Co. KG +enabled-by: true +header: Section Header +label: SectionHeader +links: [] +qdp-type: sphinx-section +type: qdp diff --git a/rtemsspec/tests/spec-packagebuild/qdp/source/doc-subsection.yml b/rtemsspec/tests/spec-packagebuild/qdp/source/doc-subsection.yml new file mode 100644 index 00000000..0636dada --- /dev/null +++ b/rtemsspec/tests/spec-packagebuild/qdp/source/doc-subsection.yml @@ -0,0 +1,15 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +content: | + Subsection content. +copyrights: +- Copyright (C) 2023 embedded brains GmbH & Co. KG +enabled-by: true +header: Subsection Header +label: SubsectionHeader +links: +- hash: null + name: spec + role: input + uid: ../steps/rtems-item-cache +qdp-type: sphinx-section +type: qdp diff --git a/rtemsspec/tests/spec-packagebuild/qdp/source/doc.yml b/rtemsspec/tests/spec-packagebuild/qdp/source/doc.yml new file mode 100644 index 00000000..ca2a620b --- /dev/null +++ b/rtemsspec/tests/spec-packagebuild/qdp/source/doc.yml @@ -0,0 +1,19 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2023 embedded brains GmbH & Co. KG +copyrights-by-license: {} +directory: ${../variant:/build-directory}/src/doc +directory-state-type: generic +enabled-by: true +files: +- file: copy-and-substitute.rst + hash: null +- file: copy.rst + hash: null +- file: index.rst + hash: null +hash: null +links: [] +patterns: [] +qdp-type: directory-state +type: qdp diff --git a/rtemsspec/tests/spec-packagebuild/qdp/steps/doc-2.yml b/rtemsspec/tests/spec-packagebuild/qdp/steps/doc-2.yml new file mode 100644 index 00000000..910cb2fd --- /dev/null +++ b/rtemsspec/tests/spec-packagebuild/qdp/steps/doc-2.yml @@ -0,0 +1,36 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +build-step-type: sphinx +copyrights: +- Copyright (C) 2023 embedded brains GmbH & Co. KG +description: | + Builds a Sphinx document 2. +document-title: The Title +document-toctree-maxdepth: 4 +document-html-help-base-name: Puh +document-components: [] +document-contract: '' +document-copyrights: +- Copyright (C) 2023 embedded brains GmbH & Co. KG +document-key: bla +document-releases: [] +document-contributors: [] +document-license: CC-BY-SA-4.0 +document-license-map: + BSD-2-Clause: CC-BY-SA-4.0 OR BSD-2-Clause +document-type: generic +enabled-by: sphinx-builder-2 +links: +- hash: null + name: source + role: input + uid: ../source/doc +- name: build + role: output + uid: ../build/doc-2 +- name: destination + role: output + uid: ../deployment/doc-2 +output-pdf: null +output-html: null +qdp-type: build-step +type: qdp diff --git a/rtemsspec/tests/spec-packagebuild/qdp/steps/doc.yml b/rtemsspec/tests/spec-packagebuild/qdp/steps/doc.yml new file mode 100644 index 00000000..7a6c1b17 --- /dev/null +++ b/rtemsspec/tests/spec-packagebuild/qdp/steps/doc.yml @@ -0,0 +1,102 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +build-step-type: sphinx +copyrights: +- Copyright (C) 2020 embedded brains GmbH & Co. KG +description: | + Builds a Sphinx document. +document-title: The\breakTitle +document-toctree-maxdepth: 4 +document-html-help-base-name: Base +document-components: +- action: copy-and-substitute + add-to-index: true + source: copy-and-substitute.rst + destination: source/copy-and-substitute.rst +- action: copy + add-to-index: false + source: copy.rst + destination: source/copy.rst +- action: copy + add-to-index: false + enabled-by: false + source: nil.rst + destination: source/nada.rst +- action: copy + add-to-index: false + source: some.txt + destination: source/some.txt +- action: copy-and-substitute + add-to-index: false + source: some.txt + destination: source/some.txt +- action: copy-files + add-to-index: false + source: . + destination: other + files: + - copy.rst +- action: add-to-index + add-to-index: true + destination: source/glossary.rst +- action: copy-and-substitute + add-to-index: false + source: index.rst + destination: source/index.rst +- action: glossary + add-to-index: false + destination: source/glossary.rst + glossary-groups: + - /glossary-general +document-contract: Contract +document-copyrights: +- Copyright (C) 2020 embedded brains GmbH & Co. KG +document-key: blub +document-releases: +- date: '1970-01-01' + status: Replaced + changes: Initial release. +- date: '2020-10-26' + status: Draft + changes: | + * ${.:/document-copyright} + + * e +document-contributors: +- action: Written by + contributors: + - name: John Doe + organization: Some Organization + - name: Foo + organization: Bár Organization +- action: Super Action + contributors: + - name: This is a Long Name + organization: Short +document-license: CC-BY-SA-4.0 +document-license-map: + CC-BY-SA-4.0 OR BSD-2-Clause: CC-BY-SA-4.0 +document-type: generic +enabled-by: sphinx-builder +links: +- hash: null + name: source + role: input + uid: ../source/doc +- hash: null + name: section + role: input + uid: ../source/doc-section +- hash: null + name: subsection + role: input + uid: ../source/doc-subsection +- name: build + role: output + uid: ../build/doc +- name: destination + role: output + uid: ../deployment/doc +output-pdf: doc.pdf +output-html: html +qdp-type: build-step +type: qdp diff --git a/rtemsspec/tests/spec-packagebuild/rtems/if.yml b/rtemsspec/tests/spec-packagebuild/rtems/if.yml index 0e1d67fe..3e0c69d6 100644 --- a/rtemsspec/tests/spec-packagebuild/rtems/if.yml +++ b/rtemsspec/tests/spec-packagebuild/rtems/if.yml @@ -1,7 +1,8 @@ -SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +SPDX-License-Identifier: BSD-2-Clause brief: | Brief. copyrights: +- Copyright (C) 2023 Bob - Copyright (C) 2023 embedded brains GmbH & Co. KG definition: default: diff --git a/rtemsspec/tests/test-files/pkg/build/src/doc/copy-and-substitute.rst b/rtemsspec/tests/test-files/pkg/build/src/doc/copy-and-substitute.rst new file mode 100644 index 00000000..916b6389 --- /dev/null +++ b/rtemsspec/tests/test-files/pkg/build/src/doc/copy-and-substitute.rst @@ -0,0 +1,21 @@ +.. SPDX-License-Identifier: CC-BY-SA-4.0 + +.. Copyright (C) 2023 embedded brains GmbH & Co. KG + +${.:/push-enabled-by:and: [sphinx-builder, {not: {not: sphinx-builder}}]} +${.:/push-enabled-by:not: sphinx-builder} +This is disabled. +${.:/pop-enabled-by} +${.:/document-contract-html} +${.:/document-contract-latex} +${.:/document-normal-title} +${.:/document-title-page-title} +${.:/document-release} +${.:/document-latex-copyright} +${.:/document-latex-title} +${/glossary/term:/term} +${/glossary/term:/plural} +${/rtems/if:/name} +${.:/spec} +${.:/sections:1:section} +${.:/pop-enabled-by} diff --git a/rtemsspec/tests/test-files/pkg/build/src/doc/copy.rst b/rtemsspec/tests/test-files/pkg/build/src/doc/copy.rst new file mode 100644 index 00000000..f76dec5e --- /dev/null +++ b/rtemsspec/tests/test-files/pkg/build/src/doc/copy.rst @@ -0,0 +1,5 @@ +.. SPDX-License-Identifier: CC-BY-SA-4.0 + +.. Copyright (C) 2023 embedded brains GmbH & Co. KG + +Only copy, no ${/variable:/substitute}. diff --git a/rtemsspec/tests/test-files/pkg/build/src/doc/index.rst b/rtemsspec/tests/test-files/pkg/build/src/doc/index.rst new file mode 100644 index 00000000..edd05e6a --- /dev/null +++ b/rtemsspec/tests/test-files/pkg/build/src/doc/index.rst @@ -0,0 +1,19 @@ +.. SPDX-License-Identifier: CC-BY-SA-4.0 + +.. Copyright (C) 2023 embedded brains GmbH & Co. KG + +${.:/document-copyright} + +${.:/document-author} + +${.:/document-copyrights} + +${.:/document-bsd-2-clause-copyrights} + +${.:/document-sphinx-title} + +${.:/document-releases} + +${.:/document-contributors} + +${.:/document-index} diff --git a/rtemsspec/tests/test-files/pkg/build/src/doc/some.txt b/rtemsspec/tests/test-files/pkg/build/src/doc/some.txt new file mode 100644 index 00000000..3e715502 --- /dev/null +++ b/rtemsspec/tests/test-files/pkg/build/src/doc/some.txt @@ -0,0 +1 @@ +Some text. diff --git a/rtemsspec/tests/test_packagebuild.py b/rtemsspec/tests/test_packagebuild.py index 5ddbff41..5ad614d8 100644 --- a/rtemsspec/tests/test_packagebuild.py +++ b/rtemsspec/tests/test_packagebuild.py @@ -42,6 +42,7 @@ from rtemsspec.packagebuild import BuildItem, BuildItemMapper, \ from rtemsspec.packagebuildfactory import create_build_item_factory from rtemsspec.rtems import RTEMSItemCache from rtemsspec.specverify import verify +import rtemsspec.sphinxbuilder import rtemsspec.testrunner from rtemsspec.testrunner import Executable, Report, TestRunner from rtemsspec.tests.util import get_and_clear_log @@ -130,6 +131,31 @@ def _gather_sections(item_cache, path, objdump, gdb): return {} +def _sphinx_builder_run_command(args, cwd=None, stdout=None): + if args == ["python3", "-msphinx", "-M", "clean", "source", "build"]: + return 0 + if args == ["python3", "-msphinx", "-M", "latexpdf", "source", "build"]: + os.makedirs(os.path.join(cwd, "build/latex")) + open(os.path.join(cwd, "build/latex/document.pdf"), "w+").close() + return 0 + if args == ["python3", "-msphinx", "-M", "html", "source", "build"]: + os.makedirs(os.path.join(cwd, "build/html")) + open(os.path.join(cwd, "build/html/index.html"), "w+").close() + return 0 + if args == ["make", "super", "clean"]: + return 0 + if args == ["make"]: + stdout.append("example") + return 0 + if "pkg-config" in args: + stdout.append(" ".join(args)) + return 0 + if args[0].endswith("verify"): + stdout.append("verify") + return 0 + return 1 + + def test_packagebuild(caplog, tmpdir, monkeypatch): tmp_dir = Path(tmpdir) item_cache = _create_item_cache(tmp_dir, Path("spec-packagebuild")) @@ -444,3 +470,192 @@ def test_packagebuild(caplog, tmpdir, monkeypatch): monkeypatch.undo() log = get_and_clear_log(caplog) assert f"/qdp/steps/membench: get memory benchmarks for build-label from: arch/bsp" in log + + # Test SphinxBuilder + variant["enabled"] = ["sphinx-builder"] + doc = director["/qdp/steps/doc"] + doc.substitute("${.:/document-author}") == "embedded brains GmbH & Co. KG" + doc.substitute("${.:/document-year}") == "2020" + doc.substitute( + "${.:/document-copyright}") == "2020 embedded brains GmbH & Co. KG" + doc.item["document-copyrights"].append("Copyright (C) 2023 John Doe") + doc.substitute("${.:/document-author}" + ) == "embedded brains GmbH & Co. KG and contributors" + doc.substitute("${.:/document-copyright}" + ) == "2020 embedded brains GmbH & Co. KG and contributors" + doc.item["document-copyrights"].pop() + doc_src = director["/qdp/source/doc"] + doc_src.load() + doc_build = Path(director["/qdp/build/doc"].directory) + assert not (doc_build / "source" / "copy.rst").exists() + assert not (doc_build / "other" / "copy.rst").exists() + monkeypatch.setattr(rtemsspec.sphinxbuilder, "run_command", + _sphinx_builder_run_command) + director.build_package(None, None) + monkeypatch.undo() + assert (doc_build / "source" / "copy.rst").is_file() + assert (doc_build / "other" / "copy.rst").is_file() + doc_result = doc_build / "source" / "copy-and-substitute.rst" + with open(doc_result, "r", encoding="utf-8") as src: + assert src.read() == """.. SPDX-License-Identifier: CC-BY-SA-4.0 + +.. Copyright (C) 2023 embedded brains GmbH & Co. KG + +. Contract +Contract +The Title +The \\break \\break Title +2 +2020 embedded brains GmbH \\& Co. KG +The Title +:term:`Term` +:term:`Terms ` +:c:func:`identity` +spec:/qdp/steps/doc +.. _SectionHeader: + +Section Header +-------------- + +Section content: + +.. _SubsectionHeader: + +Subsection Header +^^^^^^^^^^^^^^^^^ + +Subsection content. +""" + doc_index = doc_build / "source" / "index.rst" + with open(doc_index, "r", encoding="utf-8") as src: + assert src.read() == """.. SPDX-License-Identifier: CC-BY-SA-4.0 + +.. Copyright (C) 2023 embedded brains GmbH & Co. KG + +2020 embedded brains GmbH & Co. KG + +embedded brains GmbH & Co. KG + +| © 2023 Alice +| © 2020, 2023 embedded brains GmbH & Co. KG + +| © 2023 Bob +| © 2023 embedded brains GmbH & Co. KG + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +The Title +********* + +.. topic:: Release: 2, Date: 2020-10-26, Status: Draft + + * 2020 embedded brains GmbH & Co. KG + + * e + +.. topic:: Release: 1, Date: 1970-01-01, Status: Replaced + + Initial release. + +.. table:: + :class: longtable + :widths: 16 26 30 28 + + +--------------+---------------------+-------------------+-----------+ + | Action | Name | Organization | Signature | + +==============+=====================+===================+===========+ + | Written by | John Doe | Some Organization | | + + +---------------------+-------------------+-----------+ + | | Foo | Bár Organization | | + +--------------+---------------------+-------------------+-----------+ + | Super Action | This is a Long Name | Short | | + +--------------+---------------------+-------------------+-----------+ + +.. toctree:: + :maxdepth: 4 + :numbered: + + copy-and-substitute + glossary +""" + doc_glossary = doc_build / "source" / "glossary.rst" + with open(doc_glossary, "r", encoding="utf-8") as src: + assert src.read() == """.. SPDX-License-Identifier: CC-BY-SA-4.0 + +.. Copyright (C) 2023 Alice +.. Copyright (C) 2020 embedded brains GmbH & Co. KG + +Terms, definitions and abbreviated terms +**************************************** + +.. glossary:: + :sorted: + + Term + This is the term. +""" + doc_deployment = director["/qdp/deployment/doc"] + assert doc_deployment["copyrights-by-license"] == { + "BSD-2-Clause": [ + "Copyright (C) 2023 Bob", + "Copyright (C) 2023 embedded brains GmbH & Co. KG" + ] + } + + variant["enabled"] = ["sphinx-builder-2"] + doc_2 = director["/qdp/steps/doc-2"] + doc_2.substitute("${.:/document-bsd-2-clause-copyrights}") == "\n" + + with pytest.raises(NotImplementedError): + doc_2.mapper.get_link(doc_2.mapper.item) + + with doc_2.section_level( + ItemGetValueContext(doc_2.item, "", "", "", -1, + "")) as (section_level, args): + assert section_level == 3 + assert args == None + with doc_2.section_level( + ItemGetValueContext(doc_2.item, "", "", "", -1, + "-1")) as (section_level, args): + assert section_level == 1 + assert args == None + with doc_2.section_level( + ItemGetValueContext(doc_2.item, "", "", "", -1, + "2:mo:re")) as (section_level, args): + assert section_level == 4 + assert args == "mo:re" + + doc_2.item["document-components"].append({ + "action": "foobar", + "add-to-index": False, + "value": 123 + }) + action_run = 0 + + def action(component): + nonlocal action_run + action_run += 1 + assert component["value"] == 123 + + doc_2.add_component_action("foobar", action) + director.build_package(None, None) + assert action_run == 1 diff --git a/spec-qdp/spec/qdp-document-license-map.yml b/spec-qdp/spec/qdp-document-license-map.yml new file mode 100644 index 00000000..6f8d3959 --- /dev/null +++ b/spec-qdp/spec/qdp-document-license-map.yml @@ -0,0 +1,25 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2023 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +spec-description: null +spec-example: null +spec-info: + dict: + attributes: {} + description: | + This set of attributes specifies how SPDX license identifiers are mapped + to another SPDX license identifier. For example, it may be used to map + "CC-BY-SA-4.0 OR BSD-2-Clause" to "CC-BY-SA-4.0" for a particular + document. + generic-attributes: + description: null + key-spec-type: spdx-license-identifier + value-spec-type: spdx-license-identifier + mandatory-attributes: all +spec-name: Document License Map +spec-type: qdp-document-license-map +type: spec diff --git a/spec-qdp/spec/qdp-sphinx-build.yml b/spec-qdp/spec/qdp-sphinx-build.yml new file mode 100644 index 00000000..666f5de5 --- /dev/null +++ b/spec-qdp/spec/qdp-sphinx-build.yml @@ -0,0 +1,98 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2020, 2023 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +- role: spec-refinement + spec-key: build-step-type + spec-value: sphinx + uid: qdp-build-step +spec-description: | + Items of this type shall have the following links: + + * There shall be exactly one link to a ${qdp-directory-state:/spec-name} item + with the ${qdp-input-role:/spec-name} and the name ``"source"``. The link + target directory state item defines the source directory of the file copy + operation and the list of files to copy. + + * There shall be exactly one link to a ${qdp-directory-state:/spec-name} item + with the ${qdp-output-role:/spec-name} and the name ``"build"``. The link + target directory state item defines the build directory. + + * There shall be exactly one link to a ${qdp-directory-state:/spec-name} item + with the ${qdp-output-role:/spec-name} and the name ``"destination"``. The + link target directory state item defines the destination directory of the + generated output. +spec-example: null +spec-info: + dict: + attributes: + document-components: + description: null + spec-type: qdp-sphinx-component-list + document-contract: + description: | + It shall be the document contract reference. + spec-type: str + document-contributors: + description: null + spec-type: qdp-sphinx-contributor-action-list + document-copyrights: + description: | + It shall be the list of copyright statements of explicit contributors + to the document. The first contributor on the list is the main + contributor. + spec-type: copyrights + document-html-help-base-name: + description: | + It shall be the HTML help base name. + spec-type: str + document-key: + description: | + It shall be the document key, for example "icd". + spec-type: name + document-license: + description: | + It shall be the document license. + spec-type: spdx-license-identifier + document-license-map: + description: | + It shall be the document license map. + spec-type: qdp-document-license-map + document-releases: + description: null + spec-type: qdp-sphinx-release-list + document-title: + description: | + It shall be the document title. Use ``$${break}`` to add break hints + between words. + spec-type: str + document-toctree-maxdepth: + description: | + It shall be the maximum depth of the document table of contents tree. + spec-type: int + document-type: + description: | + It shall be the document type. + spec-type: str + output-html: + description: | + If the value is present, then it shall be the path to the generated + HTML document directory relative to the base directory of the + directory state production. + spec-type: optional-str + output-pdf: + description: | + If the value is present, then it shall be the path to the generated + PDF document relative to the base directory of the directory state + production. + spec-type: optional-str + description: | + This set of attributes specifies a document using the Sphinx + documentation framework. + mandatory-attributes: all +spec-name: Sphinx Document Build Item Type +spec-type: qdp-sphinx-build +type: spec diff --git a/spec-qdp/spec/qdp-sphinx-component-copy-and-substitute.yml b/spec-qdp/spec/qdp-sphinx-component-copy-and-substitute.yml new file mode 100644 index 00000000..a6fbb4c9 --- /dev/null +++ b/spec-qdp/spec/qdp-sphinx-component-copy-and-substitute.yml @@ -0,0 +1,34 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2020 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +- role: spec-refinement + spec-key: action + spec-value: copy-and-substitute + uid: qdp-sphinx-component +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + destination: + description: | + It shall be the destination path of a Sphinx source file relative to + the build directory. + spec-type: str + source: + description: | + It shall be the source path of a Sphinx source file relative to the + base directory of the directory state dependency. + spec-type: str + description: | + This set of attributes specifies a file to copy for a document using the + Sphinx documentation framework. A variable substitution is performed on + the source file. + mandatory-attributes: all +spec-name: Sphinx Document Component Copy and Substitute Action +spec-type: qdp-sphinx-component-copy-and-substitute +type: spec diff --git a/spec-qdp/spec/qdp-sphinx-component-copy-files.yml b/spec-qdp/spec/qdp-sphinx-component-copy-files.yml new file mode 100644 index 00000000..af8e8c8d --- /dev/null +++ b/spec-qdp/spec/qdp-sphinx-component-copy-files.yml @@ -0,0 +1,38 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2020, 2023 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +- role: spec-refinement + spec-key: action + spec-value: copy-files + uid: qdp-sphinx-component +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + destination: + description: | + It shall be the path to the destination directory. + spec-type: str + files: + description: | + It shall be the list of the files to copy from the source directory + to the destination directory. The files may be specified by a path + relative to the source directory. This relative path is preserved in + the destination directory. + spec-type: list-str + source: + description: | + It shall be the path to the source directory. + spec-type: str + description: | + This set of attributes specifies a list of files to copy from the source + directory to the destination directory. + mandatory-attributes: all +spec-name: Sphinx Document Component Copy Files Action +spec-type: qdp-sphinx-component-copy-files +type: spec diff --git a/spec-qdp/spec/qdp-sphinx-component-copy.yml b/spec-qdp/spec/qdp-sphinx-component-copy.yml new file mode 100644 index 00000000..76f86554 --- /dev/null +++ b/spec-qdp/spec/qdp-sphinx-component-copy.yml @@ -0,0 +1,33 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2020 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +- role: spec-refinement + spec-key: action + spec-value: copy + uid: qdp-sphinx-component +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + destination: + description: | + It shall be the destination path of a Sphinx source file relative to + the build directory. + spec-type: str + source: + description: | + It shall be the source path of a Sphinx source file relative to the + base directory of the directory state dependency. + spec-type: str + description: | + This set of attributes specifies a file to copy for a document using the + Sphinx documentation framework. + mandatory-attributes: all +spec-name: Sphinx Document Component Copy Action +spec-type: qdp-sphinx-component-copy +type: spec diff --git a/spec-qdp/spec/qdp-sphinx-component-generic.yml b/spec-qdp/spec/qdp-sphinx-component-generic.yml new file mode 100644 index 00000000..edd9474f --- /dev/null +++ b/spec-qdp/spec/qdp-sphinx-component-generic.yml @@ -0,0 +1,52 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2020, 2022 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +- role: spec-refinement + spec-key: action + spec-value: add-to-index + uid: qdp-sphinx-component +- role: spec-refinement + spec-key: action + spec-value: known-problems + uid: qdp-sphinx-component +- role: spec-refinement + spec-key: action + spec-value: requirements + uid: qdp-sphinx-component +- role: spec-refinement + spec-key: action + spec-value: requirements-and-design + uid: qdp-sphinx-component +- role: spec-refinement + spec-key: action + spec-value: test-cases + uid: qdp-sphinx-component +- role: spec-refinement + spec-key: action + spec-value: traceability + uid: qdp-sphinx-component +- role: spec-refinement + spec-key: action + spec-value: validation + uid: qdp-sphinx-component +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + destination: + description: | + It shall be the destination path of a Sphinx source file relative to + the build directory. + spec-type: str + description: | + This set of attributes specifies that a generic action which produces a + Sphinx source file for a document using Sphinx documentation framework. + mandatory-attributes: all +spec-name: Sphinx Document Component Generic +spec-type: qdp-sphinx-component-generic +type: spec diff --git a/spec-qdp/spec/qdp-sphinx-component-glossary.yml b/spec-qdp/spec/qdp-sphinx-component-glossary.yml new file mode 100644 index 00000000..ad60b1d9 --- /dev/null +++ b/spec-qdp/spec/qdp-sphinx-component-glossary.yml @@ -0,0 +1,32 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2020, 2022 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +- role: spec-refinement + spec-key: action + spec-value: glossary + uid: qdp-sphinx-component +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + destination: + description: | + It shall be the destination path of a Sphinx source file relative to + the build directory. + spec-type: str + glossary-groups: + description: | + It shall be the list of Glossary group identifiers. + spec-type: list-uid + description: | + This set of attributes specifies that a file which should contain the + glossary of a document using Sphinx documentation framework. + mandatory-attributes: all +spec-name: Sphinx Document Component Glossary +spec-type: qdp-sphinx-component-glossary +type: spec diff --git a/spec-qdp/spec/qdp-sphinx-component-list.yml b/spec-qdp/spec/qdp-sphinx-component-list.yml new file mode 100644 index 00000000..9dbcd269 --- /dev/null +++ b/spec-qdp/spec/qdp-sphinx-component-list.yml @@ -0,0 +1,16 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2020 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +spec-description: null +spec-example: null +spec-info: + list: + description: null + spec-type: qdp-sphinx-component +spec-name: Sphinx Document Component List +spec-type: qdp-sphinx-component-list +type: spec diff --git a/spec-qdp/spec/qdp-sphinx-component.yml b/spec-qdp/spec/qdp-sphinx-component.yml new file mode 100644 index 00000000..d0c1748b --- /dev/null +++ b/spec-qdp/spec/qdp-sphinx-component.yml @@ -0,0 +1,34 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2020 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + action: + description: | + It shall be the Sphinx component action. + spec-type: str + add-to-index: + description: | + It set to true, then the file will be added to the index, otherwise + it will not be added to the index. + spec-type: bool + enabled-by: + description: | + It shall define the conditions under which the action is enabled. + spec-type: enabled-by + description: | + This set of attributes specifies a component of a document using the + Sphinx documentation framework. + mandatory-attributes: + - action + - add-to-index +spec-name: Sphinx Document Component +spec-type: qdp-sphinx-component +type: spec diff --git a/spec-qdp/spec/qdp-sphinx-contributor-action-list.yml b/spec-qdp/spec/qdp-sphinx-contributor-action-list.yml new file mode 100644 index 00000000..4dee8dbd --- /dev/null +++ b/spec-qdp/spec/qdp-sphinx-contributor-action-list.yml @@ -0,0 +1,16 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2020 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +spec-description: null +spec-example: null +spec-info: + list: + description: null + spec-type: qdp-sphinx-contributor-action +spec-name: Sphinx Document Contributors by Action List +spec-type: qdp-sphinx-contributor-action-list +type: spec diff --git a/spec-qdp/spec/qdp-sphinx-contributor-action.yml b/spec-qdp/spec/qdp-sphinx-contributor-action.yml new file mode 100644 index 00000000..f398eb36 --- /dev/null +++ b/spec-qdp/spec/qdp-sphinx-contributor-action.yml @@ -0,0 +1,26 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2020 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + action: + description: | + It shall be the action performed by the contributors. + spec-type: str + contributors: + description: null + spec-type: qdp-sphinx-contributor-list + description: | + This set of attributes specifies document contributors which performed a + common action. + mandatory-attributes: all +spec-name: Sphinx Document Contributors by Action +spec-type: qdp-sphinx-contributor-action +type: spec diff --git a/spec-qdp/spec/qdp-sphinx-contributor-list.yml b/spec-qdp/spec/qdp-sphinx-contributor-list.yml new file mode 100644 index 00000000..4bd4c2d9 --- /dev/null +++ b/spec-qdp/spec/qdp-sphinx-contributor-list.yml @@ -0,0 +1,16 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2020 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +spec-description: null +spec-example: null +spec-info: + list: + description: null + spec-type: qdp-sphinx-contributor +spec-name: Sphinx Document Contributor List +spec-type: qdp-sphinx-contributor-list +type: spec diff --git a/spec-qdp/spec/qdp-sphinx-contributor.yml b/spec-qdp/spec/qdp-sphinx-contributor.yml new file mode 100644 index 00000000..cc10bd48 --- /dev/null +++ b/spec-qdp/spec/qdp-sphinx-contributor.yml @@ -0,0 +1,26 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2020 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + name: + description: | + It shall be the name of the contributor. + spec-type: str + organization: + description: | + It shall be the organization of the contributor. + spec-type: str + description: | + This set of attributes specifies a document contributor. + mandatory-attributes: all +spec-name: Sphinx Document Contributor +spec-type: qdp-sphinx-contributor +type: spec diff --git a/spec-qdp/spec/qdp-sphinx-release-list.yml b/spec-qdp/spec/qdp-sphinx-release-list.yml new file mode 100644 index 00000000..76414718 --- /dev/null +++ b/spec-qdp/spec/qdp-sphinx-release-list.yml @@ -0,0 +1,16 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2020 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +spec-description: null +spec-example: null +spec-info: + list: + description: null + spec-type: qdp-sphinx-release +spec-name: Sphinx Document Release List +spec-type: qdp-sphinx-release-list +type: spec diff --git a/spec-qdp/spec/qdp-sphinx-release.yml b/spec-qdp/spec/qdp-sphinx-release.yml new file mode 100644 index 00000000..498a3bd1 --- /dev/null +++ b/spec-qdp/spec/qdp-sphinx-release.yml @@ -0,0 +1,31 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2020 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + changes: + description: | + It shall be a summary of the document changes for this release in + Sphinx format. A variable substitution is performed. + spec-type: str + date: + description: | + It shall be a document release date. + spec-type: str + status: + description: | + It shall be a document release status. + spec-type: str + description: | + This set of attributes specifies a document release. + mandatory-attributes: all +spec-name: Sphinx Document Release +spec-type: qdp-sphinx-release +type: spec diff --git a/spec-qdp/spec/qdp-sphinx-section.yml b/spec-qdp/spec/qdp-sphinx-section.yml new file mode 100644 index 00000000..bc6ff494 --- /dev/null +++ b/spec-qdp/spec/qdp-sphinx-section.yml @@ -0,0 +1,34 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2023 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +- role: spec-refinement + spec-key: qdp-type + spec-value: sphinx-section + uid: qdp-root +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + content: + description: | + It shall be the section content. + spec-type: str + header: + description: | + It shall be the section header. + spec-type: str + label: + description: | + If the value is present, then it shall be the section label. + spec-type: optional-str + description: | + This set of attributes specifies a Sphinx section. + mandatory-attributes: all +spec-name: Sphinx Section Item Type +spec-type: qdp-sphinx-section +type: spec diff --git a/spec-qdp/spec/qdp-sphinx-types.yml b/spec-qdp/spec/qdp-sphinx-types.yml new file mode 100644 index 00000000..dfa7c2f8 --- /dev/null +++ b/spec-qdp/spec/qdp-sphinx-types.yml @@ -0,0 +1,23 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2020 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +- role: spec-refinement + spec-key: document-type + spec-value: generic + uid: qdp-sphinx-build +spec-description: null +spec-example: null +spec-info: + dict: + attributes: {} + description: | + This empty set of attributes is used for refined Sphinx document types + which do not need extra attributes. + mandatory-attributes: all +spec-name: Build Sphinx Simple Document Item Types +spec-type: qdp-sphinx-types +type: spec -- cgit v1.2.3