summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2020-05-27 14:05:36 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2020-05-28 10:38:23 +0200
commitc8e568a1caf99693515e4e0ca798d3e6c8b2747c (patch)
tree3bb3a7df6e55032de4ec42d696e86b815e37652f
parentspec: Add interface domain items (diff)
downloadrtems-central-c8e568a1caf99693515e4e0ca798d3e6c8b2747c.tar.bz2
sphinxcontent: Move Sphinx content to new module
-rw-r--r--rtemsqual/applconfig.py2
-rw-r--r--rtemsqual/content.py181
-rw-r--r--rtemsqual/glossary.py2
-rw-r--r--rtemsqual/specdoc.py2
-rw-r--r--rtemsqual/sphinxcontent.py205
-rw-r--r--rtemsqual/tests/test_content_sphinx.py106
6 files changed, 267 insertions, 231 deletions
diff --git a/rtemsqual/applconfig.py b/rtemsqual/applconfig.py
index 7b7b3e17..2a4074f2 100644
--- a/rtemsqual/applconfig.py
+++ b/rtemsqual/applconfig.py
@@ -26,7 +26,7 @@
from typing import Any, Dict, List, Optional
-from rtemsqual.content import SphinxContent
+from rtemsqual.sphinxcontent import SphinxContent
from rtemsqual.items import Item, ItemCache
ItemMap = Dict[str, Item]
diff --git a/rtemsqual/content.py b/rtemsqual/content.py
index 8aa0cb5b..bf07ebdd 100644
--- a/rtemsqual/content.py
+++ b/rtemsqual/content.py
@@ -32,7 +32,7 @@ import textwrap
from typing import Any, Callable, ContextManager, Dict, Iterable, Iterator, \
List, NamedTuple, Optional, Set, Tuple, Union
-from rtemsqual.items import Item, ItemMapper
+from rtemsqual.items import Item
AddContext = Callable[["Content"], ContextManager[None]]
GenericContent = Union[str, List[str], "Content"]
@@ -128,7 +128,8 @@ class Copyrights:
return statements
-def _make_lines(content: GenericContent) -> List[str]:
+def make_lines(content: GenericContent) -> List[str]:
+ """ Makes a list of lines from a generic content. """
if isinstance(content, str):
return content.strip("\n").split("\n")
if isinstance(content, list):
@@ -146,21 +147,11 @@ def _indent(lines: List[str], indent: str,
return lines
-def _to_camel_case(name: str) -> str:
- return name[0].upper() + re.sub(
- r"[^a-zA-Z0-9]", "X",
- re.sub(r"[ \n\t]+([a-zA-Z0-9])", lambda match: match.group(1).upper(),
- name[1:]))
-
-
@contextmanager
def _add_context(_content: "Content") -> Iterator[None]:
yield
-_HEADER_LEVELS = ["#", "*", "=", "-", "^", "\""]
-
-
class Content:
""" This class builds content. """
@@ -193,12 +184,12 @@ class Content:
def append(self, content: GenericContent) -> None:
""" Appends the content. """
self._lines.extend(
- _indent(_make_lines(content), self._indent,
+ _indent(make_lines(content), self._indent,
self._empty_line_indent))
def prepend(self, content: GenericContent) -> None:
""" Prepends the content. """
- self._lines[0:0] = _indent(_make_lines(content), self._indent,
+ self._lines[0:0] = _indent(make_lines(content), self._indent,
self._empty_line_indent)
def add(self,
@@ -209,7 +200,7 @@ class Content:
"""
if not content:
return
- lines = _make_lines(content)
+ lines = make_lines(content)
index = 0
for line in lines:
if line:
@@ -405,166 +396,6 @@ class Content:
out.write(str(self))
-class SphinxContent(Content):
- """ This class builds Sphinx content. """
- def __init__(self, section_level: int = 2):
- super().__init__("CC-BY-SA-4.0", True)
- self._tab = " "
- self._section_level = section_level
-
- def get_reference(self, label: str, name: Optional[str] = None) -> str:
- """ Returns the reference to the specified label. """
- # pylint: disable=no-self-use
- if name:
- return f":ref:`{name} <{label}>`"
- return f":ref:`{label}`"
-
- def add_label(self, label: str) -> None:
- """ Adds a label. """
- self.add(".. _" + label.strip() + ":")
-
- def get_section_label(self, name: str, prefix: str = "Section") -> str:
- """ Returns the section label for the specified section name. """
- # pylint: disable=no-self-use
- return prefix + _to_camel_case(name.strip())
-
- def add_header(self, name, level=2) -> None:
- """ Adds a header. """
- name = name.strip()
- self.add([name, _HEADER_LEVELS[level] * len(name)])
-
- def add_header_with_label(self,
- name: str,
- level: int = 2,
- label_prefix: str = "Section") -> str:
- """ Adds a header with label. """
- label = self.get_section_label(name, label_prefix)
- self.add_label(label)
- self.add_header(name, level)
- return label
-
- def add_index_entries(self, entries) -> None:
- """ Adds a list of index entries the content. """
- self.add([".. index:: " + entry for entry in _make_lines(entries)])
-
- def add_definition_item(self, name, lines) -> None:
- """ Adds a definition item the content. """
- @contextmanager
- def _definition_item_context(content: Content) -> Iterator[None]:
- content.append(name)
- content.push_indent()
- yield
- content.pop_indent()
-
- self.add(lines, _definition_item_context)
-
- def open_directive(self,
- name: str,
- value: Optional[str] = None,
- options: Optional[List[str]] = None) -> None:
- """ Opens a directive. """
- value = " " + value if value else ""
- self.add(f".. {name.strip()}::{value}")
- self.push_indent()
- self.add(options)
- self.gap = True
-
- def close_directive(self) -> None:
- """ Closes a directive. """
- self.pop_indent()
-
- @contextmanager
- def directive(self,
- name: str,
- value: Optional[str] = None,
- options: Optional[List[str]] = None):
- """ Opens a directive context. """
- self.open_directive(name, value, options)
- yield
- self.close_directive()
-
- def open_section(self, name: str, label_prefix: str = "Section") -> str:
- """ Opens a section. """
- label = self.add_header_with_label(name, self._section_level,
- label_prefix)
- self._section_level += 1
- return label
-
- def close_section(self) -> None:
- """ Closes a section. """
- self._section_level -= 1
-
- @contextmanager
- def section(self,
- name: str,
- label_prefix: str = "Section") -> Iterator[str]:
- """ Opens a section context. """
- yield self.open_section(name, label_prefix)
- self.close_section()
-
- def add_list_item(self, content: GenericContent) -> None:
- """ Adds a list item. """
- self.wrap(content, initial_indent="* ", subsequent_indent=" ")
-
- def add_list(self,
- items: GenericContentIterable,
- prologue: Optional[GenericContent] = None,
- epilogue: Optional[GenericContent] = None,
- add_blank_line: bool = False) -> None:
- """ Adds a list with introduction. """
- if items:
- self.wrap(prologue)
- for item in items:
- self.add_list_item(item)
- if add_blank_line:
- self.add_blank_line()
- self.wrap(epilogue)
-
- def open_list_item(self, content: GenericContent) -> None:
- """ Opens a list item. """
- self.add(["* "])
- self.push_indent(" ")
- self.gap = True
- self.paste(content)
-
- def close_list_item(self) -> None:
- """ Closes a list item. """
- self.pop_indent()
- self.gap = True
-
- @contextmanager
- def list_item(self, content: GenericContent) -> Iterator[None]:
- """ Opens a list item context. """
- self.open_list_item(content)
- yield
- self.close_list_item()
-
- def add_licence_and_copyrights(self) -> None:
- """
- Adds a licence and copyright block according to the registered licenses
- and copyrights.
- """
- statements = self._copyrights.get_statements()
- if statements:
- self.prepend("")
- self.prepend([f".. {stm}" for stm in statements])
- self.prepend([f".. SPDX-License-Identifier: {self._license}", ""])
-
-
-class SphinxMapper(ItemMapper):
- """ Sphinx mapper. """
- def __init__(self, item: Item):
- super().__init__(item)
-
- def get_value(self, _item: Item, _path: str, value: Any, key: str,
- _index: Optional[int]) -> Any:
- """ Gets a value by key and optional index. """
- # pylint: disable=no-self-use
- if key == "term":
- return f":term:`{value[key]}`"
- raise KeyError
-
-
_BSD_2_CLAUSE_LICENSE = """Redistribution and use in source and binary \
forms, with or without
modification, are permitted provided that the following conditions
diff --git a/rtemsqual/glossary.py b/rtemsqual/glossary.py
index 14448e0b..f05e3aee 100644
--- a/rtemsqual/glossary.py
+++ b/rtemsqual/glossary.py
@@ -28,7 +28,7 @@ import glob
import re
from typing import Any, Dict, Optional
-from rtemsqual.content import SphinxContent, SphinxMapper
+from rtemsqual.sphinxcontent import SphinxContent, SphinxMapper
from rtemsqual.items import Item, ItemCache, ItemMapper
ItemMap = Dict[str, Item]
diff --git a/rtemsqual/specdoc.py b/rtemsqual/specdoc.py
index 7a99e788..8dde1d41 100644
--- a/rtemsqual/specdoc.py
+++ b/rtemsqual/specdoc.py
@@ -26,7 +26,7 @@
from typing import Any, Dict, Iterator, Optional, Set, Tuple
-from rtemsqual.content import SphinxContent
+from rtemsqual.sphinxcontent import SphinxContent
from rtemsqual.items import Item, ItemCache
from rtemsqual.specverify import NAME
diff --git a/rtemsqual/sphinxcontent.py b/rtemsqual/sphinxcontent.py
new file mode 100644
index 00000000..fbcbd22f
--- /dev/null
+++ b/rtemsqual/sphinxcontent.py
@@ -0,0 +1,205 @@
+# SPDX-License-Identifier: BSD-2-Clause
+""" This module provides classes for Sphinx content generation. """
+
+# Copyright (C) 2019, 2020 embedded brains GmbH (http://www.embedded-brains.de)
+#
+# 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 re
+from typing import Any, Iterable, Iterator, List, Optional, Union
+
+from rtemsqual.content import Content, make_lines
+from rtemsqual.items import Item, ItemMapper
+
+GenericContent = Union[str, List[str], "Content"]
+GenericContentIterable = Union[Iterable[str], Iterable[List[str]],
+ Iterable[GenericContent]]
+
+_HEADER_LEVELS = ["#", "*", "=", "-", "^", "\""]
+
+
+def _to_camel_case(name: str) -> str:
+ return name[0].upper() + re.sub(
+ r"[^a-zA-Z0-9]", "X",
+ re.sub(r"[ \n\t]+([a-zA-Z0-9])", lambda match: match.group(1).upper(),
+ name[1:]))
+
+
+class SphinxContent(Content):
+ """ This class builds Sphinx content. """
+ def __init__(self, section_level: int = 2):
+ super().__init__("CC-BY-SA-4.0", True)
+ self._tab = " "
+ self._section_level = section_level
+
+ def get_reference(self, label: str, name: Optional[str] = None) -> str:
+ """ Returns the reference to the specified label. """
+ # pylint: disable=no-self-use
+ if name:
+ return f":ref:`{name} <{label}>`"
+ return f":ref:`{label}`"
+
+ def add_label(self, label: str) -> None:
+ """ Adds a label. """
+ self.add(".. _" + label.strip() + ":")
+
+ def get_section_label(self, name: str, prefix: str = "Section") -> str:
+ """ Returns the section label for the specified section name. """
+ # pylint: disable=no-self-use
+ return prefix + _to_camel_case(name.strip())
+
+ def add_header(self, name, level=2) -> None:
+ """ Adds a header. """
+ name = name.strip()
+ self.add([name, _HEADER_LEVELS[level] * len(name)])
+
+ def add_header_with_label(self,
+ name: str,
+ level: int = 2,
+ label_prefix: str = "Section") -> str:
+ """ Adds a header with label. """
+ label = self.get_section_label(name, label_prefix)
+ self.add_label(label)
+ self.add_header(name, level)
+ return label
+
+ def add_index_entries(self, entries) -> None:
+ """ Adds a list of index entries the content. """
+ self.add([".. index:: " + entry for entry in make_lines(entries)])
+
+ def add_definition_item(self, name, lines) -> None:
+ """ Adds a definition item the content. """
+ @contextmanager
+ def _definition_item_context(content: Content) -> Iterator[None]:
+ content.append(name)
+ content.push_indent()
+ yield
+ content.pop_indent()
+
+ self.add(lines, _definition_item_context)
+
+ def open_directive(self,
+ name: str,
+ value: Optional[str] = None,
+ options: Optional[List[str]] = None) -> None:
+ """ Opens a directive. """
+ value = " " + value if value else ""
+ self.add(f".. {name.strip()}::{value}")
+ self.push_indent()
+ self.add(options)
+ self.gap = True
+
+ def close_directive(self) -> None:
+ """ Closes a directive. """
+ self.pop_indent()
+
+ @contextmanager
+ def directive(self,
+ name: str,
+ value: Optional[str] = None,
+ options: Optional[List[str]] = None):
+ """ Opens a directive context. """
+ self.open_directive(name, value, options)
+ yield
+ self.close_directive()
+
+ def open_section(self, name: str, label_prefix: str = "Section") -> str:
+ """ Opens a section. """
+ label = self.add_header_with_label(name, self._section_level,
+ label_prefix)
+ self._section_level += 1
+ return label
+
+ def close_section(self) -> None:
+ """ Closes a section. """
+ self._section_level -= 1
+
+ @contextmanager
+ def section(self,
+ name: str,
+ label_prefix: str = "Section") -> Iterator[str]:
+ """ Opens a section context. """
+ yield self.open_section(name, label_prefix)
+ self.close_section()
+
+ def add_list_item(self, content: GenericContent) -> None:
+ """ Adds a list item. """
+ self.wrap(content, initial_indent="* ", subsequent_indent=" ")
+
+ def add_list(self,
+ items: GenericContentIterable,
+ prologue: Optional[GenericContent] = None,
+ epilogue: Optional[GenericContent] = None,
+ add_blank_line: bool = False) -> None:
+ """ Adds a list with introduction. """
+ if items:
+ self.wrap(prologue)
+ for item in items:
+ self.add_list_item(item)
+ if add_blank_line:
+ self.add_blank_line()
+ self.wrap(epilogue)
+
+ def open_list_item(self, content: GenericContent) -> None:
+ """ Opens a list item. """
+ self.add(["* "])
+ self.push_indent(" ")
+ self.gap = True
+ self.paste(content)
+
+ def close_list_item(self) -> None:
+ """ Closes a list item. """
+ self.pop_indent()
+ self.gap = True
+
+ @contextmanager
+ def list_item(self, content: GenericContent) -> Iterator[None]:
+ """ Opens a list item context. """
+ self.open_list_item(content)
+ yield
+ self.close_list_item()
+
+ def add_licence_and_copyrights(self) -> None:
+ """
+ Adds a licence and copyright block according to the registered licenses
+ and copyrights.
+ """
+ statements = self._copyrights.get_statements()
+ if statements:
+ self.prepend("")
+ self.prepend([f".. {stm}" for stm in statements])
+ self.prepend([f".. SPDX-License-Identifier: {self._license}", ""])
+
+
+class SphinxMapper(ItemMapper):
+ """ Sphinx mapper. """
+ def __init__(self, item: Item):
+ super().__init__(item)
+
+ def get_value(self, _item: Item, _path: str, value: Any, key: str,
+ _index: Optional[int]) -> Any:
+ """ Gets a value by key and optional index. """
+ # pylint: disable=no-self-use
+ if key == "term":
+ return f":term:`{value[key]}`"
+ raise KeyError
diff --git a/rtemsqual/tests/test_content_sphinx.py b/rtemsqual/tests/test_content_sphinx.py
index 4f033077..43272c38 100644
--- a/rtemsqual/tests/test_content_sphinx.py
+++ b/rtemsqual/tests/test_content_sphinx.py
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: BSD-2-Clause
-""" Unit tests for the rtemsqual.content module. """
+""" Unit tests for the rtemsqual.sphinxcontent module. """
# Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de)
#
@@ -26,29 +26,29 @@
import pytest
-from rtemsqual.content import SphinxContent, SphinxMapper
+from rtemsqual.sphinxcontent import SphinxContent, SphinxMapper
from rtemsqual.items import Item, ItemCache, ItemMapper
from rtemsqual.tests.util import create_item_cache_config_and_copy_spec
def test_add_label():
- sc = SphinxContent()
- sc.add_label("x")
- assert str(sc) == """.. _x:
+ content = SphinxContent()
+ content.add_label("x")
+ assert str(content) == """.. _x:
"""
def test_directive():
- sc = SphinxContent()
- with sc.directive("x"):
- sc.add("y")
- assert str(sc) == """.. x::
+ content = SphinxContent()
+ with content.directive("x"):
+ content.add("y")
+ assert str(content) == """.. x::
y
"""
- with sc.directive("z", "xy", [":a:", ":b:"]):
- sc.add("c")
- assert str(sc) == """.. x::
+ with content.directive("z", "xy", [":a:", ":b:"]):
+ content.add("c")
+ assert str(content) == """.. x::
y
@@ -61,13 +61,13 @@ def test_directive():
def test_add_header():
- sc = SphinxContent()
- sc.add_header("x")
- assert str(sc) == """x
+ content = SphinxContent()
+ content.add_header("x")
+ assert str(content) == """x
=
"""
- sc.add_header("yz", 1)
- assert str(sc) == """x
+ content.add_header("yz", 1)
+ assert str(content) == """x
=
yz
@@ -76,17 +76,17 @@ yz
def test_add_header_with_label():
- sc = SphinxContent()
- label = sc.add_header_with_label("x", 1)
+ content = SphinxContent()
+ label = content.add_header_with_label("x", 1)
assert label == "SectionX"
- assert str(sc) == """.. _SectionX:
+ assert str(content) == """.. _SectionX:
x
*
"""
- label = sc.add_header_with_label("yz w", 2)
+ label = content.add_header_with_label("yz w", 2)
assert label == "SectionYzW"
- assert str(sc) == """.. _SectionX:
+ assert str(content) == """.. _SectionX:
x
*
@@ -171,30 +171,30 @@ d
def test_append():
- sc = SphinxContent()
- sc.append("x")
- assert str(sc) == """x
+ content = SphinxContent()
+ content.append("x")
+ assert str(content) == """x
"""
- with sc.indent():
- sc.append("y")
- assert str(sc) == """x
+ with content.indent():
+ content.append("y")
+ assert str(content) == """x
y
"""
- sc.append("")
- assert str(sc) == """x
+ content.append("")
+ assert str(content) == """x
y
"""
def test_add_index_entries():
- sc = SphinxContent()
- sc.add_index_entries(["x", "y"])
- assert str(sc) == """.. index:: x
+ content = SphinxContent()
+ content.add_index_entries(["x", "y"])
+ assert str(content) == """.. index:: x
.. index:: y
"""
- sc.add_index_entries("z")
- assert str(sc) == """.. index:: x
+ content.add_index_entries("z")
+ assert str(content) == """.. index:: x
.. index:: y
.. index:: z
@@ -202,39 +202,39 @@ def test_add_index_entries():
def test_add_definition_item():
- sc = SphinxContent()
- sc.add_definition_item("x", ["y", "z"])
- assert str(sc) == """x
+ content = SphinxContent()
+ content.add_definition_item("x", ["y", "z"])
+ assert str(content) == """x
y
z
"""
- sc = SphinxContent()
- sc.add_definition_item("a", "\n b\n")
- assert str(sc) == """a
+ content = SphinxContent()
+ content.add_definition_item("a", "\n b\n")
+ assert str(content) == """a
b
"""
def test_license():
- sc = SphinxContent()
+ content = SphinxContent()
with pytest.raises(ValueError):
- sc.register_license("x")
- sc.register_license("CC-BY-SA-4.0")
- assert str(sc) == ""
- sc.add_licence_and_copyrights()
- assert str(sc) == """.. SPDX-License-Identifier: CC-BY-SA-4.0
+ content.register_license("x")
+ content.register_license("CC-BY-SA-4.0")
+ assert str(content) == ""
+ content.add_licence_and_copyrights()
+ assert str(content) == """.. SPDX-License-Identifier: CC-BY-SA-4.0
"""
def test_license_and_copyrights():
- sc = SphinxContent()
+ content = SphinxContent()
with pytest.raises(ValueError):
- sc.register_license("x")
- sc.register_copyright("Copyright (C) A")
- assert str(sc) == ""
- sc.add_licence_and_copyrights()
- assert str(sc) == """.. SPDX-License-Identifier: CC-BY-SA-4.0
+ content.register_license("x")
+ content.register_copyright("Copyright (C) A")
+ assert str(content) == ""
+ content.add_licence_and_copyrights()
+ assert str(content) == """.. SPDX-License-Identifier: CC-BY-SA-4.0
.. Copyright (C) A