summary refs log tree commit diff stats
path: root/docs/sphinx/qapidoc.py
diff options
context:
space:
mode:
authorJohn Snow <jsnow@redhat.com>2025-03-10 23:42:37 -0400
committerMarkus Armbruster <armbru@redhat.com>2025-03-11 10:10:57 +0100
commitbd7c1496aa695f7b7a560a2caf29f4b84f8752af (patch)
tree84274277fc39ea7a994f8601c2d09635a01250db /docs/sphinx/qapidoc.py
parent45d483a851051bcea3a32b1ce7367180a8cf7bae (diff)
downloadfocaccia-qemu-bd7c1496aa695f7b7a560a2caf29f4b84f8752af.tar.gz
focaccia-qemu-bd7c1496aa695f7b7a560a2caf29f4b84f8752af.zip
docs/qapidoc: add transmogrifier class stub
Add the beginnings of the Transmogrifier class by adding the rST
conversion helpers that will be used to build the virtual rST document.

This version of the class does not actually "do anything" yet; each
individual feature is added one-at-a-time in the forthcoming commits.

Signed-off-by: John Snow <jsnow@redhat.com>
Message-ID: <20250311034303.75779-40-jsnow@redhat.com>
Acked-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Diffstat (limited to '')
-rw-r--r--docs/sphinx/qapidoc.py73
1 files changed, 70 insertions, 3 deletions
diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py
index 5246832b68..c243bb6faa 100644
--- a/docs/sphinx/qapidoc.py
+++ b/docs/sphinx/qapidoc.py
@@ -26,14 +26,17 @@ https://www.sphinx-doc.org/en/master/development/index.html
 
 from __future__ import annotations
 
+from contextlib import contextmanager
 import os
 import sys
 from typing import TYPE_CHECKING
 
 from docutils import nodes
 from docutils.parsers.rst import Directive, directives
+from docutils.statemachine import StringList
 from qapi.error import QAPIError
 from qapi.schema import QAPISchema, QAPISchemaVisitor
+from qapi.source import QAPISourceInfo
 
 from qapidoc_legacy import QAPISchemaGenRSTVisitor  # type: ignore
 from sphinx import addnodes
@@ -44,9 +47,12 @@ from sphinx.util.nodes import nested_parse_with_titles
 
 
 if TYPE_CHECKING:
-    from typing import Any, List, Sequence
-
-    from docutils.statemachine import StringList
+    from typing import (
+        Any,
+        Generator,
+        List,
+        Sequence,
+    )
 
     from sphinx.application import Sphinx
     from sphinx.util.typing import ExtensionMetadata
@@ -55,6 +61,67 @@ if TYPE_CHECKING:
 __version__ = "1.0"
 
 
+class Transmogrifier:
+    def __init__(self) -> None:
+        self._result = StringList()
+        self.indent = 0
+
+    # General-purpose rST generation functions
+
+    def get_indent(self) -> str:
+        return "   " * self.indent
+
+    @contextmanager
+    def indented(self) -> Generator[None]:
+        self.indent += 1
+        try:
+            yield
+        finally:
+            self.indent -= 1
+
+    def add_line_raw(self, line: str, source: str, *lineno: int) -> None:
+        """Append one line of generated reST to the output."""
+
+        # NB: Sphinx uses zero-indexed lines; subtract one.
+        lineno = tuple((n - 1 for n in lineno))
+
+        if line.strip():
+            # not a blank line
+            self._result.append(
+                self.get_indent() + line.rstrip("\n"), source, *lineno
+            )
+        else:
+            self._result.append("", source, *lineno)
+
+    def add_line(self, content: str, info: QAPISourceInfo) -> None:
+        # NB: We *require* an info object; this works out OK because we
+        # don't document built-in objects that don't have
+        # one. Everything else should.
+        self.add_line_raw(content, info.fname, info.line)
+
+    def add_lines(
+        self,
+        content: str,
+        info: QAPISourceInfo,
+    ) -> None:
+        lines = content.splitlines(True)
+        for i, line in enumerate(lines):
+            self.add_line_raw(line, info.fname, info.line + i)
+
+    def ensure_blank_line(self) -> None:
+        # Empty document -- no blank line required.
+        if not self._result:
+            return
+
+        # Last line isn't blank, add one.
+        if self._result[-1].strip():  # pylint: disable=no-member
+            fname, line = self._result.info(-1)
+            assert isinstance(line, int)
+            # New blank line is credited to one-after the current last line.
+            # +2: correct for zero/one index, then increment by one.
+            self.add_line_raw("", fname, line + 2)
+
+
 class QAPISchemaGenDepVisitor(QAPISchemaVisitor):
     """A QAPI schema visitor which adds Sphinx dependencies each module