qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/21] qapi: convert "Note" and "Example" sections to rST
@ 2024-06-26 22:21 John Snow
  2024-06-26 22:21 ` [PATCH v2 01/21] [DO-NOT-MERGE]: Add some ad-hoc linting helpers John Snow
                   ` (20 more replies)
  0 siblings, 21 replies; 44+ messages in thread
From: John Snow @ 2024-06-26 22:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Markus Armbruster, Philippe Mathieu-Daudé, Lukas Straub,
	Igor Mammedov, Jason Wang, Yanan Wang, Hanna Reitz,
	Konstantin Kostiuk, Stefan Berger, John Snow

This series focuses primarily on converting our existing QAPI/QMP
documentation to remove special "Note" and "Example" sections in favor
of rST markup for the same.

This is being done primarily to reduce the number of specially parsed
QAPI sections we have in favor of allowing fully arbitrary rST markup
for greater flexibility and freedom in styling the rendered HTML
documentation.

(A tangible side benefit is that the new qapidoc generator has fewer
sections to reason about when it splices inherited documentation
together for the QMP reference manual; docs largely preserve the order
of documentation "as written" instead of needing to splice multiple
separate sections together. A goal of the new generator is to eventually
remove all tagged sections except for "members" and "features".)

V2:
 - Lotsa stuff :{
 - Added new example box styling and sphinx directive macro
 - Addressed... most? list feedback. (But not the indent split.)

Known issues:

- The Example boxes are styled a little wonkily if prose follows the
  code-block instead of precedes it, fixup will be tomorrow.

--js

Harmonie Snow (1):
  docs/sphinx: add CSS styling for qmp-example directive

John Snow (20):
  [DO-NOT-MERGE]: Add some ad-hoc linting helpers.
  qapi: linter fixups
  docs/qapidoc: remove unused intersperse function
  docs/qapidoc: delint a tiny portion of the module
  qapi/parser: preserve indentation in QAPIDoc sections
  qapi/parser: fix comment parsing immediately following a doc block
  docs/qapidoc: fix nested parsing under untagged sections
  qapi: fix non-compliant JSON examples
  qapi: nail down convention that Errors sections are lists
  qapi: convert "Note" sections to plain rST
  qapi: update prose in note blocks
  qapi: add markup to note blocks
  qapi/parser: don't parse rST markup as section headers
  docs/qapidoc: factor out do_parse()
  docs/qapidoc: create qmp-example directive
  docs/qapidoc: add QMP highlighting to annotated qmp-example blocks
  qapi: convert "Example" sections without titles
  qapi: convert "Example" sections with titles
  qapi: convert "Example" sections with longer prose
  qapi: remove "Example" doc section

 docs/devel/qapi-code-gen.rst                  |  25 +-
 docs/sphinx-static/theme_overrides.css        |  46 ++++
 docs/sphinx/qapidoc.py                        | 258 +++++++++++++-----
 qapi/acpi.json                                |   4 +-
 qapi/block-core.json                          | 116 ++++----
 qapi/block.json                               |  59 ++--
 qapi/char.json                                |  36 ++-
 qapi/control.json                             |  28 +-
 qapi/dump.json                                |  10 +-
 qapi/introspect.json                          |   6 +-
 qapi/machine-target.json                      |  28 +-
 qapi/machine.json                             | 117 ++++----
 qapi/migration.json                           | 104 +++----
 qapi/misc-target.json                         |  22 +-
 qapi/misc.json                                | 123 +++++----
 qapi/net.json                                 |  32 ++-
 qapi/pci.json                                 |  10 +-
 qapi/qdev.json                                |  40 +--
 qapi/qom.json                                 |  33 ++-
 qapi/replay.json                              |   8 +-
 qapi/rocker.json                              |  26 +-
 qapi/run-state.json                           |  48 ++--
 qapi/sockets.json                             |  10 +-
 qapi/stats.json                               |  22 +-
 qapi/tpm.json                                 |   6 +-
 qapi/trace.json                               |   4 +-
 qapi/transaction.json                         |  12 +-
 qapi/ui.json                                  |  76 +++---
 qapi/vfio.json                                |   2 +-
 qapi/virtio.json                              |  57 ++--
 qapi/yank.json                                |   4 +-
 qga/qapi-schema.json                          |  48 ++--
 scripts/qapi-lint.sh                          |  61 +++++
 scripts/qapi/Makefile                         |   5 +
 scripts/qapi/introspect.py                    |   8 +-
 scripts/qapi/parser.py                        |  38 ++-
 scripts/qapi/schema.py                        |   6 +-
 scripts/qapi/visit.py                         |   5 +-
 tests/qapi-schema/doc-empty-section.err       |   2 +-
 tests/qapi-schema/doc-empty-section.json      |   2 +-
 tests/qapi-schema/doc-good.json               |  28 +-
 tests/qapi-schema/doc-good.out                |  61 +++--
 tests/qapi-schema/doc-good.txt                |  36 ++-
 .../qapi-schema/doc-interleaved-section.json  |   2 +-
 44 files changed, 1010 insertions(+), 664 deletions(-)
 create mode 100755 scripts/qapi-lint.sh
 create mode 100644 scripts/qapi/Makefile

-- 
2.45.0




^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH v2 01/21] [DO-NOT-MERGE]: Add some ad-hoc linting helpers.
  2024-06-26 22:21 [PATCH v2 00/21] qapi: convert "Note" and "Example" sections to rST John Snow
@ 2024-06-26 22:21 ` John Snow
  2024-06-26 22:21 ` [PATCH v2 02/21] qapi: linter fixups John Snow
                   ` (19 subsequent siblings)
  20 siblings, 0 replies; 44+ messages in thread
From: John Snow @ 2024-06-26 22:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Markus Armbruster, Philippe Mathieu-Daudé, Lukas Straub,
	Igor Mammedov, Jason Wang, Yanan Wang, Hanna Reitz,
	Konstantin Kostiuk, Stefan Berger, John Snow

These aren't ready for upstream inclusion, because they do not properly
manage version dependencies, execution environment and so on. These are
just the tools I use in my Own Special Environment :tm: for testing and
debugging.

They've been tested only on Fedora 38 for right now, which means:

Python 3.11.4-1.fc38
pylint 2.17.4-2.fc38
mypy 1.4.0-1.fc38
isort 5.12.0-1.fc38
flake8 5.0.3-2.fc38

"Soon" :tm: I'll move the qapi generator code under the python/
directory to take advantage of the more robust linting infrastructure
there, but that's going to happen after this series. Sorry about that!

Signed-off-by: John Snow <jsnow@redhat.com>
---
 scripts/qapi-lint.sh  | 61 +++++++++++++++++++++++++++++++++++++++++++
 scripts/qapi/Makefile |  5 ++++
 2 files changed, 66 insertions(+)
 create mode 100755 scripts/qapi-lint.sh
 create mode 100644 scripts/qapi/Makefile

diff --git a/scripts/qapi-lint.sh b/scripts/qapi-lint.sh
new file mode 100755
index 00000000000..732716f2444
--- /dev/null
+++ b/scripts/qapi-lint.sh
@@ -0,0 +1,61 @@
+#!/usr/bin/env bash
+set -e
+
+if [[ -f qapi/.flake8 ]]; then
+    echo "flake8 --config=qapi/.flake8 qapi/"
+    flake8 --config=qapi/.flake8 qapi/
+fi
+if [[ -f qapi/pylintrc ]]; then
+    echo "pylint --rcfile=qapi/pylintrc qapi/"
+    pylint --rcfile=qapi/pylintrc qapi/
+fi
+if [[ -f qapi/mypy.ini ]]; then
+    echo "mypy --config-file=qapi/mypy.ini qapi/"
+    mypy --config-file=qapi/mypy.ini qapi/
+fi
+
+if [[ -f qapi/.isort.cfg ]]; then
+    pushd qapi
+    echo "isort -c ."
+    isort -c .
+    popd
+fi
+
+if [[ -f ../docs/sphinx/qapi-domain.py ]]; then
+    pushd ../docs/sphinx
+
+    echo "mypy --strict qapi-domain.py"
+    mypy --strict qapi-domain.py
+    echo "flake8 qapi-domain.py --max-line-length=99"
+    flake8 qapi-domain.py --max-line-length=99
+    echo "isort qapi-domain.py"
+    isort qapi-domain.py
+    echo "black --check qapi-domain.py"
+    black --check qapi-domain.py
+
+    popd
+fi
+
+if [[ -f ../docs/sphinx/qapidoc.py ]]; then
+    pushd ../docs/sphinx
+
+    echo "pylint --rc-file ../../scripts/qapi/pylintrc qapidoc.py"
+    PYTHONPATH=../scripts/ pylint \
+                         --rc-file ../../scripts/qapi/pylintrc \
+                         qapidoc.py
+    echo "flake8 qapidoc.py --max-line-length=80"
+    flake8 qapidoc.py --max-line-length=80
+    echo "isort qapidoc.py"
+    isort qapidoc.py
+    echo "black --line-length 80 --check qapidoc.py"
+    black --line-length 80 --check qapidoc.py
+
+    popd
+fi
+
+pushd ../build
+make -j13
+make check-qapi-schema
+make docs
+make sphinxdocs
+popd
diff --git a/scripts/qapi/Makefile b/scripts/qapi/Makefile
new file mode 100644
index 00000000000..314e8a5505e
--- /dev/null
+++ b/scripts/qapi/Makefile
@@ -0,0 +1,5 @@
+check:
+	isort -c .
+	flake8 .
+	cd .. && pylint --rcfile=qapi/pylintrc qapi
+	cd .. && mypy -p qapi --config-file=qapi/mypy.ini
-- 
2.45.0



^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v2 02/21] qapi: linter fixups
  2024-06-26 22:21 [PATCH v2 00/21] qapi: convert "Note" and "Example" sections to rST John Snow
  2024-06-26 22:21 ` [PATCH v2 01/21] [DO-NOT-MERGE]: Add some ad-hoc linting helpers John Snow
@ 2024-06-26 22:21 ` John Snow
  2024-06-26 22:21 ` [PATCH v2 03/21] docs/qapidoc: remove unused intersperse function John Snow
                   ` (18 subsequent siblings)
  20 siblings, 0 replies; 44+ messages in thread
From: John Snow @ 2024-06-26 22:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Markus Armbruster, Philippe Mathieu-Daudé, Lukas Straub,
	Igor Mammedov, Jason Wang, Yanan Wang, Hanna Reitz,
	Konstantin Kostiuk, Stefan Berger, John Snow

Fix minor irritants to pylint/flake8 et al.

(Yes, these need to be guarded by the Python tests. That's a work in
progress, a series that's quite likely to follow once I finish this
Sphinx project. Please pardon the temporary irritation.)

Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
---
 scripts/qapi/introspect.py | 8 ++++----
 scripts/qapi/schema.py     | 6 +++---
 scripts/qapi/visit.py      | 5 +++--
 3 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py
index 86c075a6ad2..ac14b20f308 100644
--- a/scripts/qapi/introspect.py
+++ b/scripts/qapi/introspect.py
@@ -27,8 +27,8 @@
 from .schema import (
     QAPISchema,
     QAPISchemaAlternatives,
-    QAPISchemaBranches,
     QAPISchemaArrayType,
+    QAPISchemaBranches,
     QAPISchemaBuiltinType,
     QAPISchemaEntity,
     QAPISchemaEnumMember,
@@ -233,9 +233,9 @@ def _use_type(self, typ: QAPISchemaType) -> str:
             typ = type_int
         elif (isinstance(typ, QAPISchemaArrayType) and
               typ.element_type.json_type() == 'int'):
-            type_intList = self._schema.lookup_type('intList')
-            assert type_intList
-            typ = type_intList
+            type_intlist = self._schema.lookup_type('intList')
+            assert type_intlist
+            typ = type_intlist
         # Add type to work queue if new
         if typ not in self._used_types:
             self._used_types.append(typ)
diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
index 721c470d2b8..d65c35f6ee6 100644
--- a/scripts/qapi/schema.py
+++ b/scripts/qapi/schema.py
@@ -730,6 +730,7 @@ def set_defined_in(self, name: str) -> None:
         for v in self.variants:
             v.set_defined_in(name)
 
+    # pylint: disable=unused-argument
     def check(
             self, schema: QAPISchema, seen: Dict[str, QAPISchemaMember]
     ) -> None:
@@ -1166,7 +1167,7 @@ def _def_definition(self, defn: QAPISchemaDefinition) -> None:
                 defn.info, "%s is already defined" % other_defn.describe())
         self._entity_dict[defn.name] = defn
 
-    def lookup_entity(self,name: str) -> Optional[QAPISchemaEntity]:
+    def lookup_entity(self, name: str) -> Optional[QAPISchemaEntity]:
         return self._entity_dict.get(name)
 
     def lookup_type(self, name: str) -> Optional[QAPISchemaType]:
@@ -1302,11 +1303,10 @@ def _make_implicit_object_type(
         name = 'q_obj_%s-%s' % (name, role)
         typ = self.lookup_entity(name)
         if typ:
-            assert(isinstance(typ, QAPISchemaObjectType))
+            assert isinstance(typ, QAPISchemaObjectType)
             # The implicit object type has multiple users.  This can
             # only be a duplicate definition, which will be flagged
             # later.
-            pass
         else:
             self._def_definition(QAPISchemaObjectType(
                 name, info, None, ifcond, None, None, members, None))
diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
index e766acaac92..12f92e429f6 100644
--- a/scripts/qapi/visit.py
+++ b/scripts/qapi/visit.py
@@ -280,8 +280,9 @@ def gen_visit_alternate(name: str,
         abort();
     default:
         assert(visit_is_input(v));
-        error_setg(errp, "Invalid parameter type for '%%s', expected: %(name)s",
-                         name ? name : "null");
+        error_setg(errp,
+                   "Invalid parameter type for '%%s', expected: %(name)s",
+                   name ? name : "null");
         /* Avoid passing invalid *obj to qapi_free_%(c_name)s() */
         g_free(*obj);
         *obj = NULL;
-- 
2.45.0



^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v2 03/21] docs/qapidoc: remove unused intersperse function
  2024-06-26 22:21 [PATCH v2 00/21] qapi: convert "Note" and "Example" sections to rST John Snow
  2024-06-26 22:21 ` [PATCH v2 01/21] [DO-NOT-MERGE]: Add some ad-hoc linting helpers John Snow
  2024-06-26 22:21 ` [PATCH v2 02/21] qapi: linter fixups John Snow
@ 2024-06-26 22:21 ` John Snow
  2024-06-27  6:02   ` Markus Armbruster
  2024-06-27 10:43   ` Markus Armbruster
  2024-06-26 22:21 ` [PATCH v2 04/21] docs/qapidoc: delint a tiny portion of the module John Snow
                   ` (17 subsequent siblings)
  20 siblings, 2 replies; 44+ messages in thread
From: John Snow @ 2024-06-26 22:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Markus Armbruster, Philippe Mathieu-Daudé, Lukas Straub,
	Igor Mammedov, Jason Wang, Yanan Wang, Hanna Reitz,
	Konstantin Kostiuk, Stefan Berger, John Snow

This function has been unused since fd62bff901b.

Signed-off-by: John Snow <jsnow@redhat.com>
---
 docs/sphinx/qapidoc.py | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py
index f270b494f01..3c0565d0ceb 100644
--- a/docs/sphinx/qapidoc.py
+++ b/docs/sphinx/qapidoc.py
@@ -50,16 +50,6 @@
 __version__ = '1.0'
 
 
-# Function borrowed from pydash, which is under the MIT license
-def intersperse(iterable, separator):
-    """Yield the members of *iterable* interspersed with *separator*."""
-    iterable = iter(iterable)
-    yield next(iterable)
-    for item in iterable:
-        yield separator
-        yield item
-
-
 class QAPISchemaGenRSTVisitor(QAPISchemaVisitor):
     """A QAPI schema visitor which generates docutils/Sphinx nodes
 
-- 
2.45.0



^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v2 04/21] docs/qapidoc: delint a tiny portion of the module
  2024-06-26 22:21 [PATCH v2 00/21] qapi: convert "Note" and "Example" sections to rST John Snow
                   ` (2 preceding siblings ...)
  2024-06-26 22:21 ` [PATCH v2 03/21] docs/qapidoc: remove unused intersperse function John Snow
@ 2024-06-26 22:21 ` John Snow
  2024-06-28  7:29   ` Markus Armbruster
  2024-06-26 22:21 ` [PATCH v2 05/21] qapi/parser: preserve indentation in QAPIDoc sections John Snow
                   ` (16 subsequent siblings)
  20 siblings, 1 reply; 44+ messages in thread
From: John Snow @ 2024-06-26 22:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Markus Armbruster, Philippe Mathieu-Daudé, Lukas Straub,
	Igor Mammedov, Jason Wang, Yanan Wang, Hanna Reitz,
	Konstantin Kostiuk, Stefan Berger, John Snow

In a forthcoming series that adds a new QMP documentation generator, it
will be helpful to have a linting baseline. However, there's no need to
shuffle around the deck chairs too much, because most of this code will
be removed once that new qapidoc generator (the "transmogrifier") is in
place.

To ease my pain: just turn off the black auto-formatter for most, but
not all, of qapidoc.py. This will help ensure that *new* code follows a
coding standard without bothering too much with cleaning up the existing
code.

Code that I intend to keep is still subject to the delinting beam.

Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
---
 docs/sphinx/qapidoc.py | 62 +++++++++++++++++++++++++-----------------
 1 file changed, 37 insertions(+), 25 deletions(-)

diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py
index 3c0565d0ceb..659e507353a 100644
--- a/docs/sphinx/qapidoc.py
+++ b/docs/sphinx/qapidoc.py
@@ -28,26 +28,33 @@
 import re
 
 from docutils import nodes
+from docutils.parsers.rst import Directive, directives
 from docutils.statemachine import ViewList
-from docutils.parsers.rst import directives, Directive
-from sphinx.errors import ExtensionError
-from sphinx.util.nodes import nested_parse_with_titles
-import sphinx
-from qapi.gen import QAPISchemaVisitor
 from qapi.error import QAPIError, QAPISemError
+from qapi.gen import QAPISchemaVisitor
 from qapi.schema import QAPISchema
 
+import sphinx
+from sphinx.errors import ExtensionError
+from sphinx.util.nodes import nested_parse_with_titles
+
 
 # Sphinx up to 1.6 uses AutodocReporter; 1.7 and later
 # use switch_source_input. Check borrowed from kerneldoc.py.
-Use_SSI = sphinx.__version__[:3] >= '1.7'
-if Use_SSI:
+USE_SSI = sphinx.__version__[:3] >= "1.7"
+if USE_SSI:
     from sphinx.util.docutils import switch_source_input
 else:
-    from sphinx.ext.autodoc import AutodocReporter
+    from sphinx.ext.autodoc import (  # pylint: disable=no-name-in-module
+        AutodocReporter,
+    )
 
 
-__version__ = '1.0'
+__version__ = "1.0"
+
+
+# Disable black auto-formatter until re-enabled:
+# fmt: off
 
 
 class QAPISchemaGenRSTVisitor(QAPISchemaVisitor):
@@ -441,6 +448,10 @@ def get_document_nodes(self):
         return self._top_node.children
 
 
+# Turn the black formatter on for the rest of the file.
+# fmt: on
+
+
 class QAPISchemaGenDepVisitor(QAPISchemaVisitor):
     """A QAPI schema visitor which adds Sphinx dependencies each module
 
@@ -448,34 +459,34 @@ class QAPISchemaGenDepVisitor(QAPISchemaVisitor):
     that the generated documentation output depends on the input
     schema file associated with each module in the QAPI input.
     """
+
     def __init__(self, env, qapidir):
         self._env = env
         self._qapidir = qapidir
 
     def visit_module(self, name):
         if name != "./builtin":
-            qapifile = self._qapidir + '/' + name
+            qapifile = self._qapidir + "/" + name
             self._env.note_dependency(os.path.abspath(qapifile))
         super().visit_module(name)
 
 
 class QAPIDocDirective(Directive):
     """Extract documentation from the specified QAPI .json file"""
+
     required_argument = 1
     optional_arguments = 1
-    option_spec = {
-        'qapifile': directives.unchanged_required
-    }
+    option_spec = {"qapifile": directives.unchanged_required}
     has_content = False
 
     def new_serialno(self):
         """Return a unique new ID string suitable for use as a node's ID"""
         env = self.state.document.settings.env
-        return 'qapidoc-%d' % env.new_serialno('qapidoc')
+        return "qapidoc-%d" % env.new_serialno("qapidoc")
 
     def run(self):
         env = self.state.document.settings.env
-        qapifile = env.config.qapidoc_srctree + '/' + self.arguments[0]
+        qapifile = env.config.qapidoc_srctree + "/" + self.arguments[0]
         qapidir = os.path.dirname(qapifile)
 
         try:
@@ -513,13 +524,14 @@ def do_parse(self, rstlist, node):
         # plain self.state.nested_parse(), and so we can drop the saving
         # of title_styles and section_level that kerneldoc.py does,
         # because nested_parse_with_titles() does that for us.
-        if Use_SSI:
+        if USE_SSI:
             with switch_source_input(self.state, rstlist):
                 nested_parse_with_titles(self.state, rstlist, node)
         else:
             save = self.state.memo.reporter
             self.state.memo.reporter = AutodocReporter(
-                rstlist, self.state.memo.reporter)
+                rstlist, self.state.memo.reporter
+            )
             try:
                 nested_parse_with_titles(self.state, rstlist, node)
             finally:
@@ -527,12 +539,12 @@ def do_parse(self, rstlist, node):
 
 
 def setup(app):
-    """ Register qapi-doc directive with Sphinx"""
-    app.add_config_value('qapidoc_srctree', None, 'env')
-    app.add_directive('qapi-doc', QAPIDocDirective)
+    """Register qapi-doc directive with Sphinx"""
+    app.add_config_value("qapidoc_srctree", None, "env")
+    app.add_directive("qapi-doc", QAPIDocDirective)
 
-    return dict(
-        version=__version__,
-        parallel_read_safe=True,
-        parallel_write_safe=True
-    )
+    return {
+        "version": __version__,
+        "parallel_read_safe": True,
+        "parallel_write_safe": True,
+    }
-- 
2.45.0



^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v2 05/21] qapi/parser: preserve indentation in QAPIDoc sections
  2024-06-26 22:21 [PATCH v2 00/21] qapi: convert "Note" and "Example" sections to rST John Snow
                   ` (3 preceding siblings ...)
  2024-06-26 22:21 ` [PATCH v2 04/21] docs/qapidoc: delint a tiny portion of the module John Snow
@ 2024-06-26 22:21 ` John Snow
  2024-06-27  6:25   ` Markus Armbruster
  2024-06-27 10:43   ` Markus Armbruster
  2024-06-26 22:21 ` [PATCH v2 06/21] qapi/parser: fix comment parsing immediately following a doc block John Snow
                   ` (15 subsequent siblings)
  20 siblings, 2 replies; 44+ messages in thread
From: John Snow @ 2024-06-26 22:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Markus Armbruster, Philippe Mathieu-Daudé, Lukas Straub,
	Igor Mammedov, Jason Wang, Yanan Wang, Hanna Reitz,
	Konstantin Kostiuk, Stefan Berger, John Snow

Change get_doc_indented() to preserve indentation on all subsequent text
lines, and create a compatibility dedent() function for qapidoc.py that
removes indentation the same way get_doc_indented() did.

This is being done for the benefit of a new qapidoc generator which
requires that indentation in argument and features sections are
preserved.

Prior to this patch, a section like this:

```
@name: lorem ipsum
   dolor sit amet
     consectetur adipiscing elit
```

would have its body text be parsed into:

```
lorem ipsum
dolor sit amet
  consectetur adipiscing elit
```

We want to preserve the indentation for even the first body line so that
the entire block can be parsed directly as rST. This patch would now
parse that segment into:

```
lorem ipsum
   dolor sit amet
     consectetur adipiscing elit
```

This is helpful for formatting arguments and features as field lists in
rST, where the new generator will format this information as:

```
:arg type name: lorem ipsum
   dolor sit amet
     consectetur apidiscing elit
```

...and can be formed by the simple concatenation of the field list
construct and the body text. The indents help preserve the continuation
of a block-level element, and further allow the use of additional rST
block-level constructs such as code blocks, lists, and other such
markup.

This understandably breaks the existing qapidoc.py; so a new function is
added there to dedent the text for compatibility. Once the new generator
is merged, this function will not be needed any longer and can be
dropped.

Signed-off-by: John Snow <jsnow@redhat.com>
[Edited commit message and code comments per review --js]
Reviewed-by: Markus Armbruster <armbru@redhat.com>
---
 docs/sphinx/qapidoc.py         | 27 ++++++++++++++++++++++-----
 scripts/qapi/parser.py         |  4 ++--
 tests/qapi-schema/doc-good.out | 32 ++++++++++++++++----------------
 3 files changed, 40 insertions(+), 23 deletions(-)

diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py
index 659e507353a..f9683444b14 100644
--- a/docs/sphinx/qapidoc.py
+++ b/docs/sphinx/qapidoc.py
@@ -26,6 +26,7 @@
 
 import os
 import re
+import textwrap
 
 from docutils import nodes
 from docutils.parsers.rst import Directive, directives
@@ -53,6 +54,19 @@
 __version__ = "1.0"
 
 
+def dedent(text: str) -> str:
+    # Adjust indentation to make description text parse as paragraph.
+
+    lines = text.splitlines(True)
+    if re.match(r"\s+", lines[0]):
+        # First line is indented; description started on the line after
+        # the name. dedent the whole block.
+        return textwrap.dedent(text)
+
+    # Descr started on same line. Dedent line 2+.
+    return lines[0] + textwrap.dedent("".join(lines[1:]))
+
+
 # Disable black auto-formatter until re-enabled:
 # fmt: off
 
@@ -164,7 +178,7 @@ def _nodes_for_members(self, doc, what, base=None, branches=None):
             term = self._nodes_for_one_member(section.member)
             # TODO drop fallbacks when undocumented members are outlawed
             if section.text:
-                defn = section.text
+                defn = dedent(section.text)
             else:
                 defn = [nodes.Text('Not documented')]
 
@@ -202,7 +216,7 @@ def _nodes_for_enum_values(self, doc):
                 termtext.extend(self._nodes_for_ifcond(section.member.ifcond))
             # TODO drop fallbacks when undocumented members are outlawed
             if section.text:
-                defn = section.text
+                defn = dedent(section.text)
             else:
                 defn = [nodes.Text('Not documented')]
 
@@ -237,7 +251,7 @@ def _nodes_for_features(self, doc):
         dlnode = nodes.definition_list()
         for section in doc.features.values():
             dlnode += self._make_dlitem(
-                [nodes.literal('', section.member.name)], section.text)
+                [nodes.literal('', section.member.name)], dedent(section.text))
             seen_item = True
 
         if not seen_item:
@@ -260,9 +274,12 @@ def _nodes_for_sections(self, doc):
                 continue
             snode = self._make_section(section.tag)
             if section.tag and section.tag.startswith('Example'):
-                snode += self._nodes_for_example(section.text)
+                snode += self._nodes_for_example(dedent(section.text))
             else:
-                self._parse_text_into_node(section.text, snode)
+                self._parse_text_into_node(
+                    dedent(section.text) if section.tag else section.text,
+                    snode,
+                )
             nodelist.append(snode)
         return nodelist
 
diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py
index 7b13a583ac1..1ef1f85b028 100644
--- a/scripts/qapi/parser.py
+++ b/scripts/qapi/parser.py
@@ -448,7 +448,7 @@ def get_doc_indented(self, doc: 'QAPIDoc') -> Optional[str]:
         indent = must_match(r'\s*', line).end()
         if not indent:
             return line
-        doc.append_line(line[indent:])
+        doc.append_line(line)
         prev_line_blank = False
         while True:
             self.accept(False)
@@ -465,7 +465,7 @@ def get_doc_indented(self, doc: 'QAPIDoc') -> Optional[str]:
                     self,
                     "unexpected de-indent (expected at least %d spaces)" %
                     indent)
-            doc.append_line(line[indent:])
+            doc.append_line(line)
             prev_line_blank = True
 
     def get_doc_paragraph(self, doc: 'QAPIDoc') -> Optional[str]:
diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out
index 716a9a41026..435f6e6d768 100644
--- a/tests/qapi-schema/doc-good.out
+++ b/tests/qapi-schema/doc-good.out
@@ -117,8 +117,8 @@ doc symbol=Base
     body=
 
     arg=base1
-description starts on a new line,
-minimally indented
+ description starts on a new line,
+ minimally indented
 doc symbol=Variant1
     body=
 A paragraph
@@ -145,8 +145,8 @@ doc symbol=Alternate
 
     arg=i
 description starts on the same line
-remainder indented the same
-@b is undocumented
+    remainder indented the same
+    @b is undocumented
     arg=b
 
     feature=alt-feat
@@ -158,11 +158,11 @@ doc symbol=cmd
     body=
 
     arg=arg1
-description starts on a new line,
-indented
+    description starts on a new line,
+    indented
     arg=arg2
 description starts on the same line
-remainder indented differently
+    remainder indented differently
     arg=arg3
 
     feature=cmd-feat1
@@ -178,16 +178,16 @@ some
     section=TODO
 frobnicate
     section=Notes
-- Lorem ipsum dolor sit amet
-- Ut enim ad minim veniam
+ - Lorem ipsum dolor sit amet
+ - Ut enim ad minim veniam
 
-Duis aute irure dolor
+ Duis aute irure dolor
     section=Example
--> in
-<- out
+ -> in
+ <- out
     section=Examples
-- *verbatim*
-- {braces}
+ - *verbatim*
+ - {braces}
     section=Since
 2.10
 doc symbol=cmd-boxed
@@ -198,9 +198,9 @@ a feature
     feature=cmd-feat2
 another feature
     section=Example
--> in
+ -> in
 
-<- out
+ <- out
 doc symbol=EVT_BOXED
     body=
 
-- 
2.45.0



^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v2 06/21] qapi/parser: fix comment parsing immediately following a doc block
  2024-06-26 22:21 [PATCH v2 00/21] qapi: convert "Note" and "Example" sections to rST John Snow
                   ` (4 preceding siblings ...)
  2024-06-26 22:21 ` [PATCH v2 05/21] qapi/parser: preserve indentation in QAPIDoc sections John Snow
@ 2024-06-26 22:21 ` John Snow
  2024-06-26 22:21 ` [PATCH v2 07/21] docs/qapidoc: fix nested parsing under untagged sections John Snow
                   ` (14 subsequent siblings)
  20 siblings, 0 replies; 44+ messages in thread
From: John Snow @ 2024-06-26 22:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Markus Armbruster, Philippe Mathieu-Daudé, Lukas Straub,
	Igor Mammedov, Jason Wang, Yanan Wang, Hanna Reitz,
	Konstantin Kostiuk, Stefan Berger, John Snow

If a comment immediately follows a doc block, the parser doesn't ignore
that token appropriately. Fix that.

e.g.

> ##
> # = Hello World!
> ##
>
> # I'm a comment!

will break the parser, because it does not properly ignore the comment
token if it immediately follows a doc block.

Fixes: 3d035cd2cca6 (qapi: Rewrite doc comment parser)
Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
---
 scripts/qapi/parser.py          | 2 +-
 tests/qapi-schema/doc-good.json | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py
index 1ef1f85b028..c3d20cc01bc 100644
--- a/scripts/qapi/parser.py
+++ b/scripts/qapi/parser.py
@@ -583,7 +583,7 @@ def get_doc(self) -> 'QAPIDoc':
                 line = self.get_doc_line()
                 first = False
 
-        self.accept(False)
+        self.accept()
         doc.end()
         return doc
 
diff --git a/tests/qapi-schema/doc-good.json b/tests/qapi-schema/doc-good.json
index de38a386e8f..8b39eb946af 100644
--- a/tests/qapi-schema/doc-good.json
+++ b/tests/qapi-schema/doc-good.json
@@ -55,6 +55,8 @@
 # - {braces}
 ##
 
+# Not a doc comment
+
 ##
 # @Enum:
 #
-- 
2.45.0



^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v2 07/21] docs/qapidoc: fix nested parsing under untagged sections
  2024-06-26 22:21 [PATCH v2 00/21] qapi: convert "Note" and "Example" sections to rST John Snow
                   ` (5 preceding siblings ...)
  2024-06-26 22:21 ` [PATCH v2 06/21] qapi/parser: fix comment parsing immediately following a doc block John Snow
@ 2024-06-26 22:21 ` John Snow
  2024-06-28  7:54   ` Markus Armbruster
  2024-06-26 22:21 ` [PATCH v2 08/21] qapi: fix non-compliant JSON examples John Snow
                   ` (13 subsequent siblings)
  20 siblings, 1 reply; 44+ messages in thread
From: John Snow @ 2024-06-26 22:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Markus Armbruster, Philippe Mathieu-Daudé, Lukas Straub,
	Igor Mammedov, Jason Wang, Yanan Wang, Hanna Reitz,
	Konstantin Kostiuk, Stefan Berger, John Snow

Sphinx does not like sections without titles, because it wants to
convert every section into a reference. When there is no title, it
struggles to do this and transforms the tree inproperly.

Depending on the rST used, this may result in an assertion error deep in
the docutils HTMLWriter.

(Observed when using ".. admonition:: Notes" under such a section - When
this is transformed with its own <title> element, Sphinx is fooled into
believing this title belongs to the section and incorrect mutates the
docutils tree, leading to errors during rendering time.)

When parsing an untagged section (free paragraphs), skip making a hollow
section and instead append the parse results to the prior section.

Many Bothans died to bring us this information.

Signed-off-by: John Snow <jsnow@redhat.com>
Acked-by: Markus Armbruster <armbru@redhat.com>
---
 docs/sphinx/qapidoc.py | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py
index f9683444b14..efcd84656fa 100644
--- a/docs/sphinx/qapidoc.py
+++ b/docs/sphinx/qapidoc.py
@@ -272,14 +272,20 @@ def _nodes_for_sections(self, doc):
             if section.tag and section.tag == 'TODO':
                 # Hide TODO: sections
                 continue
+
+            if not section.tag:
+                # Sphinx cannot handle sectionless titles;
+                # Instead, just append the results to the prior section.
+                container = nodes.container()
+                self._parse_text_into_node(section.text, container)
+                nodelist += container.children
+                continue
+
             snode = self._make_section(section.tag)
-            if section.tag and section.tag.startswith('Example'):
+            if section.tag.startswith('Example'):
                 snode += self._nodes_for_example(dedent(section.text))
             else:
-                self._parse_text_into_node(
-                    dedent(section.text) if section.tag else section.text,
-                    snode,
-                )
+                self._parse_text_into_node(dedent(section.text), snode)
             nodelist.append(snode)
         return nodelist
 
-- 
2.45.0



^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v2 08/21] qapi: fix non-compliant JSON examples
  2024-06-26 22:21 [PATCH v2 00/21] qapi: convert "Note" and "Example" sections to rST John Snow
                   ` (6 preceding siblings ...)
  2024-06-26 22:21 ` [PATCH v2 07/21] docs/qapidoc: fix nested parsing under untagged sections John Snow
@ 2024-06-26 22:21 ` John Snow
  2024-06-26 22:21 ` [PATCH v2 09/21] qapi: nail down convention that Errors sections are lists John Snow
                   ` (12 subsequent siblings)
  20 siblings, 0 replies; 44+ messages in thread
From: John Snow @ 2024-06-26 22:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Markus Armbruster, Philippe Mathieu-Daudé, Lukas Straub,
	Igor Mammedov, Jason Wang, Yanan Wang, Hanna Reitz,
	Konstantin Kostiuk, Stefan Berger, John Snow

The new QMP documentation generator wants to parse all examples as
"QMP". We have an existing QMP lexer in docs/sphinx/qmp_lexer.py (Seen
in-use here: https://qemu-project.gitlab.io/qemu/interop/bitmaps.html)
that allows the use of "->", "<-" and "..." tokens to denote QMP
protocol flow with elisions, but otherwise defers to the JSON lexer.

To utilize this lexer for the existing QAPI documentation, we need them
to conform to a standard so that they lex and render correctly. Once the
QMP lexer is active for examples, errant QMP/JSON will produce warning
messages and fail the build.

Fix any invalid JSON found in QAPI documentation (identified by
attempting to lex all examples as QMP; see subsequent
commits). Additionally, elisions must be standardized for the QMP lexer;
they must be represented as the value "...", so three examples have been
adjusted to support that format here.

Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
---
 qapi/control.json   | 3 ++-
 qapi/machine.json   | 2 +-
 qapi/migration.json | 2 +-
 qapi/misc.json      | 3 ++-
 qapi/net.json       | 6 +++---
 qapi/rocker.json    | 2 +-
 qapi/ui.json        | 2 +-
 7 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/qapi/control.json b/qapi/control.json
index 6bdbf077c2e..10c906fa0e7 100644
--- a/qapi/control.json
+++ b/qapi/control.json
@@ -145,7 +145,8 @@
 #             },
 #             {
 #                "name":"system_powerdown"
-#             }
+#             },
+#             ...
 #          ]
 #        }
 #
diff --git a/qapi/machine.json b/qapi/machine.json
index 2fd3e9c3d5d..a982c945035 100644
--- a/qapi/machine.json
+++ b/qapi/machine.json
@@ -1057,7 +1057,7 @@
 #            "vcpus-count": 1 },
 #          { "props": { "core-id": 0 }, "type": "POWER8-spapr-cpu-core",
 #            "vcpus-count": 1, "qom-path": "/machine/unattached/device[0]"}
-#        ]}'
+#        ]}
 #
 #     For pc machine type started with -smp 1,maxcpus=2:
 #
diff --git a/qapi/migration.json b/qapi/migration.json
index 0f24206bce4..9ec9ef36c47 100644
--- a/qapi/migration.json
+++ b/qapi/migration.json
@@ -2106,7 +2106,7 @@
 # Example:
 #
 #     -> {"execute": "calc-dirty-rate", "arguments": {"calc-time": 1,
-#                                                     'sample-pages': 512} }
+#                                                     "sample-pages": 512} }
 #     <- { "return": {} }
 #
 #     Measure dirty rate using dirty bitmap for 500 milliseconds:
diff --git a/qapi/misc.json b/qapi/misc.json
index ec30e5c570a..4b41e15dcd4 100644
--- a/qapi/misc.json
+++ b/qapi/misc.json
@@ -287,7 +287,8 @@
 #
 # Example:
 #
-#     -> { "execute": "get-win32-socket", "arguments": { "info": "abcd123..", fdname": "skclient" } }
+#     -> { "execute": "get-win32-socket",
+#          "arguments": { "info": "abcd123..", "fdname": "skclient" } }
 #     <- { "return": {} }
 ##
 { 'command': 'get-win32-socket', 'data': {'info': 'str', 'fdname': 'str'}, 'if': 'CONFIG_WIN32' }
diff --git a/qapi/net.json b/qapi/net.json
index 0f5a259475e..c19df435a53 100644
--- a/qapi/net.json
+++ b/qapi/net.json
@@ -1003,9 +1003,9 @@
 #
 # Example:
 #
-#     <- { 'event': 'NETDEV_STREAM_DISCONNECTED',
-#          'data': {'netdev-id': 'netdev0'},
-#          'timestamp': {'seconds': 1663330937, 'microseconds': 526695} }
+#     <- { "event": "NETDEV_STREAM_DISCONNECTED",
+#          "data": {"netdev-id": "netdev0"},
+#          "timestamp": {"seconds": 1663330937, "microseconds": 526695} }
 ##
 { 'event': 'NETDEV_STREAM_DISCONNECTED',
   'data': { 'netdev-id': 'str' } }
diff --git a/qapi/rocker.json b/qapi/rocker.json
index 5635cf174fd..f5225eb62cc 100644
--- a/qapi/rocker.json
+++ b/qapi/rocker.json
@@ -250,7 +250,7 @@
 #                       "action": {"goto-tbl": 10},
 #                       "mask": {"in-pport": 4294901760}
 #                      },
-#                      {...more...},
+#                      {...},
 #        ]}
 ##
 { 'command': 'query-rocker-of-dpa-flows',
diff --git a/qapi/ui.json b/qapi/ui.json
index f610bce118a..c12f5292571 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -361,7 +361,7 @@
 #                    "channel-id": 0,
 #                    "tls": false
 #                 },
-#                 [ ... more channels follow ... ]
+#                 ...
 #              ]
 #           }
 #        }
-- 
2.45.0



^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v2 09/21] qapi: nail down convention that Errors sections are lists
  2024-06-26 22:21 [PATCH v2 00/21] qapi: convert "Note" and "Example" sections to rST John Snow
                   ` (7 preceding siblings ...)
  2024-06-26 22:21 ` [PATCH v2 08/21] qapi: fix non-compliant JSON examples John Snow
@ 2024-06-26 22:21 ` John Snow
  2024-06-26 22:21 ` [PATCH v2 10/21] qapi: convert "Note" sections to plain rST John Snow
                   ` (11 subsequent siblings)
  20 siblings, 0 replies; 44+ messages in thread
From: John Snow @ 2024-06-26 22:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Markus Armbruster, Philippe Mathieu-Daudé, Lukas Straub,
	Igor Mammedov, Jason Wang, Yanan Wang, Hanna Reitz,
	Konstantin Kostiuk, Stefan Berger, John Snow

By unstated convention, Errors sections are rST lists.  Document the
convention, and make the one exception conform.

Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
---
 docs/devel/qapi-code-gen.rst | 7 +++++++
 qapi/transaction.json        | 2 +-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/docs/devel/qapi-code-gen.rst b/docs/devel/qapi-code-gen.rst
index f453bd35465..cee43222f19 100644
--- a/docs/devel/qapi-code-gen.rst
+++ b/docs/devel/qapi-code-gen.rst
@@ -1011,6 +1011,13 @@ like this::
 "Returns" and "Errors" sections are only valid for commands.  They
 document the success and the error response, respectively.
 
+"Errors" sections should be formatted as an rST list, each entry
+detailing a relevant error condition. For example::
+
+ # Errors:
+ #     - If @device does not exist, DeviceNotFound
+ #     - Any other error returns a GenericError.
+
 A "Since: x.y.z" tagged section lists the release that introduced the
 definition.
 
diff --git a/qapi/transaction.json b/qapi/transaction.json
index 5749c133d4a..07afc269d54 100644
--- a/qapi/transaction.json
+++ b/qapi/transaction.json
@@ -235,7 +235,7 @@
 #     additional detail.
 #
 # Errors:
-#     Any errors from commands in the transaction
+#     - Any errors from commands in the transaction
 #
 # Note: The transaction aborts on the first failure.  Therefore, there
 #     will be information on only one failed operation returned in an
-- 
2.45.0



^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v2 10/21] qapi: convert "Note" sections to plain rST
  2024-06-26 22:21 [PATCH v2 00/21] qapi: convert "Note" and "Example" sections to rST John Snow
                   ` (8 preceding siblings ...)
  2024-06-26 22:21 ` [PATCH v2 09/21] qapi: nail down convention that Errors sections are lists John Snow
@ 2024-06-26 22:21 ` John Snow
  2024-06-28  9:51   ` Markus Armbruster
  2024-07-01 15:08   ` Markus Armbruster
  2024-06-26 22:21 ` [PATCH v2 11/21] qapi: update prose in note blocks John Snow
                   ` (10 subsequent siblings)
  20 siblings, 2 replies; 44+ messages in thread
From: John Snow @ 2024-06-26 22:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Markus Armbruster, Philippe Mathieu-Daudé, Lukas Straub,
	Igor Mammedov, Jason Wang, Yanan Wang, Hanna Reitz,
	Konstantin Kostiuk, Stefan Berger, John Snow

We do not need a dedicated section for notes. By eliminating a specially
parsed section, these notes can be treated as normal rST paragraphs in
the new QMP reference manual, and can be placed and styled much more
flexibly.

Convert all existing "Note" and "Notes" sections to pure rST. As part of
the conversion, capitalize the first letter of each sentence and add
trailing punctuation where appropriate to ensure notes look sensible and
consistent in rendered HTML documentation. Markup is also re-aligned to
the de-facto standard of 3 spaces for directives.

Update docs/devel/qapi-code-gen.rst to reflect the new paradigm, and
update the QAPI parser to prohibit "Note" sections while suggesting a
new syntax. The exact formatting to use is a matter of taste, but a good
candidate is simply:

.. note:: lorem ipsum ...
   ... dolor sit amet ...
   ... consectetur adipiscing elit ...

... but there are other choices, too. The Sphinx readthedocs theme
offers theming for the following forms (capitalization unimportant); all
are adorned with a (!) symbol () in the title bar for rendered HTML
docs.

See
https://sphinx-rtd-theme.readthedocs.io/en/stable/demo/demo.html#admonitions
for examples of each directive/admonition in use.

These are rendered in orange:

.. Attention:: ...
.. Caution:: ...
.. WARNING:: ...

These are rendered in red:

.. DANGER:: ...
.. Error:: ...

These are rendered in green:

.. Hint:: ...
.. Important:: ...
.. Tip:: ...

These are rendered in blue:

.. Note:: ...
.. admonition:: custom title

   admonition body text

This patch uses ".. note::" almost everywhere, with just two "caution"
directives. Several instances of "Notes:" have been converted to merely
".. note::" where appropriate, but ".. admonition:: notes" is used in a
few places where we had an ordered list of multiple notes that would not
make sense as standalone/separate admonitions.

NOTE: Because qapidoc.py does not attempt to preserve source ordering of
sections, the conversion of Notes from a "tagged section" to an
"untagged section" means that rendering order for some notes *may
change* as a result of this patch. The forthcoming qapidoc.py rewrite
strictly preserves source ordering in the rendered documentation, so
this issue will be rectified in the new generator.

Signed-off-by: John Snow <jsnow@redhat.com>
Acked-by: Stefan Hajnoczi <stefanha@redhat.com> [for block*.json]
---
 docs/devel/qapi-code-gen.rst                  |  7 +-
 qapi/block-core.json                          | 28 +++---
 qapi/block.json                               |  2 +-
 qapi/char.json                                | 12 +--
 qapi/control.json                             | 17 ++--
 qapi/dump.json                                |  2 +-
 qapi/introspect.json                          |  6 +-
 qapi/machine-target.json                      | 26 +++---
 qapi/machine.json                             | 47 +++++-----
 qapi/migration.json                           | 12 +--
 qapi/misc.json                                | 88 +++++++++----------
 qapi/net.json                                 |  6 +-
 qapi/pci.json                                 |  8 +-
 qapi/qdev.json                                | 28 +++---
 qapi/qom.json                                 | 17 ++--
 qapi/rocker.json                              | 16 ++--
 qapi/run-state.json                           | 18 ++--
 qapi/sockets.json                             | 10 +--
 qapi/stats.json                               | 22 ++---
 qapi/transaction.json                         |  8 +-
 qapi/ui.json                                  | 29 +++---
 qapi/virtio.json                              | 12 +--
 qga/qapi-schema.json                          | 48 +++++-----
 scripts/qapi/parser.py                        | 15 ++++
 tests/qapi-schema/doc-empty-section.err       |  2 +-
 tests/qapi-schema/doc-empty-section.json      |  2 +-
 tests/qapi-schema/doc-good.json               |  4 +-
 tests/qapi-schema/doc-good.out                |  8 +-
 tests/qapi-schema/doc-good.txt                | 10 +--
 .../qapi-schema/doc-interleaved-section.json  |  2 +-
 30 files changed, 260 insertions(+), 252 deletions(-)

diff --git a/docs/devel/qapi-code-gen.rst b/docs/devel/qapi-code-gen.rst
index cee43222f19..ae97b335cbf 100644
--- a/docs/devel/qapi-code-gen.rst
+++ b/docs/devel/qapi-code-gen.rst
@@ -995,14 +995,13 @@ line "Features:", like this::
   # @feature: Description text
 
 A tagged section begins with a paragraph that starts with one of the
-following words: "Note:"/"Notes:", "Since:", "Example:"/"Examples:",
-"Returns:", "Errors:", "TODO:".  It ends with the start of a new
-section.
+following words: "Since:", "Example:"/"Examples:", "Returns:",
+"Errors:", "TODO:".  It ends with the start of a new section.
 
 The second and subsequent lines of tagged sections must be indented
 like this::
 
- # Note: Ut enim ad minim veniam, quis nostrud exercitation ullamco
+ # TODO: Ut enim ad minim veniam, quis nostrud exercitation ullamco
  #     laboris nisi ut aliquip ex ea commodo consequat.
  #
  #     Duis aute irure dolor in reprehenderit in voluptate velit esse
diff --git a/qapi/block-core.json b/qapi/block-core.json
index df5e07debd2..cacedfb771c 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1619,9 +1619,9 @@
 #
 # @unstable: Member @x-perf is experimental.
 #
-# Note: @on-source-error and @on-target-error only affect background
-#     I/O.  If an error occurs during a guest write request, the
-#     device's rerror/werror actions will be used.
+# .. note:: @on-source-error and @on-target-error only affect background
+#    I/O.  If an error occurs during a guest write request, the device's
+#    rerror/werror actions will be used.
 #
 # Since: 4.2
 ##
@@ -5545,8 +5545,8 @@
 #     after this event and must be repaired (Since 2.2; before, every
 #     BLOCK_IMAGE_CORRUPTED event was fatal)
 #
-# Note: If action is "stop", a STOP event will eventually follow the
-#     BLOCK_IO_ERROR event.
+# .. note:: If action is "stop", a STOP event will eventually follow the
+#    BLOCK_IO_ERROR event.
 #
 # Example:
 #
@@ -5592,8 +5592,8 @@
 #     field is a debugging aid for humans, it should not be parsed by
 #     applications) (since: 2.2)
 #
-# Note: If action is "stop", a STOP event will eventually follow the
-#     BLOCK_IO_ERROR event
+# .. note:: If action is "stop", a STOP event will eventually follow the
+#    BLOCK_IO_ERROR event.
 #
 # Since: 0.13
 #
@@ -5731,8 +5731,8 @@
 #
 # @speed: rate limit, bytes per second
 #
-# Note: The "ready to complete" status is always reset by a
-#     @BLOCK_JOB_ERROR event
+# .. note:: The "ready to complete" status is always reset by a
+#    @BLOCK_JOB_ERROR event.
 #
 # Since: 1.3
 #
@@ -5985,7 +5985,7 @@
 #
 # @sectors-count: failed read operation sector count
 #
-# Note: This event is rate-limited.
+# .. note:: This event is rate-limited.
 #
 # Since: 2.0
 #
@@ -6016,7 +6016,7 @@
 #
 # @sectors-count: failed read operation sector count
 #
-# Note: This event is rate-limited.
+# .. note:: This event is rate-limited.
 #
 # Since: 2.0
 #
@@ -6048,9 +6048,9 @@
 #
 # @name: the name of the internal snapshot to be created
 #
-# Notes: In transaction, if @name is empty, or any snapshot matching
-#     @name exists, the operation will fail.  Only some image formats
-#     support it, for example, qcow2, and rbd.
+# .. note:: In transaction, if @name is empty, or any snapshot matching
+#    @name exists, the operation will fail.  Only some image formats
+#    support it, for example, qcow2, and rbd.
 #
 # Since: 1.7
 ##
diff --git a/qapi/block.json b/qapi/block.json
index 5de99fe09d9..ea81d9e1921 100644
--- a/qapi/block.json
+++ b/qapi/block.json
@@ -113,7 +113,7 @@
 # Errors:
 #     - If @device is not a valid block device, DeviceNotFound
 #
-# Notes: Ejecting a device with no media results in success
+# .. note:: Ejecting a device with no media results in success.
 #
 # Since: 0.14
 #
diff --git a/qapi/char.json b/qapi/char.json
index 777dde55d97..5eabf8e7645 100644
--- a/qapi/char.json
+++ b/qapi/char.json
@@ -21,8 +21,8 @@
 #     backend (e.g. with the chardev=... option) is in open or closed
 #     state (since 2.1)
 #
-# Notes: @filename is encoded using the QEMU command line character
-#     device encoding.  See the QEMU man page for details.
+# .. note:: @filename is encoded using the QEMU command line character
+#    device encoding.  See the QEMU man page for details.
 #
 # Since: 0.14
 ##
@@ -388,9 +388,9 @@
 #
 # @rows: console height, in chars
 #
-# Note: the options are only effective when the VNC or SDL graphical
-#     display backend is active.  They are ignored with the GTK,
-#     Spice, VNC and D-Bus display backends.
+# .. note:: The options are only effective when the VNC or SDL graphical
+#    display backend is active.  They are ignored with the GTK, Spice,
+#    VNC and D-Bus display backends.
 #
 # Since: 1.5
 ##
@@ -806,7 +806,7 @@
 #
 # @open: true if the guest has opened the virtio-serial port
 #
-# Note: This event is rate-limited.
+# .. note:: This event is rate-limited.
 #
 # Since: 2.1
 #
diff --git a/qapi/control.json b/qapi/control.json
index 10c906fa0e7..59d5e00c151 100644
--- a/qapi/control.json
+++ b/qapi/control.json
@@ -22,14 +22,13 @@
 #          "arguments": { "enable": [ "oob" ] } }
 #     <- { "return": {} }
 #
-# Notes: This command is valid exactly when first connecting: it must
-#     be issued before any other command will be accepted, and will
-#     fail once the monitor is accepting other commands.  (see qemu
-#     docs/interop/qmp-spec.rst)
+# .. note:: This command is valid exactly when first connecting: it must
+#    be issued before any other command will be accepted, and will fail
+#    once the monitor is accepting other commands.  (see qemu
+#    docs/interop/qmp-spec.rst)
 #
-#     The QMP client needs to explicitly enable QMP capabilities,
-#     otherwise all the QMP capabilities will be turned off by
-#     default.
+# .. note:: The QMP client needs to explicitly enable QMP capabilities,
+#    otherwise all the QMP capabilities will be turned off by default.
 #
 # Since: 0.13
 ##
@@ -150,8 +149,8 @@
 #          ]
 #        }
 #
-# Note: This example has been shortened as the real response is too
-#     long.
+# This example has been shortened as the real response is too long.
+#
 ##
 { 'command': 'query-commands', 'returns': ['CommandInfo'],
   'allow-preconfig': true }
diff --git a/qapi/dump.json b/qapi/dump.json
index 2fa9504d864..f9aee7ea1dd 100644
--- a/qapi/dump.json
+++ b/qapi/dump.json
@@ -90,7 +90,7 @@
 #     and @length is not allowed to be specified with non-elf @format
 #     at the same time (since 2.0)
 #
-# Note: All boolean arguments default to false
+# .. note:: All boolean arguments default to false.
 #
 # Since: 1.2
 #
diff --git a/qapi/introspect.json b/qapi/introspect.json
index b041b02ba8c..b15052ec21a 100644
--- a/qapi/introspect.json
+++ b/qapi/introspect.json
@@ -41,9 +41,9 @@
 #     names are guaranteed to be unique (no name will be duplicated
 #     with different meta-types).
 #
-# Note: the QAPI schema is also used to help define *internal*
-#     interfaces, by defining QAPI types.  These are not part of the
-#     QMP wire ABI, and therefore not returned by this command.
+# .. note:: The QAPI schema is also used to help define *internal*
+#    interfaces, by defining QAPI types.  These are not part of the QMP
+#    wire ABI, and therefore not returned by this command.
 #
 # Since: 2.5
 ##
diff --git a/qapi/machine-target.json b/qapi/machine-target.json
index 29428530923..a8d9ec87f59 100644
--- a/qapi/machine-target.json
+++ b/qapi/machine-target.json
@@ -49,15 +49,15 @@
 #     to be migration-safe, but allows tooling to get an insight and
 #     work with model details.
 #
-# Note: When a non-migration-safe CPU model is expanded in static
-#     mode, some features enabled by the CPU model may be omitted,
-#     because they can't be implemented by a static CPU model
-#     definition (e.g. cache info passthrough and PMU passthrough in
-#     x86). If you need an accurate representation of the features
-#     enabled by a non-migration-safe CPU model, use @full.  If you
-#     need a static representation that will keep ABI compatibility
-#     even when changing QEMU version or machine-type, use @static
-#     (but keep in mind that some features may be omitted).
+# .. note:: When a non-migration-safe CPU model is expanded in static
+#    mode, some features enabled by the CPU model may be omitted,
+#    because they can't be implemented by a static CPU model definition
+#    (e.g. cache info passthrough and PMU passthrough in x86). If you
+#    need an accurate representation of the features enabled by a
+#    non-migration-safe CPU model, use @full.  If you need a static
+#    representation that will keep ABI compatibility even when changing
+#    QEMU version or machine-type, use @static (but keep in mind that
+#    some features may be omitted).
 #
 # Since: 2.8
 ##
@@ -175,8 +175,8 @@
 #     - if a model contains an unknown cpu definition name, unknown
 #       properties or properties with wrong types.
 #
-# Note: this command isn't specific to s390x, but is only implemented
-#     on this architecture currently.
+# .. note:: This command isn't specific to s390x, but is only
+#    implemented on this architecture currently.
 #
 # Since: 2.8
 ##
@@ -229,8 +229,8 @@
 #     - if a model contains an unknown cpu definition name, unknown
 #       properties or properties with wrong types.
 #
-# Note: this command isn't specific to s390x, but is only implemented
-#     on this architecture currently.
+# .. note:: This command isn't specific to s390x, but is only
+#    implemented on this architecture currently.
 #
 # Since: 2.8
 ##
diff --git a/qapi/machine.json b/qapi/machine.json
index a982c945035..f15ad1b43e2 100644
--- a/qapi/machine.json
+++ b/qapi/machine.json
@@ -24,9 +24,9 @@
 #
 # @avr: since 5.1
 #
-# Notes: The resulting QMP strings can be appended to the
-#     "qemu-system-" prefix to produce the corresponding QEMU
-#     executable name.  This is true even for "qemu-system-x86_64".
+# .. note:: The resulting QMP strings can be appended to the
+#    "qemu-system-" prefix to produce the corresponding QEMU executable
+#    name.  This is true even for "qemu-system-x86_64".
 #
 # Since: 3.0
 ##
@@ -305,8 +305,9 @@
 #
 # Since: 0.14
 #
-# Notes: If no UUID was specified for the guest, a null UUID is
-#     returned.
+# .. note:: If no UUID was specified for the guest, a null UUID is
+#    returned.
+#
 ##
 { 'struct': 'UuidInfo', 'data': {'UUID': 'str'} }
 
@@ -367,10 +368,10 @@
 #
 # Since: 0.14
 #
-# Notes: A guest may or may not respond to this command.  This command
-#     returning does not indicate that a guest has accepted the
-#     request or that it has shut down.  Many guests will respond to
-#     this command by prompting the user in some way.
+# .. note:: A guest may or may not respond to this command.  This
+#    command returning does not indicate that a guest has accepted the
+#    request or that it has shut down.  Many guests will respond to this
+#    command by prompting the user in some way.
 #
 # Example:
 #
@@ -389,8 +390,8 @@
 #
 # Since: 1.1
 #
-# Note: prior to 4.0, this command does nothing in case the guest
-#     isn't suspended.
+# .. note:: Prior to 4.0, this command does nothing in case the guest
+#    isn't suspended.
 #
 # Example:
 #
@@ -440,8 +441,8 @@
 #
 # Since: 0.14
 #
-# Note: prior to 2.1, this command was only supported for x86 and s390
-#     VMs
+# .. note:: Prior to 2.1, this command was only supported for x86 and
+#    s390 VMs.
 #
 # Example:
 #
@@ -839,7 +840,7 @@
 #
 # Since: 0.14
 #
-# Notes: Errors were not reliably returned until 1.1
+# .. caution:: Errors were not reliably returned until 1.1.
 #
 # Example:
 #
@@ -865,7 +866,7 @@
 #
 # Since: 0.14
 #
-# Notes: Errors were not reliably returned until 1.1
+# .. caution:: Errors were not reliably returned until 1.1.
 #
 # Example:
 #
@@ -995,8 +996,8 @@
 #
 # @thread-id: thread number within the core the CPU  belongs to
 #
-# Note: management should be prepared to pass through additional
-#     properties with device_add.
+# .. note:: Management should be prepared to pass through additional
+#    properties with device_add.
 #
 # Since: 2.7
 ##
@@ -1123,9 +1124,9 @@
 #       the KVM kernel module cannot support it, KVMMissingCap
 #     - If no balloon device is present, DeviceNotActive
 #
-# Notes: This command just issues a request to the guest.  When it
-#     returns, the balloon size may not have changed.  A guest can
-#     change the balloon size independent of this command.
+# .. note:: This command just issues a request to the guest.  When it
+#    returns, the balloon size may not have changed.  A guest can change
+#    the balloon size independent of this command.
 #
 # Since: 0.14
 #
@@ -1185,7 +1186,7 @@
 # @actual: the logical size of the VM in bytes Formula used:
 #     logical_vm_size = vm_ram_size - balloon_size
 #
-# Note: this event is rate-limited.
+# .. note:: This event is rate-limited.
 #
 # Since: 1.2
 #
@@ -1248,7 +1249,7 @@
 # Emitted when the hv-balloon driver receives a "STATUS" message from
 # the guest.
 #
-# Note: this event is rate-limited.
+# .. note:: This event is rate-limited.
 #
 # Since: 8.2
 #
@@ -1593,7 +1594,7 @@
 #
 # @qom-path: path to the device object in the QOM tree (since 6.2)
 #
-# Note: this event is rate-limited.
+# .. note:: This event is rate-limited.
 #
 # Since: 5.1
 #
diff --git a/qapi/migration.json b/qapi/migration.json
index 9ec9ef36c47..26ad5e5e7a3 100644
--- a/qapi/migration.json
+++ b/qapi/migration.json
@@ -1456,8 +1456,8 @@
 #
 # Cancel the current executing migration process.
 #
-# Notes: This command succeeds even if there is no migration process
-#     running.
+# .. note:: This command succeeds even if there is no migration process
+#    running.
 #
 # Since: 0.14
 #
@@ -1589,16 +1589,16 @@
 #
 # Since: 0.14
 #
-# Notes:
+# .. admonition:: Notes
 #
 #     1. The 'query-migrate' command should be used to check
 #        migration's progress and final result (this information is
 #        provided by the 'status' member)
 #
-#     2. All boolean arguments default to false
+#     2. All boolean arguments default to false.
 #
 #     3. The user Monitor's "detach" argument is invalid in QMP and
-#        should not be used
+#        should not be used.
 #
 #     4. The uri argument should have the Uniform Resource Identifier
 #        of default destination VM. This connection will be bound to
@@ -1672,7 +1672,7 @@
 #
 # Since: 2.3
 #
-# Notes:
+# .. admonition:: Notes
 #
 #     1. It's a bad idea to use a string for the uri, but it needs to
 #        stay compatible with -incoming and the format of the uri is
diff --git a/qapi/misc.json b/qapi/misc.json
index 4b41e15dcd4..13ea82f5254 100644
--- a/qapi/misc.json
+++ b/qapi/misc.json
@@ -103,9 +103,9 @@
 #
 # Returns a list of information about each iothread.
 #
-# Note: this list excludes the QEMU main loop thread, which is not
-#     declared using the -object iothread command-line option.  It is
-#     always the main thread of the process.
+# .. note:: This list excludes the QEMU main loop thread, which is not
+#    declared using the -object iothread command-line option.  It is
+#    always the main thread of the process.
 #
 # Returns: a list of @IOThreadInfo for each iothread
 #
@@ -136,13 +136,13 @@
 #
 # Since: 0.14
 #
-# Notes: This function will succeed even if the guest is already in
-#     the stopped state.  In "inmigrate" state, it will ensure that
-#     the guest remains paused once migration finishes, as if the -S
-#     option was passed on the command line.
+# .. note:: This function will succeed even if the guest is already in
+#    the stopped state.  In "inmigrate" state, it will ensure that the
+#    guest remains paused once migration finishes, as if the -S option
+#    was passed on the command line.
 #
-#     In the "suspended" state, it will completely stop the VM and
-#     cause a transition to the "paused" state.  (Since 9.0)
+#    In the "suspended" state, it will completely stop the VM and cause
+#    a transition to the "paused" state.  (Since 9.0)
 #
 # Example:
 #
@@ -158,15 +158,15 @@
 #
 # Since: 0.14
 #
-# Notes: This command will succeed if the guest is currently running.
-#     It will also succeed if the guest is in the "inmigrate" state;
-#     in this case, the effect of the command is to make sure the
-#     guest starts once migration finishes, removing the effect of the
-#     -S command line option if it was passed.
+# .. note:: This command will succeed if the guest is currently running.
+#    It will also succeed if the guest is in the "inmigrate" state; in
+#    this case, the effect of the command is to make sure the guest
+#    starts once migration finishes, removing the effect of the -S
+#    command line option if it was passed.
 #
-#     If the VM was previously suspended, and not been reset or woken,
-#     this command will transition back to the "suspended" state.
-#     (Since 9.0)
+#    If the VM was previously suspended, and not been reset or woken,
+#    this command will transition back to the "suspended" state.  (Since
+#    9.0)
 #
 # Example:
 #
@@ -219,18 +219,18 @@
 #
 # Since: 0.14
 #
-# Notes: This command only exists as a stop-gap.  Its use is highly
-#     discouraged.  The semantics of this command are not guaranteed:
-#     this means that command names, arguments and responses can
-#     change or be removed at ANY time.  Applications that rely on
-#     long term stability guarantees should NOT use this command.
+# .. note:: This command only exists as a stop-gap.  Its use is highly
+#    discouraged.  The semantics of this command are not guaranteed:
+#    this means that command names, arguments and responses can change
+#    or be removed at ANY time.  Applications that rely on long term
+#    stability guarantees should NOT use this command.
 #
-#     Known limitations:
+#    Known limitations:
 #
-#     * This command is stateless, this means that commands that
-#       depend on state information (such as getfd) might not work
+#    * This command is stateless, this means that commands that
+#      depend on state information (such as getfd) might not work.
 #
-#     * Commands that prompt the user for data don't currently work
+#    * Commands that prompt the user for data don't currently work.
 #
 # Example:
 #
@@ -252,11 +252,11 @@
 #
 # Since: 0.14
 #
-# Notes: If @fdname already exists, the file descriptor assigned to it
-#     will be closed and replaced by the received file descriptor.
+# .. note:: If @fdname already exists, the file descriptor assigned to
+#    it will be closed and replaced by the received file descriptor.
 #
-#     The 'closefd' command can be used to explicitly close the file
-#     descriptor when it is no longer needed.
+#    The 'closefd' command can be used to explicitly close the file
+#    descriptor when it is no longer needed.
 #
 # Example:
 #
@@ -279,11 +279,11 @@
 #
 # Since: 8.0
 #
-# Notes: If @fdname already exists, the file descriptor assigned to it
-#     will be closed and replaced by the received file descriptor.
+# .. note:: If @fdname already exists, the file descriptor assigned to
+#    it will be closed and replaced by the received file descriptor.
 #
-#     The 'closefd' command can be used to explicitly close the file
-#     descriptor when it is no longer needed.
+#    The 'closefd' command can be used to explicitly close the file
+#    descriptor when it is no longer needed.
 #
 # Example:
 #
@@ -339,10 +339,9 @@
 #     - If file descriptor was not received, GenericError
 #     - If @fdset-id is a negative value, GenericError
 #
-# Notes:
-#     The list of fd sets is shared by all monitor connections.
+# .. note:: The list of fd sets is shared by all monitor connections.
 #
-#     If @fdset-id is not specified, a new fd set will be created.
+# .. note:: If @fdset-id is not specified, a new fd set will be created.
 #
 # Since: 1.2
 #
@@ -370,11 +369,10 @@
 #
 # Since: 1.2
 #
-# Notes:
-#     The list of fd sets is shared by all monitor connections.
+# .. note:: The list of fd sets is shared by all monitor connections.
 #
-#     If @fd is not specified, all file descriptors in @fdset-id will
-#     be removed.
+# .. note:: If @fd is not specified, all file descriptors in @fdset-id
+#    will be removed.
 #
 # Example:
 #
@@ -420,7 +418,7 @@
 #
 # Since: 1.2
 #
-# Note: The list of fd sets is shared by all monitor connections.
+# .. note:: The list of fd sets is shared by all monitor connections.
 #
 # Example:
 #
@@ -561,9 +559,9 @@
 #
 # @qom-path: path to the RTC object in the QOM tree
 #
-# Note: This event is rate-limited.  It is not guaranteed that the RTC
-#     in the system implements this event, or even that the system has
-#     an RTC at all.
+# .. note:: This event is rate-limited.  It is not guaranteed that the
+#    RTC in the system implements this event, or even that the system
+#    has an RTC at all.
 #
 # Since: 0.13
 #
diff --git a/qapi/net.json b/qapi/net.json
index c19df435a53..dd6c365c34d 100644
--- a/qapi/net.json
+++ b/qapi/net.json
@@ -22,9 +22,9 @@
 #
 # Since: 0.14
 #
-# Notes: Not all network adapters support setting link status.  This
-#     command will succeed even if the network adapter does not
-#     support link status notification.
+# .. note:: Not all network adapters support setting link status.  This
+#    command will succeed even if the network adapter does not support
+#    link status notification.
 #
 # Example:
 #
diff --git a/qapi/pci.json b/qapi/pci.json
index 08bf6958634..8287d15dd0b 100644
--- a/qapi/pci.json
+++ b/qapi/pci.json
@@ -146,8 +146,8 @@
 #
 # @regions: a list of the PCI I/O regions associated with the device
 #
-# Notes: the contents of @class_info.desc are not stable and should
-#     only be treated as informational.
+# .. note:: The contents of @class_info.desc are not stable and should
+#    only be treated as informational.
 #
 # Since: 0.14
 ##
@@ -311,7 +311,7 @@
 #           ]
 #        }
 #
-# Note: This example has been shortened as the real response is too
-#     long.
+# This example has been shortened as the real response is too long.
+#
 ##
 { 'command': 'query-pci', 'returns': ['PciInfo'] }
diff --git a/qapi/qdev.json b/qapi/qdev.json
index facaa0bc6a2..f5b35a814fe 100644
--- a/qapi/qdev.json
+++ b/qapi/qdev.json
@@ -20,9 +20,9 @@
 # Returns: a list of ObjectPropertyInfo describing a devices
 #     properties
 #
-# Note: objects can create properties at runtime, for example to
-#     describe links between different devices and/or objects.  These
-#     properties are not included in the output of this command.
+# .. note:: Objects can create properties at runtime, for example to
+#    describe links between different devices and/or objects.  These
+#    properties are not included in the output of this command.
 #
 # Since: 1.2
 ##
@@ -51,7 +51,7 @@
 #     supports JSON syntax without the reference counting leak that
 #     broke hot-unplug
 #
-# Notes:
+# .. admonition:: Notes
 #
 #     1. Additional arguments depend on the type.
 #
@@ -60,7 +60,7 @@
 #
 #     3. It's possible to list device properties by running QEMU with
 #        the "-device DEVICE,help" command-line argument, where DEVICE
-#        is the device's name
+#        is the device's name.
 #
 # Example:
 #
@@ -92,15 +92,15 @@
 # Errors:
 #     - If @id is not a valid device, DeviceNotFound
 #
-# Notes: When this command completes, the device may not be removed
-#     from the guest.  Hot removal is an operation that requires guest
-#     cooperation.  This command merely requests that the guest begin
-#     the hot removal process.  Completion of the device removal
-#     process is signaled with a DEVICE_DELETED event.  Guest reset
-#     will automatically complete removal for all devices.  If a
-#     guest-side error in the hot removal process is detected, the
-#     device will not be removed and a DEVICE_UNPLUG_GUEST_ERROR event
-#     is sent.  Some errors cannot be detected.
+# .. note:: When this command completes, the device may not be removed
+#    from the guest.  Hot removal is an operation that requires guest
+#    cooperation.  This command merely requests that the guest begin the
+#    hot removal process.  Completion of the device removal process is
+#    signaled with a DEVICE_DELETED event.  Guest reset will
+#    automatically complete removal for all devices.  If a guest-side
+#    error in the hot removal process is detected, the device will not
+#    be removed and a DEVICE_UNPLUG_GUEST_ERROR event is sent.  Some
+#    errors cannot be detected.
 #
 # Since: 0.14
 #
diff --git a/qapi/qom.json b/qapi/qom.json
index 8bd299265e3..f582a1357b7 100644
--- a/qapi/qom.json
+++ b/qapi/qom.json
@@ -195,9 +195,9 @@
 #
 # @typename: the type name of an object
 #
-# Note: objects can create properties at runtime, for example to
-#     describe links between different devices and/or objects.  These
-#     properties are not included in the output of this command.
+# .. note:: Objects can create properties at runtime, for example to
+#    describe links between different devices and/or objects.  These
+#    properties are not included in the output of this command.
 #
 # Returns: a list of ObjectPropertyInfo describing object properties
 #
@@ -612,12 +612,11 @@
 #     older to allow migration with newer QEMU versions.
 #     (default: false generally, but true for machine types <= 4.0)
 #
-# Note: prealloc=true and reserve=false cannot be set at the same
-#     time.  With reserve=true, the behavior depends on the operating
-#     system: for example, Linux will not reserve swap space for
-#     shared file mappings -- "not applicable". In contrast,
-#     reserve=false will bail out if it cannot be configured
-#     accordingly.
+# .. note:: prealloc=true and reserve=false cannot be set at the same
+#    time.  With reserve=true, the behavior depends on the operating
+#    system: for example, Linux will not reserve swap space for shared
+#    file mappings -- "not applicable". In contrast, reserve=false will
+#    bail out if it cannot be configured accordingly.
 #
 # Since: 2.1
 ##
diff --git a/qapi/rocker.json b/qapi/rocker.json
index f5225eb62cc..9f95e638309 100644
--- a/qapi/rocker.json
+++ b/qapi/rocker.json
@@ -138,8 +138,8 @@
 #
 # @ip-dst: IP header destination address
 #
-# Note: optional members may or may not appear in the flow key
-#     depending if they're relevant to the flow key.
+# .. note:: Optional members may or may not appear in the flow key
+#    depending if they're relevant to the flow key.
 #
 # Since: 2.4
 ##
@@ -168,8 +168,8 @@
 #
 # @ip-tos: IP header TOS field
 #
-# Note: optional members may or may not appear in the flow mask
-#     depending if they're relevant to the flow mask.
+# .. note:: Optional members may or may not appear in the flow mask
+#    depending if they're relevant to the flow mask.
 #
 # Since: 2.4
 ##
@@ -195,8 +195,8 @@
 #
 # @out-pport: physical output port
 #
-# Note: optional members may or may not appear in the flow action
-#     depending if they're relevant to the flow action.
+# .. note:: Optional members may or may not appear in the flow action
+#    depending if they're relevant to the flow action.
 #
 # Since: 2.4
 ##
@@ -288,8 +288,8 @@
 #
 # @ttl-check: perform TTL check
 #
-# Note: optional members may or may not appear in the group depending
-#     if they're relevant to the group type.
+# .. note:: Optional members may or may not appear in the group depending
+#    if they're relevant to the group type.
 #
 # Since: 2.4
 ##
diff --git a/qapi/run-state.json b/qapi/run-state.json
index f8773f23b29..dc524234ace 100644
--- a/qapi/run-state.json
+++ b/qapi/run-state.json
@@ -146,9 +146,9 @@
 # @reason: The @ShutdownCause which resulted in the SHUTDOWN.
 #     (since 4.0)
 #
-# Note: If the command-line option "-no-shutdown" has been specified,
-#     qemu will not exit, and a STOP event will eventually follow the
-#     SHUTDOWN event
+# .. note:: If the command-line option "-no-shutdown" has been
+#    specified, qemu will not exit, and a STOP event will eventually
+#    follow the SHUTDOWN event.
 #
 # Since: 0.12
 #
@@ -247,8 +247,8 @@
 # saved on disk, for example, S4 state, which is sometimes called
 # hibernate state
 #
-# Note: QEMU shuts down (similar to event @SHUTDOWN) when entering
-#     this state
+# .. note:: QEMU shuts down (similar to event @SHUTDOWN) when entering
+#    this state.
 #
 # Since: 1.2
 #
@@ -281,11 +281,11 @@
 #
 # @action: action that has been taken
 #
-# Note: If action is "reset", "shutdown", or "pause" the WATCHDOG
-#     event is followed respectively by the RESET, SHUTDOWN, or STOP
-#     events
+# .. note:: If action is "reset", "shutdown", or "pause" the WATCHDOG
+#    event is followed respectively by the RESET, SHUTDOWN, or STOP
+#    events.
 #
-# Note: This event is rate-limited.
+# .. note:: This event is rate-limited.
 #
 # Since: 0.13
 #
diff --git a/qapi/sockets.json b/qapi/sockets.json
index aa97c897687..3970118bf4e 100644
--- a/qapi/sockets.json
+++ b/qapi/sockets.json
@@ -104,8 +104,8 @@
 #
 # @port: port
 #
-# Note: string types are used to allow for possible future hostname or
-#     service resolution support.
+# .. note:: String types are used to allow for possible future hostname
+#    or service resolution support.
 #
 # Since: 2.8
 ##
@@ -179,9 +179,9 @@
 #
 # @type: Transport type
 #
-# Note: This type is deprecated in favor of SocketAddress.  The
-#     difference between SocketAddressLegacy and SocketAddress is that
-#     the latter has fewer {} on the wire.
+# .. note:: This type is deprecated in favor of SocketAddress.  The
+#    difference between SocketAddressLegacy and SocketAddress is that
+#    the latter has fewer {} on the wire.
 #
 # Since: 1.3
 ##
diff --git a/qapi/stats.json b/qapi/stats.json
index 578b52c7ef7..efbbe26244a 100644
--- a/qapi/stats.json
+++ b/qapi/stats.json
@@ -258,17 +258,17 @@
 #
 # @provider: a provider to restrict the query to.
 #
-# Note: runtime-collected statistics and their names fall outside
-#     QEMU's usual deprecation policies.  QEMU will try to keep the
-#     set of available data stable, together with their names, but
-#     will not guarantee stability at all costs; the same is true of
-#     providers that source statistics externally, e.g. from Linux.
-#     For example, if the same value is being tracked with different
-#     names on different architectures or by different providers, one
-#     of them might be renamed.  A statistic might go away if an
-#     algorithm is changed or some code is removed; changing a default
-#     might cause previously useful statistics to always report 0.
-#     Such changes, however, are expected to be rare.
+# .. note:: Runtime-collected statistics and their names fall outside
+#    QEMU's usual deprecation policies.  QEMU will try to keep the set
+#    of available data stable, together with their names, but will not
+#    guarantee stability at all costs; the same is true of providers
+#    that source statistics externally, e.g. from Linux.  For example,
+#    if the same value is being tracked with different names on
+#    different architectures or by different providers, one of them
+#    might be renamed.  A statistic might go away if an algorithm is
+#    changed or some code is removed; changing a default might cause
+#    previously useful statistics to always report 0.  Such changes,
+#    however, are expected to be rare.
 #
 # Since: 7.1
 ##
diff --git a/qapi/transaction.json b/qapi/transaction.json
index 07afc269d54..bcb05fdedd6 100644
--- a/qapi/transaction.json
+++ b/qapi/transaction.json
@@ -237,10 +237,10 @@
 # Errors:
 #     - Any errors from commands in the transaction
 #
-# Note: The transaction aborts on the first failure.  Therefore, there
-#     will be information on only one failed operation returned in an
-#     error condition, and subsequent actions will not have been
-#     attempted.
+# .. note:: The transaction aborts on the first failure.  Therefore,
+#    there will be information on only one failed operation returned in
+#    an error condition, and subsequent actions will not have been
+#    attempted.
 #
 # Since: 1.1
 #
diff --git a/qapi/ui.json b/qapi/ui.json
index c12f5292571..a1999965e44 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -107,11 +107,10 @@
 #     - '+INT' where INT is the number of seconds from now (integer)
 #     - 'INT' where INT is the absolute time in seconds
 #
-# Notes: Time is relative to the server and currently there is no way
-#     to coordinate server time with client time.  It is not
-#     recommended to use the absolute time version of the @time
-#     parameter unless you're sure you are on the same machine as the
-#     QEMU instance.
+# .. note:: Time is relative to the server and currently there is no way
+#    to coordinate server time with client time.  It is not recommended
+#    to use the absolute time version of the @time parameter unless
+#    you're sure you are on the same machine as the QEMU instance.
 #
 # Since: 7.0
 ##
@@ -274,7 +273,7 @@
 # @unknown: No information is available about mouse mode used by the
 #     spice server.
 #
-# Note: spice/enums.h has a SpiceMouseMode already, hence the name.
+# .. note:: spice/enums.h has a SpiceMouseMode already, hence the name.
 #
 # Since: 1.1
 ##
@@ -705,9 +704,9 @@
 #
 # Since: 1.1
 #
-# Notes: An empty password in this command will set the password to
-#     the empty string.  Existing clients are unaffected by executing
-#     this command.
+# .. note:: An empty password in this command will set the password to
+#    the empty string.  Existing clients are unaffected by executing
+#    this command.
 ##
 { 'command': 'change-vnc-password',
   'data': { 'password': 'str' },
@@ -722,8 +721,8 @@
 #
 # @client: client information
 #
-# Note: This event is emitted before any authentication takes place,
-#     thus the authentication ID is not provided
+# .. note:: This event is emitted before any authentication takes place,
+#    thus the authentication ID is not provided.
 #
 # Since: 0.13
 #
@@ -1268,10 +1267,10 @@
 #
 # Since: 2.6
 #
-# Note: The consoles are visible in the qom tree, under
-#     /backend/console[$index]. They have a device link and head
-#     property, so it is possible to map which console belongs to
-#     which device and display.
+# .. note:: The consoles are visible in the qom tree, under
+#    /backend/console[$index]. They have a device link and head
+#    property, so it is possible to map which console belongs to which
+#    device and display.
 #
 # Examples:
 #
diff --git a/qapi/virtio.json b/qapi/virtio.json
index 74fc27c7029..b91f3cdd0df 100644
--- a/qapi/virtio.json
+++ b/qapi/virtio.json
@@ -559,12 +559,12 @@
 #
 # Returns: VirtQueueStatus of the VirtQueue
 #
-# Notes: last_avail_idx will not be displayed in the case where the
-#     selected VirtIODevice has a running vhost device and the
-#     VirtIODevice VirtQueue index (queue) does not exist for the
-#     corresponding vhost device vhost_virtqueue.  Also,
-#     shadow_avail_idx will not be displayed in the case where the
-#     selected VirtIODevice has a running vhost device.
+# .. note:: last_avail_idx will not be displayed in the case where the
+#    selected VirtIODevice has a running vhost device and the
+#    VirtIODevice VirtQueue index (queue) does not exist for the
+#    corresponding vhost device vhost_virtqueue.  Also, shadow_avail_idx
+#    will not be displayed in the case where the selected VirtIODevice
+#    has a running vhost device.
 #
 # Since: 7.2
 #
diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
index b3de1fb6b3a..57598331c5c 100644
--- a/qga/qapi-schema.json
+++ b/qga/qapi-schema.json
@@ -422,8 +422,9 @@
 # Returns: GuestFsfreezeStatus ("thawed", "frozen", etc., as defined
 #     below)
 #
-# Note: This may fail to properly report the current state as a result
-#     of some other guest processes having issued an fs freeze/thaw.
+# .. note:: This may fail to properly report the current state as a
+#    result of some other guest processes having issued an fs
+#    freeze/thaw.
 #
 # Since: 0.15.0
 ##
@@ -443,9 +444,9 @@
 #
 # Returns: Number of file systems currently frozen.
 #
-# Note: On Windows, the command is implemented with the help of a
-#     Volume Shadow-copy Service DLL helper.  The frozen state is
-#     limited for up to 10 seconds by VSS.
+# .. note:: On Windows, the command is implemented with the help of a
+#    Volume Shadow-copy Service DLL helper.  The frozen state is limited
+#    for up to 10 seconds by VSS.
 #
 # Since: 0.15.0
 ##
@@ -479,10 +480,10 @@
 #
 # Returns: Number of file systems thawed by this call
 #
-# Note: if return value does not match the previous call to
-#     guest-fsfreeze-freeze, this likely means some freezable
-#     filesystems were unfrozen before this call, and that the
-#     filesystem state may have changed before issuing this command.
+# .. note:: If return value does not match the previous call to
+#    guest-fsfreeze-freeze, this likely means some freezable filesystems
+#    were unfrozen before this call, and that the filesystem state may
+#    have changed before issuing this command.
 #
 # Since: 0.15.0
 ##
@@ -560,8 +561,8 @@
 # Errors:
 #     - If suspend to disk is not supported, Unsupported
 #
-# Notes: It's strongly recommended to issue the guest-sync command
-#     before sending commands when the guest resumes
+# .. note:: It's strongly recommended to issue the guest-sync command
+#    before sending commands when the guest resumes.
 #
 # Since: 1.1
 ##
@@ -596,8 +597,8 @@
 # Errors:
 #     - If suspend to ram is not supported, Unsupported
 #
-# Notes: It's strongly recommended to issue the guest-sync command
-#     before sending commands when the guest resumes
+# .. note:: It's strongly recommended to issue the guest-sync command
+#    before sending commands when the guest resumes.
 #
 # Since: 1.1
 ##
@@ -631,8 +632,8 @@
 # Errors:
 #     - If hybrid suspend is not supported, Unsupported
 #
-# Notes: It's strongly recommended to issue the guest-sync command
-#     before sending commands when the guest resumes
+# .. note:: It's strongly recommended to issue the guest-sync command
+#    before sending commands when the guest resumes.
 #
 # Since: 1.1
 ##
@@ -1461,16 +1462,15 @@
 #     * POSIX: as defined by os-release(5)
 #     * Windows: contains string "server" or "client"
 #
-# Notes: On POSIX systems the fields @id, @name, @pretty-name,
-#     @version, @version-id, @variant and @variant-id follow the
-#     definition specified in os-release(5). Refer to the manual page
-#     for exact description of the fields.  Their values are taken
-#     from the os-release file.  If the file is not present in the
-#     system, or the values are not present in the file, the fields
-#     are not included.
+# .. note:: On POSIX systems the fields @id, @name, @pretty-name,
+#    @version, @version-id, @variant and @variant-id follow the
+#    definition specified in os-release(5). Refer to the manual page for
+#    exact description of the fields.  Their values are taken from the
+#    os-release file.  If the file is not present in the system, or the
+#    values are not present in the file, the fields are not included.
 #
-#     On Windows the values are filled from information gathered from
-#     the system.
+#    On Windows the values are filled from information gathered from
+#    the system.
 #
 # Since: 2.10
 ##
diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py
index c3d20cc01bc..0a13f0f541a 100644
--- a/scripts/qapi/parser.py
+++ b/scripts/qapi/parser.py
@@ -547,6 +547,21 @@ def get_doc(self) -> 'QAPIDoc':
                         r'(Returns|Errors|Since|Notes?|Examples?|TODO): *',
                         line):
                     # tagged section
+
+                    # TODO: Remove this error sometime in 2025 or so
+                    # after we've fully transitioned to the new qapidoc
+                    # generator.
+
+                    # See commit message for more markup suggestions O:-)
+                    if 'Note' in match.group(1):
+                        emsg = (
+                            f"The '{match.group(1)}' section is no longer "
+                            "supported. Please use rST's '.. note::' or "
+                            "'.. admonition:: notes' directives, or another "
+                            "suitable admonition instead."
+                        )
+                        raise QAPIParseError(self, emsg)
+
                     doc.new_tagged_section(self.info, match.group(1))
                     text = line[match.end():]
                     if text:
diff --git a/tests/qapi-schema/doc-empty-section.err b/tests/qapi-schema/doc-empty-section.err
index 5f03a6d733f..711a0d629c2 100644
--- a/tests/qapi-schema/doc-empty-section.err
+++ b/tests/qapi-schema/doc-empty-section.err
@@ -1 +1 @@
-doc-empty-section.json:6: text required after 'Note:'
+doc-empty-section.json:6: text required after 'Errors:'
diff --git a/tests/qapi-schema/doc-empty-section.json b/tests/qapi-schema/doc-empty-section.json
index f3384e9a3bb..f179d3eff6d 100644
--- a/tests/qapi-schema/doc-empty-section.json
+++ b/tests/qapi-schema/doc-empty-section.json
@@ -3,6 +3,6 @@
 ##
 # @foo:
 #
-# Note:
+# Errors:
 ##
 { 'command': 'foo', 'data': {'a': 'int'} }
diff --git a/tests/qapi-schema/doc-good.json b/tests/qapi-schema/doc-good.json
index 8b39eb946af..32ff910b4f8 100644
--- a/tests/qapi-schema/doc-good.json
+++ b/tests/qapi-schema/doc-good.json
@@ -157,7 +157,7 @@
 # @cmd-feat1: a feature
 # @cmd-feat2: another feature
 #
-# Note: @arg3 is undocumented
+# .. note:: @arg3 is undocumented
 #
 # Returns: @Object
 #
@@ -165,7 +165,7 @@
 #
 # TODO: frobnicate
 #
-# Notes:
+# .. admonition:: Notes
 #
 #  - Lorem ipsum dolor sit amet
 #  - Ut enim ad minim veniam
diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out
index 435f6e6d768..631dc9f8dad 100644
--- a/tests/qapi-schema/doc-good.out
+++ b/tests/qapi-schema/doc-good.out
@@ -169,15 +169,17 @@ description starts on the same line
 a feature
     feature=cmd-feat2
 another feature
-    section=Note
-@arg3 is undocumented
+    section=None
+.. note:: @arg3 is undocumented
     section=Returns
 @Object
     section=Errors
 some
     section=TODO
 frobnicate
-    section=Notes
+    section=None
+.. admonition:: Notes
+
  - Lorem ipsum dolor sit amet
  - Ut enim ad minim veniam
 
diff --git a/tests/qapi-schema/doc-good.txt b/tests/qapi-schema/doc-good.txt
index 847db70412d..d8bfa742c2f 100644
--- a/tests/qapi-schema/doc-good.txt
+++ b/tests/qapi-schema/doc-good.txt
@@ -193,11 +193,9 @@ Features
 "cmd-feat2"
    another feature
 
+Note:
 
-Note
-~~~~
-
-"arg3" is undocumented
+  "arg3" is undocumented
 
 
 Returns
@@ -211,9 +209,7 @@ Errors
 
 some
 
-
-Notes
-~~~~~
+Notes:
 
 * Lorem ipsum dolor sit amet
 
diff --git a/tests/qapi-schema/doc-interleaved-section.json b/tests/qapi-schema/doc-interleaved-section.json
index adb29e98daa..eec01ed5650 100644
--- a/tests/qapi-schema/doc-interleaved-section.json
+++ b/tests/qapi-schema/doc-interleaved-section.json
@@ -10,7 +10,7 @@
 #
 #           bao
 #
-# Note: a section.
+# TODO: a section.
 #
 # @foobar: catch this
 #
-- 
2.45.0



^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v2 11/21] qapi: update prose in note blocks
  2024-06-26 22:21 [PATCH v2 00/21] qapi: convert "Note" and "Example" sections to rST John Snow
                   ` (9 preceding siblings ...)
  2024-06-26 22:21 ` [PATCH v2 10/21] qapi: convert "Note" sections to plain rST John Snow
@ 2024-06-26 22:21 ` John Snow
  2024-06-26 22:21 ` [PATCH v2 12/21] qapi: add markup to " John Snow
                   ` (9 subsequent siblings)
  20 siblings, 0 replies; 44+ messages in thread
From: John Snow @ 2024-06-26 22:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Markus Armbruster, Philippe Mathieu-Daudé, Lukas Straub,
	Igor Mammedov, Jason Wang, Yanan Wang, Hanna Reitz,
	Konstantin Kostiuk, Stefan Berger, John Snow

Where I've noticed, rephrase the note to read more fluently.

Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
---
 qapi/block-core.json | 4 ++--
 qga/qapi-schema.json | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/qapi/block-core.json b/qapi/block-core.json
index cacedfb771c..9ef23ec02ae 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -6048,9 +6048,9 @@
 #
 # @name: the name of the internal snapshot to be created
 #
-# .. note:: In transaction, if @name is empty, or any snapshot matching
+# .. note:: In a transaction, if @name is empty or any snapshot matching
 #    @name exists, the operation will fail.  Only some image formats
-#    support it, for example, qcow2, and rbd.
+#    support it; for example, qcow2, and rbd.
 #
 # Since: 1.7
 ##
diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
index 57598331c5c..1273d85bb5f 100644
--- a/qga/qapi-schema.json
+++ b/qga/qapi-schema.json
@@ -480,7 +480,7 @@
 #
 # Returns: Number of file systems thawed by this call
 #
-# .. note:: If return value does not match the previous call to
+# .. note:: If the return value does not match the previous call to
 #    guest-fsfreeze-freeze, this likely means some freezable filesystems
 #    were unfrozen before this call, and that the filesystem state may
 #    have changed before issuing this command.
-- 
2.45.0



^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v2 12/21] qapi: add markup to note blocks
  2024-06-26 22:21 [PATCH v2 00/21] qapi: convert "Note" and "Example" sections to rST John Snow
                   ` (10 preceding siblings ...)
  2024-06-26 22:21 ` [PATCH v2 11/21] qapi: update prose in note blocks John Snow
@ 2024-06-26 22:21 ` John Snow
  2024-06-26 22:21 ` [PATCH v2 13/21] qapi/parser: don't parse rST markup as section headers John Snow
                   ` (8 subsequent siblings)
  20 siblings, 0 replies; 44+ messages in thread
From: John Snow @ 2024-06-26 22:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Markus Armbruster, Philippe Mathieu-Daudé, Lukas Straub,
	Igor Mammedov, Jason Wang, Yanan Wang, Hanna Reitz,
	Konstantin Kostiuk, Stefan Berger, John Snow

Generally, surround command-line options with ``literal`` markup to help
it stand out from prose in rendered HTML, and add cross-references to
replace "see also" messages.

References to types, values, and other QAPI definitions are not yet
adjusted here; they will be converted en masse in a subsequent patch
after the new QAPI doc generator is merged.

Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
---
 qapi/control.json   | 4 ++--
 qapi/misc.json      | 8 ++++----
 qapi/qdev.json      | 2 +-
 qapi/run-state.json | 2 +-
 qapi/sockets.json   | 2 +-
 qapi/ui.json        | 2 +-
 6 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/qapi/control.json b/qapi/control.json
index 59d5e00c151..fe2af45120b 100644
--- a/qapi/control.json
+++ b/qapi/control.json
@@ -24,8 +24,8 @@
 #
 # .. note:: This command is valid exactly when first connecting: it must
 #    be issued before any other command will be accepted, and will fail
-#    once the monitor is accepting other commands.  (see qemu
-#    docs/interop/qmp-spec.rst)
+#    once the monitor is accepting other commands.
+#    (see :doc:`/interop/qmp-spec`)
 #
 # .. note:: The QMP client needs to explicitly enable QMP capabilities,
 #    otherwise all the QMP capabilities will be turned off by default.
diff --git a/qapi/misc.json b/qapi/misc.json
index 13ea82f5254..b04efbadec6 100644
--- a/qapi/misc.json
+++ b/qapi/misc.json
@@ -104,7 +104,7 @@
 # Returns a list of information about each iothread.
 #
 # .. note:: This list excludes the QEMU main loop thread, which is not
-#    declared using the -object iothread command-line option.  It is
+#    declared using the ``-object iothread`` command-line option.  It is
 #    always the main thread of the process.
 #
 # Returns: a list of @IOThreadInfo for each iothread
@@ -138,8 +138,8 @@
 #
 # .. note:: This function will succeed even if the guest is already in
 #    the stopped state.  In "inmigrate" state, it will ensure that the
-#    guest remains paused once migration finishes, as if the -S option
-#    was passed on the command line.
+#    guest remains paused once migration finishes, as if the ``-S``
+#    option was passed on the command line.
 #
 #    In the "suspended" state, it will completely stop the VM and cause
 #    a transition to the "paused" state.  (Since 9.0)
@@ -161,7 +161,7 @@
 # .. note:: This command will succeed if the guest is currently running.
 #    It will also succeed if the guest is in the "inmigrate" state; in
 #    this case, the effect of the command is to make sure the guest
-#    starts once migration finishes, removing the effect of the -S
+#    starts once migration finishes, removing the effect of the ``-S``
 #    command line option if it was passed.
 #
 #    If the VM was previously suspended, and not been reset or woken,
diff --git a/qapi/qdev.json b/qapi/qdev.json
index f5b35a814fe..d031fc3590d 100644
--- a/qapi/qdev.json
+++ b/qapi/qdev.json
@@ -59,7 +59,7 @@
 #        the 'docs/qdev-device-use.txt' file.
 #
 #     3. It's possible to list device properties by running QEMU with
-#        the "-device DEVICE,help" command-line argument, where DEVICE
+#        the ``-device DEVICE,help`` command-line argument, where DEVICE
 #        is the device's name.
 #
 # Example:
diff --git a/qapi/run-state.json b/qapi/run-state.json
index dc524234ace..252d7d6afa7 100644
--- a/qapi/run-state.json
+++ b/qapi/run-state.json
@@ -146,7 +146,7 @@
 # @reason: The @ShutdownCause which resulted in the SHUTDOWN.
 #     (since 4.0)
 #
-# .. note:: If the command-line option "-no-shutdown" has been
+# .. note:: If the command-line option ``-no-shutdown`` has been
 #    specified, qemu will not exit, and a STOP event will eventually
 #    follow the SHUTDOWN event.
 #
diff --git a/qapi/sockets.json b/qapi/sockets.json
index 3970118bf4e..4d78d2ccb77 100644
--- a/qapi/sockets.json
+++ b/qapi/sockets.json
@@ -181,7 +181,7 @@
 #
 # .. note:: This type is deprecated in favor of SocketAddress.  The
 #    difference between SocketAddressLegacy and SocketAddress is that
-#    the latter has fewer {} on the wire.
+#    the latter has fewer ``{}`` on the wire.
 #
 # Since: 1.3
 ##
diff --git a/qapi/ui.json b/qapi/ui.json
index a1999965e44..5bcccbfc930 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -1268,7 +1268,7 @@
 # Since: 2.6
 #
 # .. note:: The consoles are visible in the qom tree, under
-#    /backend/console[$index]. They have a device link and head
+#    ``/backend/console[$index]``. They have a device link and head
 #    property, so it is possible to map which console belongs to which
 #    device and display.
 #
-- 
2.45.0



^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v2 13/21] qapi/parser: don't parse rST markup as section headers
  2024-06-26 22:21 [PATCH v2 00/21] qapi: convert "Note" and "Example" sections to rST John Snow
                   ` (11 preceding siblings ...)
  2024-06-26 22:21 ` [PATCH v2 12/21] qapi: add markup to " John Snow
@ 2024-06-26 22:21 ` John Snow
  2024-06-27  7:47   ` Markus Armbruster
  2024-06-26 22:21 ` [PATCH v2 14/21] docs/qapidoc: factor out do_parse() John Snow
                   ` (7 subsequent siblings)
  20 siblings, 1 reply; 44+ messages in thread
From: John Snow @ 2024-06-26 22:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Markus Armbruster, Philippe Mathieu-Daudé, Lukas Straub,
	Igor Mammedov, Jason Wang, Yanan Wang, Hanna Reitz,
	Konstantin Kostiuk, Stefan Berger, John Snow

The double-colon synax is rST formatting that precedes a literal code
block. We do not want to capture these as QAPI-specific sections.

Coerce blocks that start with e.g. "Example::" to be parsed as untagged
paragraphs instead of special tagged sections.

Signed-off-by: John Snow <jsnow@redhat.com>
---
 scripts/qapi/parser.py          | 9 +++++++--
 tests/qapi-schema/doc-good.json | 3 +++
 tests/qapi-schema/doc-good.out  | 3 +++
 tests/qapi-schema/doc-good.txt  | 3 +++
 4 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py
index 0a13f0f541a..6ad5663e545 100644
--- a/scripts/qapi/parser.py
+++ b/scripts/qapi/parser.py
@@ -544,10 +544,15 @@ def get_doc(self) -> 'QAPIDoc':
                         line = self.get_doc_indented(doc)
                     no_more_args = True
                 elif match := re.match(
-                        r'(Returns|Errors|Since|Notes?|Examples?|TODO): *',
-                        line):
+                        r'(Returns|Errors|Since|Notes?|Examples?|TODO)'
+                        r'(?!::): *',
+                        line,
+                ):
                     # tagged section
 
+                    # Note: "sections" with two colons are left alone as
+                    # rST markup and not interpreted as a section heading.
+
                     # TODO: Remove this error sometime in 2025 or so
                     # after we've fully transitioned to the new qapidoc
                     # generator.
diff --git a/tests/qapi-schema/doc-good.json b/tests/qapi-schema/doc-good.json
index 32ff910b4f8..107123f8a8d 100644
--- a/tests/qapi-schema/doc-good.json
+++ b/tests/qapi-schema/doc-good.json
@@ -181,6 +181,9 @@
 #  - *verbatim*
 #  - {braces}
 #
+# Note::
+#    Ceci n'est pas une note
+#
 # Since: 2.10
 ##
 { 'command': 'cmd',
diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out
index 631dc9f8dad..bd876b6542d 100644
--- a/tests/qapi-schema/doc-good.out
+++ b/tests/qapi-schema/doc-good.out
@@ -190,6 +190,9 @@ frobnicate
     section=Examples
  - *verbatim*
  - {braces}
+    section=None
+Note::
+   Ceci n'est pas une note
     section=Since
 2.10
 doc symbol=cmd-boxed
diff --git a/tests/qapi-schema/doc-good.txt b/tests/qapi-schema/doc-good.txt
index d8bfa742c2f..30d457e5488 100644
--- a/tests/qapi-schema/doc-good.txt
+++ b/tests/qapi-schema/doc-good.txt
@@ -231,6 +231,9 @@ Examples
    - *verbatim*
    - {braces}
 
+Note::
+   Ceci n'est pas une note
+
 
 Since
 ~~~~~
-- 
2.45.0



^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v2 14/21] docs/qapidoc: factor out do_parse()
  2024-06-26 22:21 [PATCH v2 00/21] qapi: convert "Note" and "Example" sections to rST John Snow
                   ` (12 preceding siblings ...)
  2024-06-26 22:21 ` [PATCH v2 13/21] qapi/parser: don't parse rST markup as section headers John Snow
@ 2024-06-26 22:21 ` John Snow
  2024-06-28 13:08   ` Markus Armbruster
  2024-06-26 22:21 ` [PATCH v2 15/21] docs/qapidoc: create qmp-example directive John Snow
                   ` (6 subsequent siblings)
  20 siblings, 1 reply; 44+ messages in thread
From: John Snow @ 2024-06-26 22:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Markus Armbruster, Philippe Mathieu-Daudé, Lukas Straub,
	Igor Mammedov, Jason Wang, Yanan Wang, Hanna Reitz,
	Konstantin Kostiuk, Stefan Berger, John Snow

Factor out the compatibility parser helper so it can be shared by other
directives.

Signed-off-by: John Snow <jsnow@redhat.com>
---
 docs/sphinx/qapidoc.py | 64 +++++++++++++++++++++++-------------------
 1 file changed, 35 insertions(+), 29 deletions(-)

diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py
index efcd84656fa..43dd99e21e6 100644
--- a/docs/sphinx/qapidoc.py
+++ b/docs/sphinx/qapidoc.py
@@ -494,7 +494,41 @@ def visit_module(self, name):
         super().visit_module(name)
 
 
-class QAPIDocDirective(Directive):
+class NestedDirective(Directive):
+    def run(self):
+        raise NotImplementedError
+
+    def do_parse(self, rstlist, node):
+        """
+        Parse rST source lines and add them to the specified node
+
+        Take the list of rST source lines rstlist, parse them as
+        rST, and add the resulting docutils nodes as children of node.
+        The nodes are parsed in a way that allows them to include
+        subheadings (titles) without confusing the rendering of
+        anything else.
+        """
+        # This is from kerneldoc.py -- it works around an API change in
+        # Sphinx between 1.6 and 1.7. Unlike kerneldoc.py, we use
+        # sphinx.util.nodes.nested_parse_with_titles() rather than the
+        # plain self.state.nested_parse(), and so we can drop the saving
+        # of title_styles and section_level that kerneldoc.py does,
+        # because nested_parse_with_titles() does that for us.
+        if USE_SSI:
+            with switch_source_input(self.state, rstlist):
+                nested_parse_with_titles(self.state, rstlist, node)
+        else:
+            save = self.state.memo.reporter
+            self.state.memo.reporter = AutodocReporter(
+                rstlist, self.state.memo.reporter
+            )
+            try:
+                nested_parse_with_titles(self.state, rstlist, node)
+            finally:
+                self.state.memo.reporter = save
+
+
+class QAPIDocDirective(NestedDirective):
     """Extract documentation from the specified QAPI .json file"""
 
     required_argument = 1
@@ -532,34 +566,6 @@ def run(self):
             # so they are displayed nicely to the user
             raise ExtensionError(str(err)) from err
 
-    def do_parse(self, rstlist, node):
-        """Parse rST source lines and add them to the specified node
-
-        Take the list of rST source lines rstlist, parse them as
-        rST, and add the resulting docutils nodes as children of node.
-        The nodes are parsed in a way that allows them to include
-        subheadings (titles) without confusing the rendering of
-        anything else.
-        """
-        # This is from kerneldoc.py -- it works around an API change in
-        # Sphinx between 1.6 and 1.7. Unlike kerneldoc.py, we use
-        # sphinx.util.nodes.nested_parse_with_titles() rather than the
-        # plain self.state.nested_parse(), and so we can drop the saving
-        # of title_styles and section_level that kerneldoc.py does,
-        # because nested_parse_with_titles() does that for us.
-        if USE_SSI:
-            with switch_source_input(self.state, rstlist):
-                nested_parse_with_titles(self.state, rstlist, node)
-        else:
-            save = self.state.memo.reporter
-            self.state.memo.reporter = AutodocReporter(
-                rstlist, self.state.memo.reporter
-            )
-            try:
-                nested_parse_with_titles(self.state, rstlist, node)
-            finally:
-                self.state.memo.reporter = save
-
 
 def setup(app):
     """Register qapi-doc directive with Sphinx"""
-- 
2.45.0



^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v2 15/21] docs/qapidoc: create qmp-example directive
  2024-06-26 22:21 [PATCH v2 00/21] qapi: convert "Note" and "Example" sections to rST John Snow
                   ` (13 preceding siblings ...)
  2024-06-26 22:21 ` [PATCH v2 14/21] docs/qapidoc: factor out do_parse() John Snow
@ 2024-06-26 22:21 ` John Snow
  2024-06-28 13:24   ` Markus Armbruster
  2024-06-26 22:21 ` [PATCH v2 16/21] docs/qapidoc: add QMP highlighting to annotated qmp-example blocks John Snow
                   ` (5 subsequent siblings)
  20 siblings, 1 reply; 44+ messages in thread
From: John Snow @ 2024-06-26 22:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Markus Armbruster, Philippe Mathieu-Daudé, Lukas Straub,
	Igor Mammedov, Jason Wang, Yanan Wang, Hanna Reitz,
	Konstantin Kostiuk, Stefan Berger, John Snow

This is a directive that creates a syntactic sugar for creating
"Example" boxes very similar to the ones already used in the bitmaps.rst
document, please see e.g.
https://www.qemu.org/docs/master/interop/bitmaps.html#creation-block-dirty-bitmap-add

In its simplest form, when a custom title is not needed or wanted, and
the example body is *solely* a QMP example:

```
.. qmp-example::

   {body}
```

is syntactic sugar for:

```
.. admonition:: Example:

   .. code-block:: QMP

      {body}
```

When a custom, plaintext title that describes the example is desired,
this form:

```
.. qmp-example::
   :title: Defrobnification

   {body}
```

Is syntactic sugar for:

```
.. admonition:: Example: Defrobnification

   .. code-block:: QMP

      {body}
```

Lastly, when Examples are multi-step processes that require non-QMP
exposition, have lengthy titles, or otherwise involve prose with rST
markup (lists, cross-references, etc), the most complex form:

```
.. qmp-example::
   :annotated:

   This example shows how to use `foo-command`::

     {body}
```

Is desugared to:

```
.. admonition:: Example:

   This example shows how to use `foo-command`::

     {body}

   For more information, please see `frobnozz`.
```

The primary benefit here being documentation source consistently using
the same directive for all forms of examples to ensure consistent visual
styling, and ensuring all relevant prose is visually grouped alongside
the code literal block.

Note that as of this commit, the code-block rST syntax "::" does not
apply QMP highlighting; you would need to use ".. code-block:: QMP". The
very next commit changes this behavior to assume all "::" code blocks
within this directive are QMP blocks.

Signed-off-by: John Snow <jsnow@redhat.com>
---
 docs/sphinx/qapidoc.py | 60 ++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 58 insertions(+), 2 deletions(-)

diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py
index 43dd99e21e6..a2fa05fc491 100644
--- a/docs/sphinx/qapidoc.py
+++ b/docs/sphinx/qapidoc.py
@@ -27,16 +27,19 @@
 import os
 import re
 import textwrap
+from typing import List
 
 from docutils import nodes
-from docutils.parsers.rst import Directive, directives
+from docutils.parsers.rst import directives
 from docutils.statemachine import ViewList
 from qapi.error import QAPIError, QAPISemError
 from qapi.gen import QAPISchemaVisitor
 from qapi.schema import QAPISchema
 
 import sphinx
+from sphinx.directives.code import CodeBlock
 from sphinx.errors import ExtensionError
+from sphinx.util.docutils import SphinxDirective
 from sphinx.util.nodes import nested_parse_with_titles
 
 
@@ -494,7 +497,7 @@ def visit_module(self, name):
         super().visit_module(name)
 
 
-class NestedDirective(Directive):
+class NestedDirective(SphinxDirective):
     def run(self):
         raise NotImplementedError
 
@@ -567,10 +570,63 @@ def run(self):
             raise ExtensionError(str(err)) from err
 
 
+class QMPExample(CodeBlock, NestedDirective):
+    """
+    Custom admonition for QMP code examples.
+
+    When the :annotated: option is present, the body of this directive
+    is parsed as normal rST instead. Code blocks must be explicitly
+    written by the user, but this allows for intermingling explanatory
+    paragraphs with arbitrary rST syntax and code blocks for more
+    involved examples.
+
+    When :annotated: is absent, the directive body is treated as a
+    simple standalone QMP code block literal.
+    """
+
+    required_argument = 0
+    optional_arguments = 0
+    has_content = True
+    option_spec = {
+        "annotated": directives.flag,
+        "title": directives.unchanged,
+    }
+
+    def admonition_wrap(self, *content) -> List[nodes.Node]:
+        title = "Example:"
+        if "title" in self.options:
+            title = f"{title} {self.options['title']}"
+
+        admon = nodes.admonition(
+            "",
+            nodes.title("", title),
+            *content,
+            classes=["admonition", "admonition-example"],
+        )
+        return [admon]
+
+    def run_annotated(self) -> List[nodes.Node]:
+        content_node: nodes.Element = nodes.section()
+        self.do_parse(self.content, content_node)
+        return content_node.children
+
+    def run(self) -> List[nodes.Node]:
+        annotated = "annotated" in self.options
+
+        if annotated:
+            content_nodes = self.run_annotated()
+        else:
+            self.arguments = ["QMP"]
+            content_nodes = super().run()
+
+        return self.admonition_wrap(*content_nodes)
+
+
 def setup(app):
     """Register qapi-doc directive with Sphinx"""
     app.add_config_value("qapidoc_srctree", None, "env")
     app.add_directive("qapi-doc", QAPIDocDirective)
+    app.add_directive("qmp-example", QMPExample)
 
     return {
         "version": __version__,
-- 
2.45.0



^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v2 16/21] docs/qapidoc: add QMP highlighting to annotated qmp-example blocks
  2024-06-26 22:21 [PATCH v2 00/21] qapi: convert "Note" and "Example" sections to rST John Snow
                   ` (14 preceding siblings ...)
  2024-06-26 22:21 ` [PATCH v2 15/21] docs/qapidoc: create qmp-example directive John Snow
@ 2024-06-26 22:21 ` John Snow
  2024-06-26 22:21 ` [PATCH v2 17/21] docs/sphinx: add CSS styling for qmp-example directive John Snow
                   ` (4 subsequent siblings)
  20 siblings, 0 replies; 44+ messages in thread
From: John Snow @ 2024-06-26 22:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Markus Armbruster, Philippe Mathieu-Daudé, Lukas Straub,
	Igor Mammedov, Jason Wang, Yanan Wang, Hanna Reitz,
	Konstantin Kostiuk, Stefan Berger, John Snow

For any code literal blocks inside of a qmp-example directive, apply and
enforce the QMP lexer/highlighter to those blocks.

This way, you won't need to write:

```
.. qmp-example::
   :annotated:

   Blah blah

   .. code-block:: QMP

      -> { "lorem": "ipsum" }
```

But instead, simply:

```
.. qmp-example::
   :annotated:

   Blah blah::

     -> { "lorem": "ipsum" }
```

Once the directive block is exited, whatever the previous default
highlight language was will be restored; localizing the forced QMP
lexing to exclusively this directive.

Signed-off-by: John Snow <jsnow@redhat.com>
---
 docs/sphinx/qapidoc.py | 53 ++++++++++++++++++++++++++++++++++++++----
 1 file changed, 49 insertions(+), 4 deletions(-)

diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py
index a2fa05fc491..c8c404ad1b0 100644
--- a/docs/sphinx/qapidoc.py
+++ b/docs/sphinx/qapidoc.py
@@ -26,6 +26,7 @@
 
 import os
 import re
+import sys
 import textwrap
 from typing import List
 
@@ -37,6 +38,7 @@
 from qapi.schema import QAPISchema
 
 import sphinx
+from sphinx import addnodes
 from sphinx.directives.code import CodeBlock
 from sphinx.errors import ExtensionError
 from sphinx.util.docutils import SphinxDirective
@@ -575,10 +577,10 @@ class QMPExample(CodeBlock, NestedDirective):
     Custom admonition for QMP code examples.
 
     When the :annotated: option is present, the body of this directive
-    is parsed as normal rST instead. Code blocks must be explicitly
-    written by the user, but this allows for intermingling explanatory
-    paragraphs with arbitrary rST syntax and code blocks for more
-    involved examples.
+    is parsed as normal rST, but with any '::' code blocks set to use
+    the QMP lexer. Code blocks must be explicitly written by the user,
+    but this allows for intermingling explanatory paragraphs with
+    arbitrary rST syntax and code blocks for more involved examples.
 
     When :annotated: is absent, the directive body is treated as a
     simple standalone QMP code block literal.
@@ -592,6 +594,33 @@ class QMPExample(CodeBlock, NestedDirective):
         "title": directives.unchanged,
     }
 
+    def _highlightlang(self) -> addnodes.highlightlang:
+        """Return the current highlightlang setting for the document"""
+        node = None
+        doc = self.state.document
+
+        if hasattr(doc, "findall"):
+            # docutils >= 0.18.1
+            for node in doc.findall(addnodes.highlightlang):
+                pass
+        else:
+            for elem in doc.traverse():
+                if isinstance(elem, addnodes.highlightlang):
+                    node = elem
+
+        if node:
+            return node
+
+        # No explicit directive found, use defaults
+        node = addnodes.highlightlang(
+            lang=self.env.config.highlight_language,
+            force=False,
+            # Yes, Sphinx uses this value to effectively disable line
+            # numbers and not 0 or None or -1 or something. ¯\_(ツ)_/¯
+            linenothreshold=sys.maxsize,
+        )
+        return node
+
     def admonition_wrap(self, *content) -> List[nodes.Node]:
         title = "Example:"
         if "title" in self.options:
@@ -606,8 +635,24 @@ def admonition_wrap(self, *content) -> List[nodes.Node]:
         return [admon]
 
     def run_annotated(self) -> List[nodes.Node]:
+        lang_node = self._highlightlang()
+
         content_node: nodes.Element = nodes.section()
+
+        # Configure QMP highlighting for "::" blocks, if needed
+        if lang_node["lang"] != "QMP":
+            content_node += addnodes.highlightlang(
+                lang="QMP",
+                force=False,  # "True" ignores lexing errors
+                linenothreshold=lang_node["linenothreshold"],
+            )
+
         self.do_parse(self.content, content_node)
+
+        # Restore prior language highlighting, if needed
+        if lang_node["lang"] != "QMP":
+            content_node += addnodes.highlightlang(**lang_node.attributes)
+
         return content_node.children
 
     def run(self) -> List[nodes.Node]:
-- 
2.45.0



^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v2 17/21] docs/sphinx: add CSS styling for qmp-example directive
  2024-06-26 22:21 [PATCH v2 00/21] qapi: convert "Note" and "Example" sections to rST John Snow
                   ` (15 preceding siblings ...)
  2024-06-26 22:21 ` [PATCH v2 16/21] docs/qapidoc: add QMP highlighting to annotated qmp-example blocks John Snow
@ 2024-06-26 22:21 ` John Snow
  2024-06-26 22:21 ` [PATCH v2 18/21] qapi: convert "Example" sections without titles John Snow
                   ` (3 subsequent siblings)
  20 siblings, 0 replies; 44+ messages in thread
From: John Snow @ 2024-06-26 22:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Markus Armbruster, Philippe Mathieu-Daudé, Lukas Straub,
	Igor Mammedov, Jason Wang, Yanan Wang, Hanna Reitz,
	Konstantin Kostiuk, Stefan Berger, Harmonie Snow, John Snow

From: Harmonie Snow <harmonie@gmail.com>

Add CSS styling for qmp-example directives to increase readability and
consistently style all example blocks.

Signed-off-by: Harmonie Snow <harmonie@gmail.com>
Signed-off-by: John Snow <jsnow@redhat.com>
---
 docs/sphinx-static/theme_overrides.css | 46 ++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/docs/sphinx-static/theme_overrides.css b/docs/sphinx-static/theme_overrides.css
index c70ef951286..f3223af62b2 100644
--- a/docs/sphinx-static/theme_overrides.css
+++ b/docs/sphinx-static/theme_overrides.css
@@ -87,6 +87,52 @@ div[class^="highlight"] pre {
     padding-bottom: 1px;
 }
 
+/* qmp-example directive styling */
+
+.rst-content .admonition-example {
+    background-color: #fcfcfc;
+    padding: 0px;
+}
+
+.rst-content .admonition-example > .admonition-title {
+    background-color: #338254;
+    margin: 0px;
+}
+
+.rst-content .admonition-example > div[class^=highlight] {
+    border-top: 1px solid #d7f0d7;
+    border-bottom: 1px solid #d7f0d7;
+    border-left: 3px solid #d7f0d7;
+    border-right: 3px solid #d7f0d7;
+}
+
+.rst-content .admonition-example .highlight {
+    background: linear-gradient(#d9f1d9 1%, #ecf8ec 10%,
+                                #ecf8ec 90%, #d9f1d9 99%);
+}
+
+.rst-content .admonition-example > .admonition-title:before {
+    content: "🧩";
+}
+
+.rst-content .admonition-example > .admonition-title p {
+    margin: 0px;
+}
+
+.rst-content .admonition-example p {
+    padding: 15px 10px;
+    margin: 0px;
+    background-color: #fafafa;
+    border-left: 1px solid #ededed;
+    border-right: 1px solid #ededed;
+}
+
+.rst-content .admonition-example > .admonition  {
+    background-color: #fcfcfc;
+}
+
+/* end qmp-example styling */
+
 @media screen {
 
     /* content column
-- 
2.45.0



^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v2 18/21] qapi: convert "Example" sections without titles
  2024-06-26 22:21 [PATCH v2 00/21] qapi: convert "Note" and "Example" sections to rST John Snow
                   ` (16 preceding siblings ...)
  2024-06-26 22:21 ` [PATCH v2 17/21] docs/sphinx: add CSS styling for qmp-example directive John Snow
@ 2024-06-26 22:21 ` John Snow
  2024-06-26 22:21 ` [PATCH v2 19/21] qapi: convert "Example" sections with titles John Snow
                   ` (2 subsequent siblings)
  20 siblings, 0 replies; 44+ messages in thread
From: John Snow @ 2024-06-26 22:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Markus Armbruster, Philippe Mathieu-Daudé, Lukas Straub,
	Igor Mammedov, Jason Wang, Yanan Wang, Hanna Reitz,
	Konstantin Kostiuk, Stefan Berger, John Snow

Use the no-option form of ".. qmp-example::" to convert any Examples
that do not have any form of caption or explanation whatsoever.

See commit-3: "docs/qapidoc: create qmp-example directive", for a
              detailed explanation of this custom directive syntax.

See commit+3: "qapi: remove "Example" doc section" for a detailed
              explanation of why.

Signed-off-by: John Snow <jsnow@redhat.com>
---
 qapi/acpi.json           |  4 +--
 qapi/block-core.json     | 64 +++++++++++++++++++++-------------------
 qapi/block.json          | 18 ++++++-----
 qapi/char.json           | 24 +++++++++------
 qapi/control.json        |  8 ++---
 qapi/dump.json           |  8 ++---
 qapi/machine-target.json |  2 +-
 qapi/machine.json        | 38 ++++++++++++------------
 qapi/migration.json      | 58 ++++++++++++++++++------------------
 qapi/misc-target.json    | 22 +++++++-------
 qapi/misc.json           | 32 ++++++++++----------
 qapi/net.json            | 20 +++++++------
 qapi/pci.json            |  2 +-
 qapi/qdev.json           | 10 ++++---
 qapi/qom.json            |  8 ++---
 qapi/replay.json         |  8 ++---
 qapi/rocker.json         |  8 ++---
 qapi/run-state.json      | 30 +++++++++----------
 qapi/tpm.json            |  6 ++--
 qapi/trace.json          |  4 +--
 qapi/transaction.json    |  2 +-
 qapi/ui.json             | 34 ++++++++++-----------
 qapi/vfio.json           |  2 +-
 qapi/virtio.json         |  2 +-
 qapi/yank.json           |  4 +--
 25 files changed, 216 insertions(+), 202 deletions(-)

diff --git a/qapi/acpi.json b/qapi/acpi.json
index aa4dbe57943..045dab6228b 100644
--- a/qapi/acpi.json
+++ b/qapi/acpi.json
@@ -111,7 +111,7 @@
 #
 # Since: 2.1
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-acpi-ospm-status" }
 #     <- { "return": [ { "device": "d1", "slot": "0", "slot-type": "DIMM", "source": 1, "status": 0},
@@ -131,7 +131,7 @@
 #
 # Since: 2.1
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "ACPI_DEVICE_OST",
 #          "data": { "info": { "device": "d1", "slot": "0",
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 9ef23ec02ae..4e0f0395146 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -764,7 +764,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-block" }
 #     <- {
@@ -1168,7 +1168,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-blockstats" }
 #     <- {
@@ -1461,7 +1461,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "block_resize",
 #          "arguments": { "device": "scratch", "size": 1073741824 } }
@@ -1682,7 +1682,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "blockdev-snapshot-sync",
 #          "arguments": { "device": "ide-hd0",
@@ -1715,7 +1715,7 @@
 #
 # Since: 2.5
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "blockdev-add",
 #          "arguments": { "driver": "qcow2",
@@ -1861,7 +1861,7 @@
 #
 # Since: 1.3
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "block-commit",
 #          "arguments": { "device": "virtio0",
@@ -1899,7 +1899,7 @@
 #
 # Since: 1.6
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "drive-backup",
 #          "arguments": { "device": "drive0",
@@ -1925,7 +1925,7 @@
 #
 # Since: 2.3
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "blockdev-backup",
 #          "arguments": { "device": "src-id",
@@ -1949,7 +1949,7 @@
 #
 # Since: 2.0
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-named-block-nodes" }
 #     <- { "return": [ { "ro":false,
@@ -2130,7 +2130,7 @@
 #
 # Since: 1.3
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "drive-mirror",
 #          "arguments": { "device": "ide-hd0",
@@ -2307,7 +2307,7 @@
 #
 # Since: 2.4
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "block-dirty-bitmap-add",
 #          "arguments": { "node": "drive0", "name": "bitmap0" } }
@@ -2331,7 +2331,7 @@
 #
 # Since: 2.4
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "block-dirty-bitmap-remove",
 #          "arguments": { "node": "drive0", "name": "bitmap0" } }
@@ -2354,7 +2354,7 @@
 #
 # Since: 2.4
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "block-dirty-bitmap-clear",
 #          "arguments": { "node": "drive0", "name": "bitmap0" } }
@@ -2375,7 +2375,7 @@
 #
 # Since: 4.0
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "block-dirty-bitmap-enable",
 #          "arguments": { "node": "drive0", "name": "bitmap0" } }
@@ -2396,7 +2396,7 @@
 #
 # Since: 4.0
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "block-dirty-bitmap-disable",
 #          "arguments": { "node": "drive0", "name": "bitmap0" } }
@@ -2428,7 +2428,7 @@
 #
 # Since: 4.0
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "block-dirty-bitmap-merge",
 #          "arguments": { "node": "drive0", "target": "bitmap0",
@@ -2537,7 +2537,7 @@
 #
 # Since: 2.6
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "blockdev-mirror",
 #          "arguments": { "device": "ide-hd0",
@@ -2862,7 +2862,7 @@
 #
 # Since: 1.1
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "block-stream",
 #          "arguments": { "device": "virtio0",
@@ -4801,7 +4801,7 @@
 #
 # Since: 2.9
 #
-# Examples:
+# .. qmp-example::
 #
 #     -> { "execute": "blockdev-add",
 #          "arguments": {
@@ -4815,6 +4815,8 @@
 #         }
 #     <- { "return": {} }
 #
+# .. qmp-example::
+#
 #     -> { "execute": "blockdev-add",
 #          "arguments": {
 #               "driver": "qcow2",
@@ -4899,7 +4901,7 @@
 #
 # Since: 2.9
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "blockdev-add",
 #          "arguments": {
@@ -5548,7 +5550,7 @@
 # .. note:: If action is "stop", a STOP event will eventually follow the
 #    BLOCK_IO_ERROR event.
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "BLOCK_IMAGE_CORRUPTED",
 #          "data": { "device": "", "node-name": "drive", "fatal": false,
@@ -5597,7 +5599,7 @@
 #
 # Since: 0.13
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "BLOCK_IO_ERROR",
 #          "data": { "device": "ide0-hd1",
@@ -5637,7 +5639,7 @@
 #
 # Since: 1.1
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "BLOCK_JOB_COMPLETED",
 #          "data": { "type": "stream", "device": "virtio-disk0",
@@ -5672,7 +5674,7 @@
 #
 # Since: 1.1
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "BLOCK_JOB_CANCELLED",
 #          "data": { "type": "stream", "device": "virtio-disk0",
@@ -5701,7 +5703,7 @@
 #
 # Since: 1.3
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "BLOCK_JOB_ERROR",
 #          "data": { "device": "ide0-hd1",
@@ -5736,7 +5738,7 @@
 #
 # Since: 1.3
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "BLOCK_JOB_READY",
 #          "data": { "device": "drive0", "type": "mirror", "speed": 0,
@@ -5764,7 +5766,7 @@
 #
 # Since: 2.12
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "BLOCK_JOB_PENDING",
 #          "data": { "type": "mirror", "id": "backup_1" },
@@ -5838,7 +5840,7 @@
 #
 # Since: 2.3
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "block-set-write-threshold",
 #          "arguments": { "node-name": "mydev",
@@ -5989,7 +5991,7 @@
 #
 # Since: 2.0
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "QUORUM_FAILURE",
 #          "data": { "reference": "usr1", "sector-num": 345435, "sectors-count": 5 },
@@ -6077,7 +6079,7 @@
 #
 # Since: 1.7
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "blockdev-snapshot-internal-sync",
 #          "arguments": { "device": "ide-hd0",
@@ -6116,7 +6118,7 @@
 #
 # Since: 1.7
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "blockdev-snapshot-delete-internal-sync",
 #          "arguments": { "device": "ide-hd0",
diff --git a/qapi/block.json b/qapi/block.json
index ea81d9e1921..c8e52bc2d29 100644
--- a/qapi/block.json
+++ b/qapi/block.json
@@ -117,7 +117,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "eject", "arguments": { "id": "ide1-0-1" } }
 #     <- { "return": {} }
@@ -161,7 +161,7 @@
 #
 # Since: 2.5
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "blockdev-open-tray",
 #          "arguments": { "id": "ide0-1-0" } }
@@ -199,7 +199,7 @@
 #
 # Since: 2.5
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "blockdev-close-tray",
 #          "arguments": { "id": "ide0-1-0" } }
@@ -231,7 +231,7 @@
 #
 # Since: 2.12
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "blockdev-remove-medium",
 #          "arguments": { "id": "ide0-1-0" } }
@@ -272,7 +272,7 @@
 #
 # Since: 2.12
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "blockdev-add",
 #          "arguments": {
@@ -397,7 +397,7 @@
 #
 # Since: 1.1
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "DEVICE_TRAY_MOVED",
 #          "data": { "device": "ide1-cd0",
@@ -421,7 +421,7 @@
 #
 # Since: 3.0
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "PR_MANAGER_STATUS_CHANGED",
 #          "data": { "id": "pr-helper0",
@@ -463,7 +463,7 @@
 #
 # Since: 1.1
 #
-# Examples:
+# .. qmp-example::
 #
 #     -> { "execute": "block_set_io_throttle",
 #          "arguments": { "id": "virtio-blk-pci0/virtio-backend",
@@ -483,6 +483,8 @@
 #                         "iops_size": 0 } }
 #     <- { "return": {} }
 #
+# .. qmp-example::
+#
 #     -> { "execute": "block_set_io_throttle",
 #          "arguments": { "id": "ide0-1-0",
 #                         "bps": 1000000,
diff --git a/qapi/char.json b/qapi/char.json
index 5eabf8e7645..5e4aeb9799d 100644
--- a/qapi/char.json
+++ b/qapi/char.json
@@ -40,7 +40,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-chardev" }
 #     <- {
@@ -86,7 +86,7 @@
 #
 # Since: 2.0
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-chardev-backends" }
 #     <- {
@@ -141,7 +141,7 @@
 #
 # Since: 1.4
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "ringbuf-write",
 #          "arguments": { "device": "foo",
@@ -177,7 +177,7 @@
 #
 # Since: 1.4
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "ringbuf-read",
 #          "arguments": { "device": "foo",
@@ -699,19 +699,23 @@
 #
 # Since: 1.4
 #
-# Examples:
+# .. qmp-example::
 #
 #     -> { "execute" : "chardev-add",
 #          "arguments" : { "id" : "foo",
 #                          "backend" : { "type" : "null", "data" : {} } } }
 #     <- { "return": {} }
 #
+# .. qmp-example::
+#
 #     -> { "execute" : "chardev-add",
 #          "arguments" : { "id" : "bar",
 #                          "backend" : { "type" : "file",
 #                                        "data" : { "out" : "/tmp/bar.log" } } } }
 #     <- { "return": {} }
 #
+# .. qmp-example::
+#
 #     -> { "execute" : "chardev-add",
 #          "arguments" : { "id" : "baz",
 #                          "backend" : { "type" : "pty", "data" : {} } } }
@@ -735,13 +739,15 @@
 #
 # Since: 2.10
 #
-# Examples:
+# .. qmp-example::
 #
 #     -> { "execute" : "chardev-change",
 #          "arguments" : { "id" : "baz",
 #                          "backend" : { "type" : "pty", "data" : {} } } }
 #     <- { "return": { "pty" : "/dev/pty/42" } }
 #
+# .. qmp-example::
+#
 #     -> {"execute" : "chardev-change",
 #         "arguments" : {
 #             "id" : "charchannel2",
@@ -772,7 +778,7 @@
 #
 # Since: 1.4
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "chardev-remove", "arguments": { "id" : "foo" } }
 #     <- { "return": {} }
@@ -789,7 +795,7 @@
 #
 # Since: 2.10
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "chardev-send-break", "arguments": { "id" : "foo" } }
 #     <- { "return": {} }
@@ -810,7 +816,7 @@
 #
 # Since: 2.1
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "VSERPORT_CHANGE",
 #          "data": { "id": "channel0", "open": true },
diff --git a/qapi/control.json b/qapi/control.json
index fe2af45120b..950443df9d4 100644
--- a/qapi/control.json
+++ b/qapi/control.json
@@ -16,7 +16,7 @@
 #     the QMP greeting message.  If the field is not provided, it
 #     means no QMP capabilities will be enabled.  (since 2.12)
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "qmp_capabilities",
 #          "arguments": { "enable": [ "oob" ] } }
@@ -97,7 +97,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-version" }
 #     <- {
@@ -134,7 +134,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-commands" }
 #     <- {
@@ -165,7 +165,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "quit" }
 #     <- { "return": {} }
diff --git a/qapi/dump.json b/qapi/dump.json
index f9aee7ea1dd..d8145dad979 100644
--- a/qapi/dump.json
+++ b/qapi/dump.json
@@ -94,7 +94,7 @@
 #
 # Since: 1.2
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "dump-guest-memory",
 #          "arguments": { "paging": false, "protocol": "fd:dump" } }
@@ -150,7 +150,7 @@
 #
 # Since: 2.6
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-dump" }
 #     <- { "return": { "status": "active", "completed": 1024000,
@@ -171,7 +171,7 @@
 #
 # Since: 2.6
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "DUMP_COMPLETED",
 #          "data": { "result": { "total": 1090650112, "status": "completed",
@@ -202,7 +202,7 @@
 #
 # Since: 2.0
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-dump-guest-memory-capability" }
 #     <- { "return": { "formats":
diff --git a/qapi/machine-target.json b/qapi/machine-target.json
index a8d9ec87f59..7edb876b5c3 100644
--- a/qapi/machine-target.json
+++ b/qapi/machine-target.json
@@ -475,7 +475,7 @@
 #
 # Since: 8.2
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "CPU_POLARIZATION_CHANGE",
 #          "data": { "polarization": "horizontal" },
diff --git a/qapi/machine.json b/qapi/machine.json
index f15ad1b43e2..83f60b319c7 100644
--- a/qapi/machine.json
+++ b/qapi/machine.json
@@ -104,7 +104,7 @@
 #
 # Since: 2.12
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-cpus-fast" }
 #     <- { "return": [
@@ -221,7 +221,7 @@
 #
 # Since: 1.2
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-machines", "arguments": { "compat-props": true } }
 #     <- { "return": [
@@ -320,7 +320,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-uuid" }
 #     <- { "return": { "UUID": "550e8400-e29b-41d4-a716-446655440000" } }
@@ -354,7 +354,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "system_reset" }
 #     <- { "return": {} }
@@ -373,7 +373,7 @@
 #    request or that it has shut down.  Many guests will respond to this
 #    command by prompting the user in some way.
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "system_powerdown" }
 #     <- { "return": {} }
@@ -393,7 +393,7 @@
 # .. note:: Prior to 4.0, this command does nothing in case the guest
 #    isn't suspended.
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "system_wakeup" }
 #     <- { "return": {} }
@@ -444,7 +444,7 @@
 # .. note:: Prior to 2.1, this command was only supported for x86 and
 #    s390 VMs.
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "inject-nmi" }
 #     <- { "return": {} }
@@ -473,7 +473,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-kvm" }
 #     <- { "return": { "enabled": true, "present": true } }
@@ -842,7 +842,7 @@
 #
 # .. caution:: Errors were not reliably returned until 1.1.
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "memsave",
 #          "arguments": { "val": 10,
@@ -868,7 +868,7 @@
 #
 # .. caution:: Errors were not reliably returned until 1.1.
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "pmemsave",
 #          "arguments": { "val": 10,
@@ -929,7 +929,7 @@
 #
 # Since: 2.1
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-memdev" }
 #     <- { "return": [
@@ -1166,7 +1166,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-balloon" }
 #     <- { "return": {
@@ -1190,7 +1190,7 @@
 #
 # Since: 1.2
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "BALLOON_CHANGE",
 #          "data": { "actual": 944766976 },
@@ -1232,7 +1232,7 @@
 #
 # Since: 8.2
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-hv-balloon-status-report" }
 #     <- { "return": {
@@ -1253,7 +1253,7 @@
 #
 # Since: 8.2
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "HV_BALLOON_STATUS_REPORT",
 #          "data": { "committed": 816640000, "available": 3333054464 },
@@ -1285,7 +1285,7 @@
 # Return the amount of initially allocated and present hotpluggable
 # (if enabled) memory in bytes.
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-memory-size-summary" }
 #     <- { "return": { "base-memory": 4294967296, "plugged-memory": 0 } }
@@ -1564,7 +1564,7 @@
 #
 # Since: 2.1
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-memory-devices" }
 #     <- { "return": [ { "data":
@@ -1598,7 +1598,7 @@
 #
 # Since: 5.1
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "MEMORY_DEVICE_SIZE_CHANGE",
 #          "data": { "id": "vm0", "size": 1073741824,
@@ -1856,7 +1856,7 @@
 #
 # Since: 7.2
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "dumpdtb" }
 #          "arguments": { "filename": "fdt.dtb" } }
diff --git a/qapi/migration.json b/qapi/migration.json
index 26ad5e5e7a3..a4391ea7e6f 100644
--- a/qapi/migration.json
+++ b/qapi/migration.json
@@ -514,7 +514,7 @@
 #
 # Since: 1.2
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "migrate-set-capabilities" , "arguments":
 #          { "capabilities": [ { "capability": "xbzrle", "state": true } ] } }
@@ -532,7 +532,7 @@
 #
 # Since: 1.2
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-migrate-capabilities" }
 #     <- { "return": [
@@ -1053,7 +1053,7 @@
 #
 # Since: 2.4
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "migrate-set-parameters" ,
 #          "arguments": { "multifd-channels": 5 } }
@@ -1256,7 +1256,7 @@
 #
 # Since: 2.4
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-migrate-parameters" }
 #     <- { "return": {
@@ -1280,7 +1280,7 @@
 #
 # Since: 2.5
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "migrate-start-postcopy" }
 #     <- { "return": {} }
@@ -1296,7 +1296,7 @@
 #
 # Since: 2.4
 #
-# Example:
+# .. qmp-example::
 #
 #     <- {"timestamp": {"seconds": 1432121972, "microseconds": 744001},
 #         "event": "MIGRATION",
@@ -1315,7 +1315,7 @@
 #
 # Since: 2.6
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "timestamp": {"seconds": 1449669631, "microseconds": 239225},
 #           "event": "MIGRATION_PASS", "data": {"pass": 2} }
@@ -1399,7 +1399,7 @@
 #
 # Since: 3.1
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "timestamp": {"seconds": 2032141960, "microseconds": 417172},
 #          "event": "COLO_EXIT", "data": {"mode": "primary", "reason": "request" } }
@@ -1442,7 +1442,7 @@
 #
 # Since: 2.8
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "x-colo-lost-heartbeat" }
 #     <- { "return": {} }
@@ -1461,7 +1461,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "migrate_cancel" }
 #     <- { "return": {} }
@@ -1477,7 +1477,7 @@
 #
 # Since: 2.11
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "migrate-continue" , "arguments":
 #          { "state": "pre-switchover" } }
@@ -1610,7 +1610,7 @@
 #     6. The 'uri' and 'channels' arguments are mutually exclusive;
 #        exactly one of the two should be present.
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "migrate", "arguments": { "uri": "tcp:0:4446" } }
 #     <- { "return": {} }
@@ -1689,7 +1689,7 @@
 #     5. The 'uri' and 'channels' arguments are mutually exclusive;
 #        exactly one of the two should be present.
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "migrate-incoming",
 #          "arguments": { "uri": "tcp:0:4446" } }
@@ -1740,7 +1740,7 @@
 #
 # Since: 1.1
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "xen-save-devices-state",
 #          "arguments": { "filename": "/tmp/save" } }
@@ -1758,7 +1758,7 @@
 #
 # Since: 1.3
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "xen-set-global-dirty-log",
 #          "arguments": { "enable": true } }
@@ -1778,7 +1778,7 @@
 #
 # Since: 2.7
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "xen-load-devices-state",
 #          "arguments": { "filename": "/tmp/resume" } }
@@ -1798,7 +1798,7 @@
 # @failover: true to do failover, false to stop.  Cannot be specified
 #     if 'enable' is true.  Default value is false.
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "xen-set-replication",
 #          "arguments": {"enable": true, "primary": false} }
@@ -1833,7 +1833,7 @@
 #
 # Returns: A @ReplicationStatus object showing the status.
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-xen-replication-status" }
 #     <- { "return": { "error": false } }
@@ -1849,7 +1849,7 @@
 #
 # Xen uses this command to notify replication to trigger a checkpoint.
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "xen-colo-do-checkpoint" }
 #     <- { "return": {} }
@@ -1887,7 +1887,7 @@
 #
 # Returns: A @COLOStatus object showing the status.
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-colo-status" }
 #     <- { "return": { "mode": "primary", "last-mode": "none", "reason": "request" } }
@@ -1905,7 +1905,7 @@
 #
 # @uri: the URI to be used for the recovery of migration stream.
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "migrate-recover",
 #          "arguments": { "uri": "tcp:192.168.1.200:12345" } }
@@ -1922,7 +1922,7 @@
 #
 # Pause a migration.  Currently it only supports postcopy.
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "migrate-pause" }
 #     <- { "return": {} }
@@ -1943,7 +1943,7 @@
 #
 # Since: 4.2
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "UNPLUG_PRIMARY",
 #          "data": { "device-id": "hostdev0" },
@@ -2182,7 +2182,7 @@
 #
 # Since: 7.1
 #
-# Example:
+# .. qmp-example::
 #
 #     -> {"execute": "set-vcpu-dirty-limit"}
 #         "arguments": { "dirty-rate": 200,
@@ -2206,7 +2206,7 @@
 #
 # Since: 7.1
 #
-# Example:
+# .. qmp-example::
 #
 #     -> {"execute": "cancel-vcpu-dirty-limit"},
 #         "arguments": { "cpu-index": 1 } }
@@ -2223,7 +2223,7 @@
 #
 # Since: 7.1
 #
-# Example:
+# .. qmp-example::
 #
 #     -> {"execute": "query-vcpu-dirty-limit"}
 #     <- {"return": [
@@ -2287,7 +2287,7 @@
 #
 # If @tag already exists, an error will be reported
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "snapshot-save",
 #          "arguments": {
@@ -2357,7 +2357,7 @@
 # device nodes that can have changed since the original @snapshot-save
 # command execution.
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "snapshot-load",
 #          "arguments": {
@@ -2418,7 +2418,7 @@
 # to determine completion and to fetch details of any errors that
 # arise.
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "snapshot-delete",
 #          "arguments": {
diff --git a/qapi/misc-target.json b/qapi/misc-target.json
index 2d7d4d89bd5..8d70bd24d8c 100644
--- a/qapi/misc-target.json
+++ b/qapi/misc-target.json
@@ -11,7 +11,7 @@
 #
 # Since: 2.1
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "rtc-reset-reinjection" }
 #     <- { "return": {} }
@@ -133,7 +133,7 @@
 #
 # Since: 2.12
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-sev" }
 #     <- { "return": { "enabled": true, "api-major" : 0, "api-minor" : 0,
@@ -164,7 +164,7 @@
 #
 # Since: 2.12
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-sev-launch-measure" }
 #     <- { "return": { "data": "4l8LXeNlSPUDlXPJG5966/8%YZ" } }
@@ -209,7 +209,7 @@
 #
 # Since: 2.12
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-sev-capabilities" }
 #     <- { "return": { "pdh": "8CCDD8DDD", "cert-chain": "888CCCDDDEE",
@@ -263,7 +263,7 @@
 #
 # Since: 6.1
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute" : "query-sev-attestation-report",
 #                      "arguments": { "mnonce": "aaaaaaa" } }
@@ -283,7 +283,7 @@
 #
 # Since: 2.5
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "dump-skeys",
 #          "arguments": { "filename": "/tmp/skeys" } }
@@ -328,7 +328,7 @@
 #
 # Since: 2.6
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-gic-capabilities" }
 #     <- { "return": [{ "version": 2, "emulated": true, "kernel": false },
@@ -386,7 +386,7 @@
 #
 # Since: 6.2
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-sgx" }
 #     <- { "return": { "sgx": true, "sgx1" : true, "sgx2" : true,
@@ -405,7 +405,7 @@
 #
 # Since: 6.2
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-sgx-capabilities" }
 #     <- { "return": { "sgx": true, "sgx1" : true, "sgx2" : true,
@@ -480,7 +480,7 @@
 #
 # Since: 8.0
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "xen-event-list" }
 #     <- { "return": [
@@ -518,7 +518,7 @@
 #
 # Since: 8.0
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "xen-event-inject", "arguments": { "port": 1 } }
 #     <- { "return": { } }
diff --git a/qapi/misc.json b/qapi/misc.json
index b04efbadec6..4a6f3baeaed 100644
--- a/qapi/misc.json
+++ b/qapi/misc.json
@@ -30,7 +30,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "add_client", "arguments": { "protocol": "vnc",
 #                                                  "fdname": "myclient" } }
@@ -60,7 +60,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-name" }
 #     <- { "return": { "name": "qemu-name" } }
@@ -111,7 +111,7 @@
 #
 # Since: 2.0
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-iothreads" }
 #     <- { "return": [
@@ -144,7 +144,7 @@
 #    In the "suspended" state, it will completely stop the VM and cause
 #    a transition to the "paused" state.  (Since 9.0)
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "stop" }
 #     <- { "return": {} }
@@ -168,7 +168,7 @@
 #    this command will transition back to the "suspended" state.  (Since
 #    9.0)
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "cont" }
 #     <- { "return": {} }
@@ -192,7 +192,7 @@
 #
 # Since: 3.0
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "x-exit-preconfig" }
 #     <- { "return": {} }
@@ -232,7 +232,7 @@
 #
 #    * Commands that prompt the user for data don't currently work.
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "human-monitor-command",
 #          "arguments": { "command-line": "info kvm" } }
@@ -258,7 +258,7 @@
 #    The 'closefd' command can be used to explicitly close the file
 #    descriptor when it is no longer needed.
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "getfd", "arguments": { "fdname": "fd1" } }
 #     <- { "return": {} }
@@ -285,7 +285,7 @@
 #    The 'closefd' command can be used to explicitly close the file
 #    descriptor when it is no longer needed.
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "get-win32-socket",
 #          "arguments": { "info": "abcd123..", "fdname": "skclient" } }
@@ -302,7 +302,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "closefd", "arguments": { "fdname": "fd1" } }
 #     <- { "return": {} }
@@ -345,7 +345,7 @@
 #
 # Since: 1.2
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "add-fd", "arguments": { "fdset-id": 1 } }
 #     <- { "return": { "fdset-id": 1, "fd": 3 } }
@@ -374,7 +374,7 @@
 # .. note:: If @fd is not specified, all file descriptors in @fdset-id
 #    will be removed.
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "remove-fd", "arguments": { "fdset-id": 1, "fd": 3 } }
 #     <- { "return": {} }
@@ -420,7 +420,7 @@
 #
 # .. note:: The list of fd sets is shared by all monitor connections.
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-fdsets" }
 #     <- { "return": [
@@ -523,7 +523,7 @@
 #
 # Since: 1.5
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-command-line-options",
 #          "arguments": { "option": "option-rom" } }
@@ -565,7 +565,7 @@
 #
 # Since: 0.13
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "RTC_CHANGE",
 #          "data": { "offset": 78 },
@@ -592,7 +592,7 @@
 #
 # Since: 7.1
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "VFU_CLIENT_HANGUP",
 #          "data": { "vfu-id": "vfu1",
diff --git a/qapi/net.json b/qapi/net.json
index dd6c365c34d..9a723e56b50 100644
--- a/qapi/net.json
+++ b/qapi/net.json
@@ -26,7 +26,7 @@
 #    command will succeed even if the network adapter does not support
 #    link status notification.
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "set_link",
 #          "arguments": { "name": "e1000.0", "up": false } }
@@ -46,7 +46,7 @@
 # Errors:
 #     - If @type is not a valid network backend, DeviceNotFound
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "netdev_add",
 #          "arguments": { "type": "user", "id": "netdev1",
@@ -68,7 +68,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "netdev_del", "arguments": { "id": "netdev1" } }
 #     <- { "return": {} }
@@ -836,7 +836,7 @@
 #
 # Since: 1.6
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-rx-filter", "arguments": { "name": "vnet0" } }
 #     <- { "return": [
@@ -881,7 +881,7 @@
 #
 # Since: 1.6
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "NIC_RX_FILTER_CHANGED",
 #          "data": { "name": "vnet0",
@@ -930,7 +930,7 @@
 # switches.  This can be useful when network bonds fail-over the
 # active slave.
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "announce-self",
 #          "arguments": {
@@ -955,7 +955,7 @@
 #
 # Since: 4.2
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "FAILOVER_NEGOTIATED",
 #          "data": { "device-id": "net1" },
@@ -975,7 +975,7 @@
 #
 # Since: 7.2
 #
-# Examples:
+# .. qmp-example::
 #
 #     <- { "event": "NETDEV_STREAM_CONNECTED",
 #          "data": { "netdev-id": "netdev0",
@@ -983,6 +983,8 @@
 #                              "host": "::1", "type": "inet" } },
 #          "timestamp": { "seconds": 1666269863, "microseconds": 311222 } }
 #
+# .. qmp-example::
+#
 #     <- { "event": "NETDEV_STREAM_CONNECTED",
 #          "data": { "netdev-id": "netdev0",
 #                    "addr": { "path": "/tmp/qemu0", "type": "unix" } },
@@ -1001,7 +1003,7 @@
 #
 # Since: 7.2
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "NETDEV_STREAM_DISCONNECTED",
 #          "data": {"netdev-id": "netdev0"},
diff --git a/qapi/pci.json b/qapi/pci.json
index 8287d15dd0b..8e2ca560ee1 100644
--- a/qapi/pci.json
+++ b/qapi/pci.json
@@ -182,7 +182,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-pci" }
 #     <- { "return": [
diff --git a/qapi/qdev.json b/qapi/qdev.json
index d031fc3590d..e91ca0309df 100644
--- a/qapi/qdev.json
+++ b/qapi/qdev.json
@@ -62,7 +62,7 @@
 #        the ``-device DEVICE,help`` command-line argument, where DEVICE
 #        is the device's name.
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "device_add",
 #          "arguments": { "driver": "e1000", "id": "net1",
@@ -104,12 +104,14 @@
 #
 # Since: 0.14
 #
-# Examples:
+# .. qmp-example::
 #
 #     -> { "execute": "device_del",
 #          "arguments": { "id": "net1" } }
 #     <- { "return": {} }
 #
+# .. qmp-example::
+#
 #     -> { "execute": "device_del",
 #          "arguments": { "id": "/machine/peripheral-anon/device[0]" } }
 #     <- { "return": {} }
@@ -130,7 +132,7 @@
 #
 # Since: 1.5
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "DEVICE_DELETED",
 #          "data": { "device": "virtio-net-pci-0",
@@ -152,7 +154,7 @@
 #
 # Since: 6.2
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "DEVICE_UNPLUG_GUEST_ERROR",
 #          "data": { "device": "core1",
diff --git a/qapi/qom.json b/qapi/qom.json
index f582a1357b7..fb365e5ce6b 100644
--- a/qapi/qom.json
+++ b/qapi/qom.json
@@ -59,7 +59,7 @@
 #
 # Since: 1.2
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "qom-list",
 #          "arguments": { "path": "/chardevs" } }
@@ -139,7 +139,7 @@
 #
 # Since: 1.2
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "qom-set",
 #          "arguments": { "path": "/machine",
@@ -1154,7 +1154,7 @@
 #
 # Since: 2.0
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "object-add",
 #          "arguments": { "qom-type": "rng-random", "id": "rng1",
@@ -1176,7 +1176,7 @@
 #
 # Since: 2.0
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "object-del", "arguments": { "id": "rng1" } }
 #     <- { "return": {} }
diff --git a/qapi/replay.json b/qapi/replay.json
index d3559f9c8f7..35e0c4a6926 100644
--- a/qapi/replay.json
+++ b/qapi/replay.json
@@ -54,7 +54,7 @@
 #
 # Since: 5.2
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-replay" }
 #     <- { "return": { "mode": "play", "filename": "log.rr", "icount": 220414 } }
@@ -76,7 +76,7 @@
 #
 # Since: 5.2
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "replay-break", "arguments": { "icount": 220414 } }
 #     <- { "return": {} }
@@ -91,7 +91,7 @@
 #
 # Since: 5.2
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "replay-delete-break" }
 #     <- { "return": {} }
@@ -112,7 +112,7 @@
 #
 # Since: 5.2
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "replay-seek", "arguments": { "icount": 220414 } }
 #     <- { "return": {} }
diff --git a/qapi/rocker.json b/qapi/rocker.json
index 9f95e638309..2e63dcb3d6f 100644
--- a/qapi/rocker.json
+++ b/qapi/rocker.json
@@ -30,7 +30,7 @@
 #
 # Since: 2.4
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-rocker", "arguments": { "name": "sw1" } }
 #     <- { "return": {"name": "sw1", "ports": 2, "id": 1327446905938}}
@@ -98,7 +98,7 @@
 #
 # Since: 2.4
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-rocker-ports", "arguments": { "name": "sw1" } }
 #     <- { "return": [ {"duplex": "full", "enabled": true, "name": "sw1.1",
@@ -240,7 +240,7 @@
 #
 # Since: 2.4
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-rocker-of-dpa-flows",
 #          "arguments": { "name": "sw1" } }
@@ -315,7 +315,7 @@
 #
 # Since: 2.4
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-rocker-of-dpa-groups",
 #          "arguments": { "name": "sw1" } }
diff --git a/qapi/run-state.json b/qapi/run-state.json
index 252d7d6afa7..718a3c958e9 100644
--- a/qapi/run-state.json
+++ b/qapi/run-state.json
@@ -123,7 +123,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-status" }
 #     <- { "return": { "running": true,
@@ -152,7 +152,7 @@
 #
 # Since: 0.12
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "SHUTDOWN",
 #          "data": { "guest": true, "reason": "guest-shutdown" },
@@ -168,7 +168,7 @@
 #
 # Since: 0.12
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "POWERDOWN",
 #          "timestamp": { "seconds": 1267040730, "microseconds": 682951 } }
@@ -189,7 +189,7 @@
 #
 # Since: 0.12
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "RESET",
 #          "data": { "guest": false, "reason": "guest-reset" },
@@ -204,7 +204,7 @@
 #
 # Since: 0.12
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "STOP",
 #          "timestamp": { "seconds": 1267041730, "microseconds": 281295 } }
@@ -218,7 +218,7 @@
 #
 # Since: 0.12
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "RESUME",
 #          "timestamp": { "seconds": 1271770767, "microseconds": 582542 } }
@@ -233,7 +233,7 @@
 #
 # Since: 1.1
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "SUSPEND",
 #          "timestamp": { "seconds": 1344456160, "microseconds": 309119 } }
@@ -252,7 +252,7 @@
 #
 # Since: 1.2
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "SUSPEND_DISK",
 #          "timestamp": { "seconds": 1344456160, "microseconds": 309119 } }
@@ -267,7 +267,7 @@
 #
 # Since: 1.1
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "WAKEUP",
 #          "timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
@@ -289,7 +289,7 @@
 #
 # Since: 0.13
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "WATCHDOG",
 #          "data": { "action": "reset" },
@@ -382,7 +382,7 @@
 #
 # Since: 2.11
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "watchdog-set-action",
 #          "arguments": { "action": "inject-nmi" } }
@@ -406,7 +406,7 @@
 #
 # Since: 6.0
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "set-action",
 #          "arguments": { "reboot": "shutdown",
@@ -433,7 +433,7 @@
 #
 # Since: 1.5
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "GUEST_PANICKED",
 #          "data": { "action": "pause" },
@@ -453,7 +453,7 @@
 #
 # Since: 5.0
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "GUEST_CRASHLOADED",
 #          "data": { "action": "run" },
@@ -597,7 +597,7 @@
 #
 # Since: 5.2
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "MEMORY_FAILURE",
 #          "data": { "recipient": "hypervisor",
diff --git a/qapi/tpm.json b/qapi/tpm.json
index 1577b5c259d..a16a72edb98 100644
--- a/qapi/tpm.json
+++ b/qapi/tpm.json
@@ -31,7 +31,7 @@
 #
 # Since: 1.5
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-tpm-models" }
 #     <- { "return": [ "tpm-tis", "tpm-crb", "tpm-spapr" ] }
@@ -62,7 +62,7 @@
 #
 # Since: 1.5
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-tpm-types" }
 #     <- { "return": [ "passthrough", "emulator" ] }
@@ -168,7 +168,7 @@
 #
 # Since: 1.5
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-tpm" }
 #     <- { "return":
diff --git a/qapi/trace.json b/qapi/trace.json
index 9ebb6d9eaf5..eb5f63f5135 100644
--- a/qapi/trace.json
+++ b/qapi/trace.json
@@ -51,7 +51,7 @@
 #
 # Since: 2.2
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "trace-event-get-state",
 #          "arguments": { "name": "qemu_memalign" } }
@@ -74,7 +74,7 @@
 #
 # Since: 2.2
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "trace-event-set-state",
 #          "arguments": { "name": "qemu_memalign", "enable": true } }
diff --git a/qapi/transaction.json b/qapi/transaction.json
index bcb05fdedd6..b0ae3437eba 100644
--- a/qapi/transaction.json
+++ b/qapi/transaction.json
@@ -244,7 +244,7 @@
 #
 # Since: 1.1
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "transaction",
 #          "arguments": { "actions": [
diff --git a/qapi/ui.json b/qapi/ui.json
index 5bcccbfc930..c0e94fd0ed0 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -83,7 +83,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "set_password", "arguments": { "protocol": "vnc",
 #                                                    "password": "secret" } }
@@ -144,7 +144,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "expire_password", "arguments": { "protocol": "vnc",
 #                                                       "time": "+60" } }
@@ -186,7 +186,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "screendump",
 #          "arguments": { "filename": "/tmp/image" } }
@@ -330,7 +330,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-spice" }
 #     <- { "return": {
@@ -379,7 +379,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "timestamp": {"seconds": 1290688046, "microseconds": 388707},
 #          "event": "SPICE_CONNECTED",
@@ -405,7 +405,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "timestamp": {"seconds": 1290688046, "microseconds": 417172},
 #          "event": "SPICE_INITIALIZED",
@@ -432,7 +432,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "timestamp": {"seconds": 1290688046, "microseconds": 388707},
 #          "event": "SPICE_DISCONNECTED",
@@ -453,7 +453,7 @@
 #
 # Since: 1.3
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "timestamp": {"seconds": 1290688046, "microseconds": 417172},
 #          "event": "SPICE_MIGRATE_COMPLETED" }
@@ -661,7 +661,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-vnc" }
 #     <- { "return": {
@@ -726,7 +726,7 @@
 #
 # Since: 0.13
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "VNC_CONNECTED",
 #          "data": {
@@ -753,7 +753,7 @@
 #
 # Since: 0.13
 #
-# Example:
+# .. qmp-example::
 #
 #     <-  { "event": "VNC_INITIALIZED",
 #           "data": {
@@ -779,7 +779,7 @@
 #
 # Since: 0.13
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "event": "VNC_DISCONNECTED",
 #          "data": {
@@ -827,7 +827,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-mice" }
 #     <- { "return": [
@@ -1036,7 +1036,7 @@
 #
 # Since: 1.3
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "send-key",
 #          "arguments": { "keys": [ { "type": "qcode", "data": "ctrl" },
@@ -1615,7 +1615,7 @@
 #
 # Since: 6.0
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "display-reload",
 #          "arguments": { "type": "vnc", "tls-certs": true  } }
@@ -1672,7 +1672,7 @@
 #
 # Since: 7.1
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "display-update",
 #          "arguments": { "type": "vnc", "addresses":
@@ -1703,7 +1703,7 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "client_migrate_info",
 #          "arguments": { "protocol": "spice",
diff --git a/qapi/vfio.json b/qapi/vfio.json
index a0e5013188a..40cbcde02eb 100644
--- a/qapi/vfio.json
+++ b/qapi/vfio.json
@@ -50,7 +50,7 @@
 #
 # Since: 9.1
 #
-# Example:
+# .. qmp-example::
 #
 #     <- { "timestamp": { "seconds": 1713771323, "microseconds": 212268 },
 #          "event": "VFIO_MIGRATION",
diff --git a/qapi/virtio.json b/qapi/virtio.json
index b91f3cdd0df..f4323cc35e8 100644
--- a/qapi/virtio.json
+++ b/qapi/virtio.json
@@ -34,7 +34,7 @@
 #
 # Since: 7.2
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "x-query-virtio" }
 #     <- { "return": [
diff --git a/qapi/yank.json b/qapi/yank.json
index 89f2f4d199b..30f46c97c98 100644
--- a/qapi/yank.json
+++ b/qapi/yank.json
@@ -81,7 +81,7 @@
 # Errors:
 #     - If any of the YankInstances doesn't exist, DeviceNotFound
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "yank",
 #          "arguments": {
@@ -104,7 +104,7 @@
 #
 # Returns: list of @YankInstance
 #
-# Example:
+# .. qmp-example::
 #
 #     -> { "execute": "query-yank" }
 #     <- { "return": [
-- 
2.45.0



^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v2 19/21] qapi: convert "Example" sections with titles
  2024-06-26 22:21 [PATCH v2 00/21] qapi: convert "Note" and "Example" sections to rST John Snow
                   ` (17 preceding siblings ...)
  2024-06-26 22:21 ` [PATCH v2 18/21] qapi: convert "Example" sections without titles John Snow
@ 2024-06-26 22:21 ` John Snow
  2024-06-26 22:21 ` [PATCH v2 20/21] qapi: convert "Example" sections with longer prose John Snow
  2024-06-26 22:21 ` [PATCH v2 21/21] qapi: remove "Example" doc section John Snow
  20 siblings, 0 replies; 44+ messages in thread
From: John Snow @ 2024-06-26 22:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Markus Armbruster, Philippe Mathieu-Daudé, Lukas Straub,
	Igor Mammedov, Jason Wang, Yanan Wang, Hanna Reitz,
	Konstantin Kostiuk, Stefan Berger, John Snow

When an Example section has a brief explanation, convert it to a
qmp-example:: section using the :title: option.

Rule of thumb: If the title can fit on a single line and requires no rST
markup, it's a good candidate for using the :title: option of
qmp-example.

In this patch, trailing punctuation is removed from the title section
for consistent headline aesthetics. In just one case, specifics of the
example are removed to make the title read better.

See commit-4: "docs/qapidoc: create qmp-example directive", for a
              detailed explanation of this custom directive syntax.

See commit+2: "qapi: remove "Example" doc section" for a detailed
              explanation of why.

Signed-off-by: John Snow <jsnow@redhat.com>
---
 qapi/block-core.json | 24 ++++++++++++------------
 qapi/block.json      | 13 ++++++-------
 qapi/migration.json  | 25 ++++++++++++++-----------
 qapi/qom.json        |  8 ++++----
 qapi/ui.json         | 11 ++++++-----
 qapi/virtio.json     | 19 ++++++++++---------
 6 files changed, 52 insertions(+), 48 deletions(-)

diff --git a/qapi/block-core.json b/qapi/block-core.json
index 4e0f0395146..a371e3464d2 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -5885,9 +5885,8 @@
 #
 # Since: 2.7
 #
-# Examples:
-#
-#     1. Add a new node to a quorum
+# .. qmp-example::
+#    :title: Add a new node to a quorum
 #
 #     -> { "execute": "blockdev-add",
 #          "arguments": {
@@ -5901,7 +5900,8 @@
 #                         "node": "new_node" } }
 #     <- { "return": {} }
 #
-#     2. Delete a quorum's node
+# .. qmp-example::
+#    :title: Delete a quorum's node
 #
 #     -> { "execute": "x-blockdev-change",
 #          "arguments": { "parent": "disk1",
@@ -5937,16 +5937,16 @@
 #
 # Since: 2.12
 #
-# Examples:
-#
-#     1. Move a node into an IOThread
+# .. qmp-example::
+#    :title: Move a node into an IOThread
 #
 #     -> { "execute": "x-blockdev-set-iothread",
 #          "arguments": { "node-name": "disk1",
 #                         "iothread": "iothread0" } }
 #     <- { "return": {} }
 #
-#     2. Move a node into the main loop
+# .. qmp-example::
+#    :title: Move a node into the main loop
 #
 #     -> { "execute": "x-blockdev-set-iothread",
 #          "arguments": { "node-name": "disk1",
@@ -6022,16 +6022,16 @@
 #
 # Since: 2.0
 #
-# Examples:
-#
-#     1. Read operation
+# .. qmp-example::
+#    :title: Read operation
 #
 #     <- { "event": "QUORUM_REPORT_BAD",
 #          "data": { "node-name": "node0", "sector-num": 345435, "sectors-count": 5,
 #                    "type": "read" },
 #          "timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
 #
-#     2. Flush operation
+# .. qmp-example::
+#    :title: Flush operation
 #
 #     <- { "event": "QUORUM_REPORT_BAD",
 #          "data": { "node-name": "node0", "sector-num": 0, "sectors-count": 2097120,
diff --git a/qapi/block.json b/qapi/block.json
index c8e52bc2d29..5ddd061e964 100644
--- a/qapi/block.json
+++ b/qapi/block.json
@@ -342,9 +342,8 @@
 #
 # Since: 2.5
 #
-# Examples:
-#
-#     1. Change a removable medium
+# .. qmp-example::
+#    :title: Change a removable medium
 #
 #     -> { "execute": "blockdev-change-medium",
 #          "arguments": { "id": "ide0-1-0",
@@ -352,7 +351,8 @@
 #                         "format": "raw" } }
 #     <- { "return": {} }
 #
-#     2. Load a read-only medium into a writable drive
+# .. qmp-example::
+#    :title: Load a read-only medium into a writable drive
 #
 #     -> { "execute": "blockdev-change-medium",
 #          "arguments": { "id": "floppyA",
@@ -577,9 +577,8 @@
 #                         "boundaries-write": [1000, 5000] } }
 #     <- { "return": {} }
 #
-# Example:
-#
-#     Remove all latency histograms:
+# .. qmp-example::
+#    :title: Remove all latency histograms
 #
 #     -> { "execute": "block-latency-histogram-set",
 #          "arguments": { "id": "drive0" } }
diff --git a/qapi/migration.json b/qapi/migration.json
index a4391ea7e6f..37ce8afa380 100644
--- a/qapi/migration.json
+++ b/qapi/migration.json
@@ -287,14 +287,14 @@
 #
 # Since: 0.14
 #
-# Examples:
-#
-#     1. Before the first migration
+# .. qmp-example::
+#    :title: Before the first migration
 #
 #     -> { "execute": "query-migrate" }
 #     <- { "return": {} }
 #
-#     2. Migration is done and has succeeded
+# .. qmp-example::
+#    :title: Migration is done and has succeeded
 #
 #     -> { "execute": "query-migrate" }
 #     <- { "return": {
@@ -314,12 +314,14 @@
 #          }
 #        }
 #
-#     3. Migration is done and has failed
+# .. qmp-example::
+#    :title: Migration is done and has failed
 #
 #     -> { "execute": "query-migrate" }
 #     <- { "return": { "status": "failed" } }
 #
-#     4. Migration is being performed:
+# .. qmp-example::
+#    :title: Migration is being performed
 #
 #     -> { "execute": "query-migrate" }
 #     <- {
@@ -340,7 +342,8 @@
 #           }
 #        }
 #
-#     5. Migration is being performed and XBZRLE is active:
+# .. qmp-example::
+#    :title: Migration is being performed and XBZRLE is active
 #
 #     -> { "execute": "query-migrate" }
 #     <- {
@@ -2131,15 +2134,15 @@
 #
 # Since: 5.2
 #
-# Examples:
-#
-#     1. Measurement is in progress:
+# .. qmp-example::
+#    :title: Measurement is in progress
 #
 #     <- {"status": "measuring", "sample-pages": 512,
 #         "mode": "page-sampling", "start-time": 1693900454, "calc-time": 10,
 #         "calc-time-unit": "second"}
 #
-#     2. Measurement has been completed:
+# .. qmp-example::
+#    :title: Measurement has been completed
 #
 #     <- {"status": "measured", "sample-pages": 512, "dirty-rate": 108,
 #         "mode": "page-sampling", "start-time": 1693900454, "calc-time": 10,
diff --git a/qapi/qom.json b/qapi/qom.json
index fb365e5ce6b..1b3e6c94b73 100644
--- a/qapi/qom.json
+++ b/qapi/qom.json
@@ -104,16 +104,16 @@
 #
 # Since: 1.2
 #
-# Examples:
-#
-#     1. Use absolute path
+# .. qmp-example::
+#    :title: Use absolute path
 #
 #     -> { "execute": "qom-get",
 #          "arguments": { "path": "/machine/unattached/device[0]",
 #                         "property": "hotplugged" } }
 #     <- { "return": false }
 #
-#     2. Use partial path
+# .. qmp-example::
+#    :title: Use partial path
 #
 #     -> { "execute": "qom-get",
 #          "arguments": { "path": "unattached/sysbus",
diff --git a/qapi/ui.json b/qapi/ui.json
index c0e94fd0ed0..779b472f064 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -1272,9 +1272,8 @@
 #    property, so it is possible to map which console belongs to which
 #    device and display.
 #
-# Examples:
-#
-#     1. Press left mouse button.
+# .. qmp-example::
+#    :title: Press left mouse button
 #
 #     -> { "execute": "input-send-event",
 #         "arguments": { "device": "video0",
@@ -1288,7 +1287,8 @@
 #                        "data" : { "down": false, "button": "left" } } ] } }
 #     <- { "return": {} }
 #
-#     2. Press ctrl-alt-del.
+# .. qmp-example::
+#    :title: Press ctrl-alt-del
 #
 #     -> { "execute": "input-send-event",
 #          "arguments": { "events": [
@@ -1300,7 +1300,8 @@
 #               "key": {"type": "qcode", "data": "delete" } } } ] } }
 #     <- { "return": {} }
 #
-#     3. Move mouse pointer to absolute coordinates (20000, 400).
+# .. qmp-example::
+#    :title: Move mouse pointer to absolute coordinates
 #
 #     -> { "execute": "input-send-event" ,
 #       "arguments": { "events": [
diff --git a/qapi/virtio.json b/qapi/virtio.json
index f4323cc35e8..d965c98ad2b 100644
--- a/qapi/virtio.json
+++ b/qapi/virtio.json
@@ -690,9 +690,8 @@
 #
 # Since: 7.2
 #
-# Examples:
-#
-#     1. Get vhost_virtqueue status for vhost-crypto
+# .. qmp-example::
+#    :title: Get vhost_virtqueue status for vhost-crypto
 #
 #     -> { "execute": "x-query-virtio-vhost-queue-status",
 #          "arguments": { "path": "/machine/peripheral/crypto0/virtio-backend",
@@ -715,7 +714,8 @@
 #          }
 #        }
 #
-#     2. Get vhost_virtqueue status for vhost-vsock
+# .. qmp-example::
+#    :title: Get vhost_virtqueue status for vhost-vsock
 #
 #     -> { "execute": "x-query-virtio-vhost-queue-status",
 #          "arguments": { "path": "/machine/peripheral/vsock0/virtio-backend",
@@ -839,9 +839,8 @@
 #
 # Since: 7.2
 #
-# Examples:
-#
-#     1. Introspect on virtio-net's VirtQueue 0 at index 5
+# .. qmp-example::
+#    :title: Introspect on virtio-net's VirtQueue 0 at index 5
 #
 #     -> { "execute": "x-query-virtio-queue-element",
 #          "arguments": { "path": "/machine/peripheral-anon/device[1]/virtio-backend",
@@ -870,7 +869,8 @@
 #          }
 #        }
 #
-#     2. Introspect on virtio-crypto's VirtQueue 1 at head
+# .. qmp-example::
+#    :title: Introspect on virtio-crypto's VirtQueue 1 at head
 #
 #     -> { "execute": "x-query-virtio-queue-element",
 #          "arguments": { "path": "/machine/peripheral/crypto0/virtio-backend",
@@ -898,7 +898,8 @@
 #          }
 #        }
 #
-#     3. Introspect on virtio-scsi's VirtQueue 2 at head
+# .. qmp-example::
+#    :title: Introspect on virtio-scsi's VirtQueue 2 at head
 #
 #     -> { "execute": "x-query-virtio-queue-element",
 #          "arguments": { "path": "/machine/peripheral-anon/device[2]/virtio-backend",
-- 
2.45.0



^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v2 20/21] qapi: convert "Example" sections with longer prose
  2024-06-26 22:21 [PATCH v2 00/21] qapi: convert "Note" and "Example" sections to rST John Snow
                   ` (18 preceding siblings ...)
  2024-06-26 22:21 ` [PATCH v2 19/21] qapi: convert "Example" sections with titles John Snow
@ 2024-06-26 22:21 ` John Snow
  2024-06-26 22:21 ` [PATCH v2 21/21] qapi: remove "Example" doc section John Snow
  20 siblings, 0 replies; 44+ messages in thread
From: John Snow @ 2024-06-26 22:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Markus Armbruster, Philippe Mathieu-Daudé, Lukas Straub,
	Igor Mammedov, Jason Wang, Yanan Wang, Hanna Reitz,
	Konstantin Kostiuk, Stefan Berger, John Snow

These examples require longer explanations or have explanations that
require markup to look reasonable when rendered and so use the longer
form of the ".. qmp-example::" directive.

By using the :annotated: option, the content in the example block is
assumed *not* to be a code block literal and is instead parsed as normal
rST - with the exception that any code literal blocks after `::` will
assumed to be a QMP code literal block.

Note: There's one title-less conversion in this patch that comes along
for the ride because it's part of a larger "Examples" block that was
better to convert all at once.

See commit-5: "docs/qapidoc: create qmp-example directive", for a
              detailed explanation of this custom directive syntax.

See commit+1: "qapi: remove "Example" doc section" for a detailed
              explanation of why.

Signed-off-by: John Snow <jsnow@redhat.com>
---
 qapi/block.json     | 26 ++++++++++++++++----------
 qapi/machine.json   | 30 ++++++++++++++++++++----------
 qapi/migration.json |  7 +++++--
 qapi/virtio.json    | 24 ++++++++++++++++++------
 4 files changed, 59 insertions(+), 28 deletions(-)

diff --git a/qapi/block.json b/qapi/block.json
index 5ddd061e964..d95e9fd8140 100644
--- a/qapi/block.json
+++ b/qapi/block.json
@@ -545,31 +545,37 @@
 #
 # Since: 4.0
 #
-# Example:
+# .. qmp-example::
+#    :annotated:
 #
-#     Set new histograms for all io types with intervals
-#     [0, 10), [10, 50), [50, 100), [100, +inf):
+#    Set new histograms for all io types with intervals
+#    [0, 10), [10, 50), [50, 100), [100, +inf)::
 #
 #     -> { "execute": "block-latency-histogram-set",
 #          "arguments": { "id": "drive0",
 #                         "boundaries": [10, 50, 100] } }
 #     <- { "return": {} }
 #
-# Example:
+# .. qmp-example::
+#    :annotated:
 #
-#     Set new histogram only for write, other histograms will remain
-#     not changed (or not created):
+#    Set new histogram only for write, other histograms will remain
+#    not changed (or not created)::
 #
 #     -> { "execute": "block-latency-histogram-set",
 #          "arguments": { "id": "drive0",
 #                         "boundaries-write": [10, 50, 100] } }
 #     <- { "return": {} }
 #
-# Example:
+# .. qmp-example::
+#    :annotated:
 #
-#     Set new histograms with the following intervals:
-#       read, flush: [0, 10), [10, 50), [50, 100), [100, +inf)
-#       write: [0, 1000), [1000, 5000), [5000, +inf)
+#    Set new histograms with the following intervals:
+#
+#    - read, flush: [0, 10), [10, 50), [50, 100), [100, +inf)
+#    - write: [0, 1000), [1000, 5000), [5000, +inf)
+#
+#    ::
 #
 #     -> { "execute": "block-latency-histogram-set",
 #          "arguments": { "id": "drive0",
diff --git a/qapi/machine.json b/qapi/machine.json
index 83f60b319c7..0a5ffe652b7 100644
--- a/qapi/machine.json
+++ b/qapi/machine.json
@@ -1047,10 +1047,11 @@
 #
 # Since: 2.7
 #
-# Examples:
+# .. qmp-example::
+#    :annotated:
 #
-#     For pseries machine type started with -smp 2,cores=2,maxcpus=4
-#     -cpu POWER8:
+#    For pseries machine type started with
+#    ``-smp 2,cores=2,maxcpus=4 -cpu POWER8``::
 #
 #     -> { "execute": "query-hotpluggable-cpus" }
 #     <- {"return": [
@@ -1060,7 +1061,10 @@
 #            "vcpus-count": 1, "qom-path": "/machine/unattached/device[0]"}
 #        ]}
 #
-#     For pc machine type started with -smp 1,maxcpus=2:
+# .. qmp-example::
+#    :annotated:
+#
+#    For pc machine type started with ``-smp 1,maxcpus=2``::
 #
 #     -> { "execute": "query-hotpluggable-cpus" }
 #     <- {"return": [
@@ -1075,8 +1079,11 @@
 #          }
 #        ]}
 #
-#     For s390x-virtio-ccw machine type started with -smp 1,maxcpus=2
-#     -cpu qemu (Since: 2.11):
+# .. qmp-example::
+#    :annotated:
+#
+#    For s390x-virtio-ccw machine type started with
+#    ``-smp 1,maxcpus=2 -cpu qemu`` (Since: 2.11)::
 #
 #     -> { "execute": "query-hotpluggable-cpus" }
 #     <- {"return": [
@@ -1130,12 +1137,15 @@
 #
 # Since: 0.14
 #
-# Example:
+# .. qmp-example::
+#    :annotated:
 #
-#     -> { "execute": "balloon", "arguments": { "value": 536870912 } }
-#     <- { "return": {} }
+#    ::
 #
-#     With a 2.5GiB guest this command inflated the ballon to 3GiB.
+#      -> { "execute": "balloon", "arguments": { "value": 536870912 } }
+#      <- { "return": {} }
+#
+#    With a 2.5GiB guest this command inflated the ballon to 3GiB.
 ##
 { 'command': 'balloon', 'data': {'value': 'int'} }
 
diff --git a/qapi/migration.json b/qapi/migration.json
index 37ce8afa380..e208a86258a 100644
--- a/qapi/migration.json
+++ b/qapi/migration.json
@@ -2106,13 +2106,16 @@
 #
 # Since: 5.2
 #
-# Example:
+# .. qmp-example::
 #
 #     -> {"execute": "calc-dirty-rate", "arguments": {"calc-time": 1,
 #                                                     "sample-pages": 512} }
 #     <- { "return": {} }
 #
-#     Measure dirty rate using dirty bitmap for 500 milliseconds:
+# .. qmp-example::
+#    :annotated:
+#
+#    Measure dirty rate using dirty bitmap for 500 milliseconds::
 #
 #     -> {"execute": "calc-dirty-rate", "arguments": {"calc-time": 500,
 #         "calc-time-unit": "millisecond", "mode": "dirty-bitmap"} }
diff --git a/qapi/virtio.json b/qapi/virtio.json
index d965c98ad2b..26df8b3064b 100644
--- a/qapi/virtio.json
+++ b/qapi/virtio.json
@@ -203,9 +203,11 @@
 #
 # Since: 7.2
 #
-# Examples:
+# .. qmp-example::
+#    :annotated:
 #
-#     1. Poll for the status of virtio-crypto (no vhost-crypto active)
+#    Poll for the status of virtio-crypto (no vhost-crypto active)
+#    ::
 #
 #     -> { "execute": "x-query-virtio-status",
 #          "arguments": { "path": "/machine/peripheral/crypto0/virtio-backend" }
@@ -261,7 +263,11 @@
 #          }
 #        }
 #
-#     2. Poll for the status of virtio-net (vhost-net is active)
+# .. qmp-example::
+#    :annotated:
+#
+#    Poll for the status of virtio-net (vhost-net is active)
+#    ::
 #
 #     -> { "execute": "x-query-virtio-status",
 #          "arguments": { "path": "/machine/peripheral-anon/device[1]/virtio-backend" }
@@ -568,9 +574,11 @@
 #
 # Since: 7.2
 #
-# Examples:
+# .. qmp-example::
+#    :annotated:
 #
-#     1. Get VirtQueueStatus for virtio-vsock (vhost-vsock running)
+#    Get VirtQueueStatus for virtio-vsock (vhost-vsock running)
+#    ::
 #
 #     -> { "execute": "x-query-virtio-queue-status",
 #          "arguments": { "path": "/machine/peripheral/vsock0/virtio-backend",
@@ -593,7 +601,11 @@
 #          }
 #        }
 #
-#     2. Get VirtQueueStatus for virtio-serial (no vhost)
+# .. qmp-example::
+#    :annotated:
+#
+#    Get VirtQueueStatus for virtio-serial (no vhost)
+#    ::
 #
 #     -> { "execute": "x-query-virtio-queue-status",
 #          "arguments": { "path": "/machine/peripheral-anon/device[0]/virtio-backend",
-- 
2.45.0



^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v2 21/21] qapi: remove "Example" doc section
  2024-06-26 22:21 [PATCH v2 00/21] qapi: convert "Note" and "Example" sections to rST John Snow
                   ` (19 preceding siblings ...)
  2024-06-26 22:21 ` [PATCH v2 20/21] qapi: convert "Example" sections with longer prose John Snow
@ 2024-06-26 22:21 ` John Snow
  20 siblings, 0 replies; 44+ messages in thread
From: John Snow @ 2024-06-26 22:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Markus Armbruster, Philippe Mathieu-Daudé, Lukas Straub,
	Igor Mammedov, Jason Wang, Yanan Wang, Hanna Reitz,
	Konstantin Kostiuk, Stefan Berger, John Snow

Fully eliminate the "Example" sections in QAPI doc blocks now that they
have all been converted to arbitrary rST syntax using the
".. qmp-example::" directive. Update tests to match.

Migrating to the new syntax
---------------------------

The old "Example:" or "Examples:" section syntax is now caught as an
error, but "Example::" is stil permitted as explicit rST syntax for an
un-lexed, generic preformatted text block.

('Example' is not special in this case, any sentence that ends with "::"
will start an indented code block in rST.)

Arbitrary rST for Examples are now possible, but it's strongly
recommended that documentation authors use the ".. qmp-example::"
directive for consistent visual formatting in rendered HTML docs. The
":title:" directive option may be used to add extra information into the
title bar for the example. The ":annotated:" option can be used to write
arbitrary rST instead, with nested "::" blocks applying QMP formatting
where desired.

Other choices available are ".. code-block:: QMP" which will not create
an "Example:" box, or the short-form "::" code-block syntax which will
not apply QMP highlighting when used outside of the qmp-example
directive.

Why?
----

This patch has several benefits:

1. Example sections can now be written more arbitrarily, mixing
   explanatory paragraphs and code blocks however desired.

2. Example sections can now use fully arbitrary rST.

3. All code blocks are now lexed and validated as QMP; increasing
   usability of the docs and ensuring validity of example snippets.

   (To some extent - This patch only gaurantees it lexes correctly, not
   that it's valid under the JSON or QMP grammars. It will catch most
   small mistakes, however.)

4. Each qmp-example can be titled or annotated independently without
   bypassing the QMP lexer/validator.

   (i.e. code blocks are now for *code* only, so we don't have to
   sacrifice exposition for having lexically valid examples.)

NOTE: As with the "Notes" conversion patch, this patch (and those
      preceding) may change the rendering order for Examples in the
      current generator. The forthcoming qapidoc rewrite will fix this
      by always generating documentation in source order.

Signed-off-by: John Snow <jsnow@redhat.com>
---
 docs/devel/qapi-code-gen.rst    | 15 +++++++--------
 scripts/qapi/parser.py          | 10 +++++++++-
 tests/qapi-schema/doc-good.json | 19 ++++++++++++-------
 tests/qapi-schema/doc-good.out  | 26 ++++++++++++++++++--------
 tests/qapi-schema/doc-good.txt  | 23 ++++++++++-------------
 5 files changed, 56 insertions(+), 37 deletions(-)

diff --git a/docs/devel/qapi-code-gen.rst b/docs/devel/qapi-code-gen.rst
index ae97b335cbf..493e2b8f8df 100644
--- a/docs/devel/qapi-code-gen.rst
+++ b/docs/devel/qapi-code-gen.rst
@@ -995,8 +995,8 @@ line "Features:", like this::
   # @feature: Description text
 
 A tagged section begins with a paragraph that starts with one of the
-following words: "Since:", "Example:"/"Examples:", "Returns:",
-"Errors:", "TODO:".  It ends with the start of a new section.
+following words: "Since:", "Returns:", "Errors:", "TODO:".  It ends with
+the start of a new section.
 
 The second and subsequent lines of tagged sections must be indented
 like this::
@@ -1020,10 +1020,9 @@ detailing a relevant error condition. For example::
 A "Since: x.y.z" tagged section lists the release that introduced the
 definition.
 
-An "Example" or "Examples" section is rendered entirely
-as literal fixed-width text.  "TODO" sections are not rendered at all
-(they are for developers, not users of QMP).  In other sections, the
-text is formatted, and rST markup can be used.
+"TODO" sections are not rendered at all (they are for developers, not
+users of QMP).  In other sections, the text is formatted, and rST markup
+can be used.
 
 For example::
 
@@ -1058,11 +1057,11 @@ For example::
  #
  # Since: 0.14
  #
- # Example:
+ # .. qmp-example::
  #
  #     -> { "execute": "query-blockstats" }
  #     <- {
- #          ... lots of output ...
+ #          ...
  #        }
  ##
  { 'command': 'query-blockstats',
diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py
index 6ad5663e545..adc85b5b394 100644
--- a/scripts/qapi/parser.py
+++ b/scripts/qapi/parser.py
@@ -553,7 +553,7 @@ def get_doc(self) -> 'QAPIDoc':
                     # Note: "sections" with two colons are left alone as
                     # rST markup and not interpreted as a section heading.
 
-                    # TODO: Remove this error sometime in 2025 or so
+                    # TODO: Remove these errors sometime in 2025 or so
                     # after we've fully transitioned to the new qapidoc
                     # generator.
 
@@ -567,6 +567,14 @@ def get_doc(self) -> 'QAPIDoc':
                         )
                         raise QAPIParseError(self, emsg)
 
+                    if 'Example' in match.group(1):
+                        emsg = (
+                            f"The '{match.group(1)}' section is no longer "
+                            "supported. Please use the '.. qmp-example::' "
+                            "directive, or other suitable markup instead."
+                        )
+                        raise QAPIParseError(self, emsg)
+
                     doc.new_tagged_section(self.info, match.group(1))
                     text = line[match.end():]
                     if text:
diff --git a/tests/qapi-schema/doc-good.json b/tests/qapi-schema/doc-good.json
index 107123f8a8d..c71d65cd51f 100644
--- a/tests/qapi-schema/doc-good.json
+++ b/tests/qapi-schema/doc-good.json
@@ -172,12 +172,17 @@
 #
 #  Duis aute irure dolor
 #
-# Example:
+# .. qmp-example::
+#    :title: Ideal fast-food burger situation
 #
-#  -> in
-#  <- out
+#    -> "in"
+#    <- "out"
 #
-# Examples:
+# Examples::
+#
+#  - Not a QMP code block
+#  - Merely a preformatted code block literal
+#  It isn't even an rST list.
 #  - *verbatim*
 #  - {braces}
 #
@@ -199,11 +204,11 @@
 # @cmd-feat1: a feature
 # @cmd-feat2: another feature
 #
-# Example:
+# .. qmp-example::
 #
-#  -> in
+#    -> "this example"
 #
-#  <- out
+#    <- "has no title"
 ##
 { 'command': 'cmd-boxed', 'boxed': true,
   'data': 'Object',
diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out
index bd876b6542d..eee18cd436a 100644
--- a/tests/qapi-schema/doc-good.out
+++ b/tests/qapi-schema/doc-good.out
@@ -184,13 +184,21 @@ frobnicate
  - Ut enim ad minim veniam
 
  Duis aute irure dolor
-    section=Example
- -> in
- <- out
-    section=Examples
+
+.. qmp-example::
+   :title: Ideal fast-food burger situation
+
+   -> "in"
+   <- "out"
+
+Examples::
+
+ - Not a QMP code block
+ - Merely a preformatted code block literal
+ It isn't even an rST list.
  - *verbatim*
  - {braces}
-    section=None
+
 Note::
    Ceci n'est pas une note
     section=Since
@@ -202,10 +210,12 @@ If you're bored enough to read this, go see a video of boxed cats
 a feature
     feature=cmd-feat2
 another feature
-    section=Example
- -> in
+    section=None
+.. qmp-example::
 
- <- out
+   -> "this example"
+
+   <- "has no title"
 doc symbol=EVT_BOXED
     body=
 
diff --git a/tests/qapi-schema/doc-good.txt b/tests/qapi-schema/doc-good.txt
index 30d457e5488..cb37db606a6 100644
--- a/tests/qapi-schema/doc-good.txt
+++ b/tests/qapi-schema/doc-good.txt
@@ -217,17 +217,16 @@ Notes:
 
 Duis aute irure dolor
 
+Example: Ideal fast-food burger situation:
 
-Example
-~~~~~~~
+   -> "in"
+   <- "out"
 
-   -> in
-   <- out
-
-
-Examples
-~~~~~~~~
+Examples:
 
+   - Not a QMP code block
+   - Merely a preformatted code block literal
+   It isn't even an rST list.
    - *verbatim*
    - {braces}
 
@@ -261,13 +260,11 @@ Features
 "cmd-feat2"
    another feature
 
+Example::
 
-Example
-~~~~~~~
+   -> "this example"
 
-   -> in
-
-   <- out
+   <- "has no title"
 
 
 "EVT_BOXED" (Event)
-- 
2.45.0



^ permalink raw reply related	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 03/21] docs/qapidoc: remove unused intersperse function
  2024-06-26 22:21 ` [PATCH v2 03/21] docs/qapidoc: remove unused intersperse function John Snow
@ 2024-06-27  6:02   ` Markus Armbruster
  2024-06-27  6:12     ` John Snow
  2024-06-27 10:46     ` Markus Armbruster
  2024-06-27 10:43   ` Markus Armbruster
  1 sibling, 2 replies; 44+ messages in thread
From: Markus Armbruster @ 2024-06-27  6:02 UTC (permalink / raw)
  To: John Snow
  Cc: qemu-devel, Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Philippe Mathieu-Daudé, Lukas Straub, Igor Mammedov,
	Jason Wang, Yanan Wang, Hanna Reitz, Konstantin Kostiuk

John Snow <jsnow@redhat.com> writes:

> This function has been unused since fd62bff901b.
>
> Signed-off-by: John Snow <jsnow@redhat.com>

Reviewed-by: Markus Armbruster <armbru@redhat.com>

I assume you won't mind me adding a bit of polish: "since commit
fd62bff901b (sphinx/qapidoc: Drop code to generate doc for simple union
tag)".



^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 03/21] docs/qapidoc: remove unused intersperse function
  2024-06-27  6:02   ` Markus Armbruster
@ 2024-06-27  6:12     ` John Snow
  2024-06-27 10:46     ` Markus Armbruster
  1 sibling, 0 replies; 44+ messages in thread
From: John Snow @ 2024-06-27  6:12 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, Qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Philippe Mathieu-Daudé, Lukas Straub, Igor Mammedov,
	Jason Wang, Yanan Wang, Hanna Reitz, Konstantin Kostiuk

[-- Attachment #1: Type: text/plain, Size: 541 bytes --]

On Thu, Jun 27, 2024, 2:02 AM Markus Armbruster <armbru@redhat.com> wrote:

> John Snow <jsnow@redhat.com> writes:
>
> > This function has been unused since fd62bff901b.
> >
> > Signed-off-by: John Snow <jsnow@redhat.com>
>
> Reviewed-by: Markus Armbruster <armbru@redhat.com>
>
> I assume you won't mind me adding a bit of polish: "since commit
> fd62bff901b (sphinx/qapidoc: Drop code to generate doc for simple union
> tag)".
>

Please be my guest!

--js

(Looking at it, that's a very weird phrase, isn't it?)

>

[-- Attachment #2: Type: text/html, Size: 1395 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 05/21] qapi/parser: preserve indentation in QAPIDoc sections
  2024-06-26 22:21 ` [PATCH v2 05/21] qapi/parser: preserve indentation in QAPIDoc sections John Snow
@ 2024-06-27  6:25   ` Markus Armbruster
  2024-06-27  6:35     ` John Snow
  2024-06-27 10:46     ` Markus Armbruster
  2024-06-27 10:43   ` Markus Armbruster
  1 sibling, 2 replies; 44+ messages in thread
From: Markus Armbruster @ 2024-06-27  6:25 UTC (permalink / raw)
  To: John Snow
  Cc: qemu-devel, Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Philippe Mathieu-Daudé, Lukas Straub, Igor Mammedov,
	Jason Wang, Yanan Wang, Hanna Reitz, Konstantin Kostiuk

John Snow <jsnow@redhat.com> writes:

> Change get_doc_indented() to preserve indentation on all subsequent text
> lines, and create a compatibility dedent() function for qapidoc.py that
> removes indentation the same way get_doc_indented() did.
>
> This is being done for the benefit of a new qapidoc generator which
> requires that indentation in argument and features sections are
> preserved.
>
> Prior to this patch, a section like this:
>
> ```
> @name: lorem ipsum
>    dolor sit amet
>      consectetur adipiscing elit
> ```
>
> would have its body text be parsed into:
>
> ```
> lorem ipsum
> dolor sit amet
>   consectetur adipiscing elit
> ```
>
> We want to preserve the indentation for even the first body line so that
> the entire block can be parsed directly as rST. This patch would now
> parse that segment into:
>
> ```
> lorem ipsum
>    dolor sit amet
>      consectetur adipiscing elit
> ```
>
> This is helpful for formatting arguments and features as field lists in
> rST, where the new generator will format this information as:
>
> ```
> :arg type name: lorem ipsum
>    dolor sit amet
>      consectetur apidiscing elit
> ```
>
> ...and can be formed by the simple concatenation of the field list
> construct and the body text. The indents help preserve the continuation
> of a block-level element, and further allow the use of additional rST
> block-level constructs such as code blocks, lists, and other such
> markup.
>
> This understandably breaks the existing qapidoc.py; so a new function is
> added there to dedent the text for compatibility. Once the new generator
> is merged, this function will not be needed any longer and can be
> dropped.

I'll restore this paragraph if you don't mind:

  I verified this patch changes absolutely nothing by comparing the
  md5sums of the QMP ref html pages both before and after the change, so
  it's certified inert. QAPI test output has been updated to reflect the
  new strategy of preserving indents for rST.

> Signed-off-by: John Snow <jsnow@redhat.com>
> [Edited commit message and code comments per review --js]

And I'll drop this line.

> Reviewed-by: Markus Armbruster <armbru@redhat.com>



^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 05/21] qapi/parser: preserve indentation in QAPIDoc sections
  2024-06-27  6:25   ` Markus Armbruster
@ 2024-06-27  6:35     ` John Snow
  2024-06-27 10:46     ` Markus Armbruster
  1 sibling, 0 replies; 44+ messages in thread
From: John Snow @ 2024-06-27  6:35 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, Qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Philippe Mathieu-Daudé, Lukas Straub, Igor Mammedov,
	Jason Wang, Yanan Wang, Hanna Reitz, Konstantin Kostiuk

[-- Attachment #1: Type: text/plain, Size: 2574 bytes --]

On Thu, Jun 27, 2024, 2:25 AM Markus Armbruster <armbru@redhat.com> wrote:

> John Snow <jsnow@redhat.com> writes:
>
> > Change get_doc_indented() to preserve indentation on all subsequent text
> > lines, and create a compatibility dedent() function for qapidoc.py that
> > removes indentation the same way get_doc_indented() did.
> >
> > This is being done for the benefit of a new qapidoc generator which
> > requires that indentation in argument and features sections are
> > preserved.
> >
> > Prior to this patch, a section like this:
> >
> > ```
> > @name: lorem ipsum
> >    dolor sit amet
> >      consectetur adipiscing elit
> > ```
> >
> > would have its body text be parsed into:
> >
> > ```
> > lorem ipsum
> > dolor sit amet
> >   consectetur adipiscing elit
> > ```
> >
> > We want to preserve the indentation for even the first body line so that
> > the entire block can be parsed directly as rST. This patch would now
> > parse that segment into:
> >
> > ```
> > lorem ipsum
> >    dolor sit amet
> >      consectetur adipiscing elit
> > ```
> >
> > This is helpful for formatting arguments and features as field lists in
> > rST, where the new generator will format this information as:
> >
> > ```
> > :arg type name: lorem ipsum
> >    dolor sit amet
> >      consectetur apidiscing elit
> > ```
> >
> > ...and can be formed by the simple concatenation of the field list
> > construct and the body text. The indents help preserve the continuation
> > of a block-level element, and further allow the use of additional rST
> > block-level constructs such as code blocks, lists, and other such
> > markup.
> >
> > This understandably breaks the existing qapidoc.py; so a new function is
> > added there to dedent the text for compatibility. Once the new generator
> > is merged, this function will not be needed any longer and can be
> > dropped.
>
> I'll restore this paragraph if you don't mind:
>
>   I verified this patch changes absolutely nothing by comparing the
>   md5sums of the QMP ref html pages both before and after the change, so
>   it's certified inert. QAPI test output has been updated to reflect the
>   new strategy of preserving indents for rST.
>

Nope, misunderstood the instruction. Go right ahead.


> > Signed-off-by: John Snow <jsnow@redhat.com>
> > [Edited commit message and code comments per review --js]
>
> And I'll drop this line.
>

Vestigial remnants of a more optimistic time.


> > Reviewed-by: Markus Armbruster <armbru@redhat.com>
>
>

[-- Attachment #2: Type: text/html, Size: 3897 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 13/21] qapi/parser: don't parse rST markup as section headers
  2024-06-26 22:21 ` [PATCH v2 13/21] qapi/parser: don't parse rST markup as section headers John Snow
@ 2024-06-27  7:47   ` Markus Armbruster
  0 siblings, 0 replies; 44+ messages in thread
From: Markus Armbruster @ 2024-06-27  7:47 UTC (permalink / raw)
  To: John Snow
  Cc: qemu-devel, Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Philippe Mathieu-Daudé, Lukas Straub, Igor Mammedov,
	Jason Wang, Yanan Wang, Hanna Reitz, Konstantin Kostiuk

John Snow <jsnow@redhat.com> writes:

> The double-colon synax is rST formatting that precedes a literal code
> block. We do not want to capture these as QAPI-specific sections.
>
> Coerce blocks that start with e.g. "Example::" to be parsed as untagged
> paragraphs instead of special tagged sections.
>
> Signed-off-by: John Snow <jsnow@redhat.com>

Reviewed-by: Markus Armbruster <armbru@redhat.com>



^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 03/21] docs/qapidoc: remove unused intersperse function
  2024-06-26 22:21 ` [PATCH v2 03/21] docs/qapidoc: remove unused intersperse function John Snow
  2024-06-27  6:02   ` Markus Armbruster
@ 2024-06-27 10:43   ` Markus Armbruster
  1 sibling, 0 replies; 44+ messages in thread
From: Markus Armbruster @ 2024-06-27 10:43 UTC (permalink / raw)
  To: John Snow
  Cc: qemu-devel, Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Philippe Mathieu-Daudé, Lukas Straub, Igor Mammedov,
	Jason Wang, Yanan Wang, Hanna Reitz, Konstantin Kostiuk

John Snow <jsnow@redhat.com> writes:

> This function has been unused since fd62bff901b.
>
> Signed-off-by: John Snow <jsnow@redhat.com>

Reviewed-by: Markus Armbruster <armbru@redhat.com>

I assume you won't mind me adding a bit of polish: "since commit
fd62bff901b (sphinx/qapidoc: Drop code to generate doc for simple union
tag)".



^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 05/21] qapi/parser: preserve indentation in QAPIDoc sections
  2024-06-26 22:21 ` [PATCH v2 05/21] qapi/parser: preserve indentation in QAPIDoc sections John Snow
  2024-06-27  6:25   ` Markus Armbruster
@ 2024-06-27 10:43   ` Markus Armbruster
  1 sibling, 0 replies; 44+ messages in thread
From: Markus Armbruster @ 2024-06-27 10:43 UTC (permalink / raw)
  To: John Snow
  Cc: qemu-devel, Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Philippe Mathieu-Daudé, Lukas Straub, Igor Mammedov,
	Jason Wang, Yanan Wang, Hanna Reitz, Konstantin Kostiuk

John Snow <jsnow@redhat.com> writes:

> Change get_doc_indented() to preserve indentation on all subsequent text
> lines, and create a compatibility dedent() function for qapidoc.py that
> removes indentation the same way get_doc_indented() did.
>
> This is being done for the benefit of a new qapidoc generator which
> requires that indentation in argument and features sections are
> preserved.
>
> Prior to this patch, a section like this:
>
> ```
> @name: lorem ipsum
>    dolor sit amet
>      consectetur adipiscing elit
> ```
>
> would have its body text be parsed into:
>
> ```
> lorem ipsum
> dolor sit amet
>   consectetur adipiscing elit
> ```
>
> We want to preserve the indentation for even the first body line so that
> the entire block can be parsed directly as rST. This patch would now
> parse that segment into:
>
> ```
> lorem ipsum
>    dolor sit amet
>      consectetur adipiscing elit
> ```
>
> This is helpful for formatting arguments and features as field lists in
> rST, where the new generator will format this information as:
>
> ```
> :arg type name: lorem ipsum
>    dolor sit amet
>      consectetur apidiscing elit
> ```
>
> ...and can be formed by the simple concatenation of the field list
> construct and the body text. The indents help preserve the continuation
> of a block-level element, and further allow the use of additional rST
> block-level constructs such as code blocks, lists, and other such
> markup.
>
> This understandably breaks the existing qapidoc.py; so a new function is
> added there to dedent the text for compatibility. Once the new generator
> is merged, this function will not be needed any longer and can be
> dropped.

I'll restore this paragraph if you don't mind:

  I verified this patch changes absolutely nothing by comparing the
  md5sums of the QMP ref html pages both before and after the change, so
  it's certified inert. QAPI test output has been updated to reflect the
  new strategy of preserving indents for rST.

> Signed-off-by: John Snow <jsnow@redhat.com>
> [Edited commit message and code comments per review --js]

And I'll drop this line.

> Reviewed-by: Markus Armbruster <armbru@redhat.com>



^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 03/21] docs/qapidoc: remove unused intersperse function
  2024-06-27  6:02   ` Markus Armbruster
  2024-06-27  6:12     ` John Snow
@ 2024-06-27 10:46     ` Markus Armbruster
  1 sibling, 0 replies; 44+ messages in thread
From: Markus Armbruster @ 2024-06-27 10:46 UTC (permalink / raw)
  To: John Snow
  Cc: qemu-devel, Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Philippe Mathieu-Daudé, Lukas Straub, Igor Mammedov,
	Jason Wang, Yanan Wang, Hanna Reitz, Konstantin Kostiuk

Accidental duplicate, please ignore.



^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 05/21] qapi/parser: preserve indentation in QAPIDoc sections
  2024-06-27  6:25   ` Markus Armbruster
  2024-06-27  6:35     ` John Snow
@ 2024-06-27 10:46     ` Markus Armbruster
  1 sibling, 0 replies; 44+ messages in thread
From: Markus Armbruster @ 2024-06-27 10:46 UTC (permalink / raw)
  To: John Snow
  Cc: qemu-devel, Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Philippe Mathieu-Daudé, Lukas Straub, Igor Mammedov,
	Jason Wang, Yanan Wang, Hanna Reitz, Konstantin Kostiuk

Accidental duplicate, please ignore.



^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 04/21] docs/qapidoc: delint a tiny portion of the module
  2024-06-26 22:21 ` [PATCH v2 04/21] docs/qapidoc: delint a tiny portion of the module John Snow
@ 2024-06-28  7:29   ` Markus Armbruster
  2024-06-28 14:36     ` John Snow
  0 siblings, 1 reply; 44+ messages in thread
From: Markus Armbruster @ 2024-06-28  7:29 UTC (permalink / raw)
  To: John Snow
  Cc: qemu-devel, Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Philippe Mathieu-Daudé, Lukas Straub, Igor Mammedov,
	Jason Wang, Yanan Wang, Hanna Reitz, Konstantin Kostiuk

John Snow <jsnow@redhat.com> writes:

> In a forthcoming series that adds a new QMP documentation generator, it
> will be helpful to have a linting baseline. However, there's no need to
> shuffle around the deck chairs too much, because most of this code will
> be removed once that new qapidoc generator (the "transmogrifier") is in
> place.
>
> To ease my pain: just turn off the black auto-formatter for most, but
> not all, of qapidoc.py. This will help ensure that *new* code follows a
> coding standard without bothering too much with cleaning up the existing
> code.
>
> Code that I intend to keep is still subject to the delinting beam.
>
> Signed-off-by: John Snow <jsnow@redhat.com>
> Reviewed-by: Markus Armbruster <armbru@redhat.com>

Not an objection, just so you know: I still see a few C0411 like 'third
party import "import sphinx" should be placed before ...'

R-by stands.



^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 07/21] docs/qapidoc: fix nested parsing under untagged sections
  2024-06-26 22:21 ` [PATCH v2 07/21] docs/qapidoc: fix nested parsing under untagged sections John Snow
@ 2024-06-28  7:54   ` Markus Armbruster
  2024-06-28 15:10     ` John Snow
  0 siblings, 1 reply; 44+ messages in thread
From: Markus Armbruster @ 2024-06-28  7:54 UTC (permalink / raw)
  To: John Snow
  Cc: qemu-devel, Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Philippe Mathieu-Daudé, Lukas Straub, Igor Mammedov,
	Jason Wang, Yanan Wang, Hanna Reitz, Konstantin Kostiuk

John Snow <jsnow@redhat.com> writes:

> Sphinx does not like sections without titles, because it wants to
> convert every section into a reference. When there is no title, it
> struggles to do this and transforms the tree inproperly.
>
> Depending on the rST used, this may result in an assertion error deep in
> the docutils HTMLWriter.
>
> (Observed when using ".. admonition:: Notes" under such a section - When
> this is transformed with its own <title> element, Sphinx is fooled into
> believing this title belongs to the section and incorrect mutates the
> docutils tree, leading to errors during rendering time.)
>
> When parsing an untagged section (free paragraphs), skip making a hollow
> section and instead append the parse results to the prior section.
>
> Many Bothans died to bring us this information.
>
> Signed-off-by: John Snow <jsnow@redhat.com>
> Acked-by: Markus Armbruster <armbru@redhat.com>

Generated HTML changes, but the diff is hard to review due to id
attribute changes all over the place.

Generated qemu-ga-ref.7 also changes:

    diff -rup old/qemu-ga-ref.7 new/qemu-ga-ref.7
    --- old/qemu-ga-ref.7	2024-06-27 10:42:21.466096276 +0200
    +++ new/qemu-ga-ref.7	2024-06-27 10:45:36.502414099 +0200
    @@ -397,6 +397,7 @@ shutdown request, with no guarantee of s
     .B \fBmode\fP: \fBstring\fP (optional)
     \(dqhalt\(dq, \(dqpowerdown\(dq (default), or \(dqreboot\(dq
     .UNINDENT
    +.sp
     This command does NOT return a response on success.  Success
     condition is indicated by the VM exiting with a zero exit status or,
     when running with \-\-no\-shutdown, by issuing the query\-status QMP
    @@ -1348,6 +1349,7 @@ the new password entry string, base64 en
     .B \fBcrypted\fP: \fBboolean\fP
     true if password is already crypt()d, false if raw
     .UNINDENT
    +.sp
     If the \fBcrypted\fP flag is true, it is the caller\(aqs responsibility to
     ensure the correct crypt() encryption scheme is used.  This command
     does not attempt to interpret or report on the encryption scheme.

We add vertical space.  Visible when viewed with man.  Looks like an
improvement to me.

Here's the first of these two spots in HTML:

    -<section id="qapidoc-31">
    -<h3><a class="toc-backref" href="#id13" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">guest-shutdown</span></code> (Command)</a><a class="headerlink" href="#qapidoc-31" title="Permalink to this heading"></a></h3>
    +<section id="qapidoc-30">
    +<h3><a class="toc-backref" href="#id13" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">guest-shutdown</span></code> (Command)</a><a class="headerlink" href="#qapidoc-30" title="Permalink to this heading"></a></h3>
     <p>Initiate guest-activated shutdown.  Note: this is an asynchronous
     shutdown request, with no guarantee of successful shutdown.</p>
     <section id="qapidoc-28">
    @@ -502,22 +502,20 @@ shutdown request, with no guarantee of s
     </dd>
     </dl>
     </section>
    -<section id="qapidoc-29">
     <p>This command does NOT return a response on success.  Success
     condition is indicated by the VM exiting with a zero exit status or,
     when running with –no-shutdown, by issuing the query-status QMP
     command to confirm the VM status is “shutdown”.</p>
    -</section>
    -<section id="qapidoc-30">
    -<h4>Since<a class="headerlink" href="#qapidoc-30" title="Permalink to this heading"></a></h4>
    +<section id="qapidoc-29">
    +<h4>Since<a class="headerlink" href="#qapidoc-29" title="Permalink to this heading"></a></h4>
     <p>0.15.0</p>
     </section>
     </section>

The id changes muddy the waters.  With them manually removed:

     <section id="qapidoc-31">
     <h3><a class="toc-backref" href="#id13" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">guest-shutdown</span></code> (Command)</a><a class="headerlink" href="#qapidoc-31" title="Permalink to this heading"></a></h3>
     <p>Initiate guest-activated shutdown.  Note: this is an asynchronous
     shutdown request, with no guarantee of successful shutdown.</p>
     <section id="qapidoc-28">
    @@ -502,22 +502,20 @@ shutdown request, with no guarantee of s
     </dd>
     </dl>
     </section>
    -<section id="qapidoc-29">
     <p>This command does NOT return a response on success.  Success
     condition is indicated by the VM exiting with a zero exit status or,
     when running with –no-shutdown, by issuing the query-status QMP
     command to confirm the VM status is “shutdown”.</p>
    -</section>
     <section id="qapidoc-30">
     <h4>Since<a class="headerlink" href="#qapidoc-30" title="Permalink to this heading"></a></h4>
     <p>0.15.0</p>
     </section>
     </section>

Makes no visual difference in my browser.

Do these differences match your expectations?



^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 10/21] qapi: convert "Note" sections to plain rST
  2024-06-26 22:21 ` [PATCH v2 10/21] qapi: convert "Note" sections to plain rST John Snow
@ 2024-06-28  9:51   ` Markus Armbruster
  2024-06-28 15:44     ` John Snow
  2024-07-01 15:08   ` Markus Armbruster
  1 sibling, 1 reply; 44+ messages in thread
From: Markus Armbruster @ 2024-06-28  9:51 UTC (permalink / raw)
  To: John Snow
  Cc: qemu-devel, Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Philippe Mathieu-Daudé, Lukas Straub, Igor Mammedov,
	Jason Wang, Yanan Wang, Hanna Reitz, Konstantin Kostiuk

John Snow <jsnow@redhat.com> writes:

> We do not need a dedicated section for notes. By eliminating a specially
> parsed section, these notes can be treated as normal rST paragraphs in
> the new QMP reference manual, and can be placed and styled much more
> flexibly.
>
> Convert all existing "Note" and "Notes" sections to pure rST. As part of
> the conversion, capitalize the first letter of each sentence and add
> trailing punctuation where appropriate to ensure notes look sensible and
> consistent in rendered HTML documentation. Markup is also re-aligned to
> the de-facto standard of 3 spaces for directives.
>
> Update docs/devel/qapi-code-gen.rst to reflect the new paradigm, and
> update the QAPI parser to prohibit "Note" sections while suggesting a
> new syntax. The exact formatting to use is a matter of taste, but a good
> candidate is simply:
>
> .. note:: lorem ipsum ...
>    ... dolor sit amet ...
>    ... consectetur adipiscing elit ...
>
> ... but there are other choices, too. The Sphinx readthedocs theme
> offers theming for the following forms (capitalization unimportant); all
> are adorned with a (!) symbol () in the title bar for rendered HTML
> docs.
>
> See
> https://sphinx-rtd-theme.readthedocs.io/en/stable/demo/demo.html#admonitions
> for examples of each directive/admonition in use.
>
> These are rendered in orange:
>
> .. Attention:: ...
> .. Caution:: ...
> .. WARNING:: ...
>
> These are rendered in red:
>
> .. DANGER:: ...
> .. Error:: ...
>
> These are rendered in green:
>
> .. Hint:: ...
> .. Important:: ...
> .. Tip:: ...
>
> These are rendered in blue:
>
> .. Note:: ...
> .. admonition:: custom title
>
>    admonition body text
>
> This patch uses ".. note::" almost everywhere, with just two "caution"
> directives. Several instances of "Notes:" have been converted to merely
> ".. note::" where appropriate, but ".. admonition:: notes" is used in a
> few places where we had an ordered list of multiple notes that would not
> make sense as standalone/separate admonitions.

I looked for hunks that don't 1:1 replace "Note:" or "Notes:" by
".. note::."  Findings:

* Two hunks replace by ".. caution::" instead.  Commit message got it.
  Good.

* Four hunks replace by ".. admonition:: notes", one of them as a test.
  Commit message got it.  Good.

* Three hunks split "Notes:" into multiple ".. note::".  Good, but could
  be mentioned in commit message.

* Two hunks drop "Note:", changing it into paragraph.  The paragraph
  merges into the preceding "Example" section.  Good, but should be
  mentioned in the commit message, or turned into a separate patch.

* One hunk adjusts a test case for the removal of the "Note:" tag.
  Good, but could be mentioned in the commit message.

Perhaps tweak the paragraph above:

  This patch uses ".. note::" almost everywhere, with just two "caution"
  directives. Several instances of "Notes:" have been converted to
  merely ".. note::", or multiple ".. note::" where appropriate.
  ".. admonition:: notes" is used in a few places where we had an
  ordered list of multiple notes that would not make sense as
  standalone/separate admonitions.  Two "Note:" following "Example:"
  have been turned into ordinary paragraphs within the example.

Okay?

> NOTE: Because qapidoc.py does not attempt to preserve source ordering of
> sections, the conversion of Notes from a "tagged section" to an
> "untagged section" means that rendering order for some notes *may
> change* as a result of this patch. The forthcoming qapidoc.py rewrite
> strictly preserves source ordering in the rendered documentation, so
> this issue will be rectified in the new generator.
>
> Signed-off-by: John Snow <jsnow@redhat.com>
> Acked-by: Stefan Hajnoczi <stefanha@redhat.com> [for block*.json]

I dislike the indentation changes, and may revert them in my tree.

Reviewed-by: Markus Armbruster <armbru@redhat.com>



^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 14/21] docs/qapidoc: factor out do_parse()
  2024-06-26 22:21 ` [PATCH v2 14/21] docs/qapidoc: factor out do_parse() John Snow
@ 2024-06-28 13:08   ` Markus Armbruster
  2024-06-28 15:16     ` John Snow
  0 siblings, 1 reply; 44+ messages in thread
From: Markus Armbruster @ 2024-06-28 13:08 UTC (permalink / raw)
  To: John Snow
  Cc: qemu-devel, Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Philippe Mathieu-Daudé, Lukas Straub, Igor Mammedov,
	Jason Wang, Yanan Wang, Hanna Reitz, Konstantin Kostiuk

John Snow <jsnow@redhat.com> writes:

> Factor out the compatibility parser helper so it can be shared by other
> directives.

Suggest "Factor out the compatibility parser helper into a base class,
so it can be shared by other directives."

>
> Signed-off-by: John Snow <jsnow@redhat.com>
> ---
>  docs/sphinx/qapidoc.py | 64 +++++++++++++++++++++++-------------------
>  1 file changed, 35 insertions(+), 29 deletions(-)
>
> diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py
> index efcd84656fa..43dd99e21e6 100644
> --- a/docs/sphinx/qapidoc.py
> +++ b/docs/sphinx/qapidoc.py
> @@ -494,7 +494,41 @@ def visit_module(self, name):
>          super().visit_module(name)
>  
>  
> -class QAPIDocDirective(Directive):
> +class NestedDirective(Directive):
> +    def run(self):
> +        raise NotImplementedError

Should this class be abstract?

> +
> +    def do_parse(self, rstlist, node):
> +        """
> +        Parse rST source lines and add them to the specified node
> +
> +        Take the list of rST source lines rstlist, parse them as
> +        rST, and add the resulting docutils nodes as children of node.
> +        The nodes are parsed in a way that allows them to include
> +        subheadings (titles) without confusing the rendering of
> +        anything else.
> +        """
> +        # This is from kerneldoc.py -- it works around an API change in
> +        # Sphinx between 1.6 and 1.7. Unlike kerneldoc.py, we use
> +        # sphinx.util.nodes.nested_parse_with_titles() rather than the
> +        # plain self.state.nested_parse(), and so we can drop the saving
> +        # of title_styles and section_level that kerneldoc.py does,
> +        # because nested_parse_with_titles() does that for us.
> +        if USE_SSI:
> +            with switch_source_input(self.state, rstlist):
> +                nested_parse_with_titles(self.state, rstlist, node)
> +        else:
> +            save = self.state.memo.reporter
> +            self.state.memo.reporter = AutodocReporter(
> +                rstlist, self.state.memo.reporter
> +            )
> +            try:
> +                nested_parse_with_titles(self.state, rstlist, node)
> +            finally:
> +                self.state.memo.reporter = save
> +
> +
> +class QAPIDocDirective(NestedDirective):
>      """Extract documentation from the specified QAPI .json file"""
>  
>      required_argument = 1
> @@ -532,34 +566,6 @@ def run(self):
>              # so they are displayed nicely to the user
>              raise ExtensionError(str(err)) from err
>  
> -    def do_parse(self, rstlist, node):
> -        """Parse rST source lines and add them to the specified node
> -
> -        Take the list of rST source lines rstlist, parse them as
> -        rST, and add the resulting docutils nodes as children of node.
> -        The nodes are parsed in a way that allows them to include
> -        subheadings (titles) without confusing the rendering of
> -        anything else.
> -        """
> -        # This is from kerneldoc.py -- it works around an API change in
> -        # Sphinx between 1.6 and 1.7. Unlike kerneldoc.py, we use
> -        # sphinx.util.nodes.nested_parse_with_titles() rather than the
> -        # plain self.state.nested_parse(), and so we can drop the saving
> -        # of title_styles and section_level that kerneldoc.py does,
> -        # because nested_parse_with_titles() does that for us.
> -        if USE_SSI:
> -            with switch_source_input(self.state, rstlist):
> -                nested_parse_with_titles(self.state, rstlist, node)
> -        else:
> -            save = self.state.memo.reporter
> -            self.state.memo.reporter = AutodocReporter(
> -                rstlist, self.state.memo.reporter
> -            )
> -            try:
> -                nested_parse_with_titles(self.state, rstlist, node)
> -            finally:
> -                self.state.memo.reporter = save
> -
>  
>  def setup(app):
>      """Register qapi-doc directive with Sphinx"""

Reviewed-by: Markus Armbruster <armbru@redhat.com>



^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 15/21] docs/qapidoc: create qmp-example directive
  2024-06-26 22:21 ` [PATCH v2 15/21] docs/qapidoc: create qmp-example directive John Snow
@ 2024-06-28 13:24   ` Markus Armbruster
  2024-06-28 15:24     ` John Snow
  0 siblings, 1 reply; 44+ messages in thread
From: Markus Armbruster @ 2024-06-28 13:24 UTC (permalink / raw)
  To: John Snow
  Cc: qemu-devel, Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Philippe Mathieu-Daudé, Lukas Straub, Igor Mammedov,
	Jason Wang, Yanan Wang, Hanna Reitz, Konstantin Kostiuk

John Snow <jsnow@redhat.com> writes:

> This is a directive that creates a syntactic sugar for creating
> "Example" boxes very similar to the ones already used in the bitmaps.rst
> document, please see e.g.
> https://www.qemu.org/docs/master/interop/bitmaps.html#creation-block-dirty-bitmap-add
>
> In its simplest form, when a custom title is not needed or wanted, and
> the example body is *solely* a QMP example:
>
> ```
> .. qmp-example::
>
>    {body}
> ```
>
> is syntactic sugar for:
>
> ```
> .. admonition:: Example:
>
>    .. code-block:: QMP
>
>       {body}
> ```
>
> When a custom, plaintext title that describes the example is desired,
> this form:
>
> ```
> .. qmp-example::
>    :title: Defrobnification
>
>    {body}
> ```
>
> Is syntactic sugar for:
>
> ```
> .. admonition:: Example: Defrobnification
>
>    .. code-block:: QMP
>
>       {body}
> ```
>
> Lastly, when Examples are multi-step processes that require non-QMP
> exposition, have lengthy titles, or otherwise involve prose with rST
> markup (lists, cross-references, etc), the most complex form:
>
> ```
> .. qmp-example::
>    :annotated:
>
>    This example shows how to use `foo-command`::
>
>      {body}
> ```
>
> Is desugared to:
>
> ```
> .. admonition:: Example:
>
>    This example shows how to use `foo-command`::
>
>      {body}
>
>    For more information, please see `frobnozz`.
> ```

Can we combine the latter two?  Like this:

  .. qmp-example::
     :title: Defrobnification
     :annotated:

     This example shows how to use `foo-command`::

       {body}

> The primary benefit here being documentation source consistently using
> the same directive for all forms of examples to ensure consistent visual
> styling, and ensuring all relevant prose is visually grouped alongside
> the code literal block.
>
> Note that as of this commit, the code-block rST syntax "::" does not
> apply QMP highlighting; you would need to use ".. code-block:: QMP". The
> very next commit changes this behavior to assume all "::" code blocks
> within this directive are QMP blocks.
>
> Signed-off-by: John Snow <jsnow@redhat.com>
> ---
>  docs/sphinx/qapidoc.py | 60 ++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 58 insertions(+), 2 deletions(-)

No tests?  Hmm, I see you convert existing tests in PATCH 19-21.  While
that works, test coverage now would make it easier to see how each patch
affects doc generator output.

> diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py
> index 43dd99e21e6..a2fa05fc491 100644
> --- a/docs/sphinx/qapidoc.py
> +++ b/docs/sphinx/qapidoc.py
> @@ -27,16 +27,19 @@
>  import os
>  import re
>  import textwrap
> +from typing import List
>  
>  from docutils import nodes
> -from docutils.parsers.rst import Directive, directives
> +from docutils.parsers.rst import directives
>  from docutils.statemachine import ViewList
>  from qapi.error import QAPIError, QAPISemError
>  from qapi.gen import QAPISchemaVisitor
>  from qapi.schema import QAPISchema
>  
>  import sphinx
> +from sphinx.directives.code import CodeBlock
>  from sphinx.errors import ExtensionError
> +from sphinx.util.docutils import SphinxDirective
>  from sphinx.util.nodes import nested_parse_with_titles
>  
>  
> @@ -494,7 +497,7 @@ def visit_module(self, name):
>          super().visit_module(name)
>  
>  
> -class NestedDirective(Directive):
> +class NestedDirective(SphinxDirective):

What is this about?

>      def run(self):
>          raise NotImplementedError
>  
> @@ -567,10 +570,63 @@ def run(self):
>              raise ExtensionError(str(err)) from err
>  
>  
> +class QMPExample(CodeBlock, NestedDirective):
> +    """
> +    Custom admonition for QMP code examples.
> +
> +    When the :annotated: option is present, the body of this directive
> +    is parsed as normal rST instead. Code blocks must be explicitly
> +    written by the user, but this allows for intermingling explanatory
> +    paragraphs with arbitrary rST syntax and code blocks for more
> +    involved examples.
> +
> +    When :annotated: is absent, the directive body is treated as a
> +    simple standalone QMP code block literal.
> +    """
> +
> +    required_argument = 0
> +    optional_arguments = 0
> +    has_content = True
> +    option_spec = {
> +        "annotated": directives.flag,
> +        "title": directives.unchanged,
> +    }
> +
> +    def admonition_wrap(self, *content) -> List[nodes.Node]:
> +        title = "Example:"
> +        if "title" in self.options:
> +            title = f"{title} {self.options['title']}"
> +
> +        admon = nodes.admonition(
> +            "",
> +            nodes.title("", title),
> +            *content,
> +            classes=["admonition", "admonition-example"],
> +        )
> +        return [admon]
> +
> +    def run_annotated(self) -> List[nodes.Node]:
> +        content_node: nodes.Element = nodes.section()
> +        self.do_parse(self.content, content_node)
> +        return content_node.children
> +
> +    def run(self) -> List[nodes.Node]:
> +        annotated = "annotated" in self.options
> +
> +        if annotated:
> +            content_nodes = self.run_annotated()
> +        else:
> +            self.arguments = ["QMP"]
> +            content_nodes = super().run()
> +
> +        return self.admonition_wrap(*content_nodes)
> +
> +
>  def setup(app):
>      """Register qapi-doc directive with Sphinx"""
>      app.add_config_value("qapidoc_srctree", None, "env")
>      app.add_directive("qapi-doc", QAPIDocDirective)
> +    app.add_directive("qmp-example", QMPExample)
>  
>      return {
>          "version": __version__,



^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 04/21] docs/qapidoc: delint a tiny portion of the module
  2024-06-28  7:29   ` Markus Armbruster
@ 2024-06-28 14:36     ` John Snow
  0 siblings, 0 replies; 44+ messages in thread
From: John Snow @ 2024-06-28 14:36 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, Qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Philippe Mathieu-Daudé, Lukas Straub, Igor Mammedov,
	Jason Wang, Yanan Wang, Hanna Reitz, Konstantin Kostiuk

[-- Attachment #1: Type: text/plain, Size: 1466 bytes --]

On Fri, Jun 28, 2024, 3:29 AM Markus Armbruster <armbru@redhat.com> wrote:

> John Snow <jsnow@redhat.com> writes:
>
> > In a forthcoming series that adds a new QMP documentation generator, it
> > will be helpful to have a linting baseline. However, there's no need to
> > shuffle around the deck chairs too much, because most of this code will
> > be removed once that new qapidoc generator (the "transmogrifier") is in
> > place.
> >
> > To ease my pain: just turn off the black auto-formatter for most, but
> > not all, of qapidoc.py. This will help ensure that *new* code follows a
> > coding standard without bothering too much with cleaning up the existing
> > code.
> >
> > Code that I intend to keep is still subject to the delinting beam.
> >
> > Signed-off-by: John Snow <jsnow@redhat.com>
> > Reviewed-by: Markus Armbruster <armbru@redhat.com>
>
> Not an objection, just so you know: I still see a few C0411 like 'third
> party import "import sphinx" should be placed before ...'
>
> R-by stands.
>

Yeah, I think it depends on precisely where you run the script. I think
because the folder is named "sphinx" that it confuses the tools in certain
contexts.

I'm not worried about it because we don't have an enforcement paradigm yet
- I stick to my little self-test script just to make sure I'm being
self-consistent, but I figured I'd worry about broader compatibility later
when I reshuffle the deck chairs for qapi.

[-- Attachment #2: Type: text/html, Size: 2422 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 07/21] docs/qapidoc: fix nested parsing under untagged sections
  2024-06-28  7:54   ` Markus Armbruster
@ 2024-06-28 15:10     ` John Snow
  2024-06-28 15:28       ` John Snow
  2024-07-01  9:11       ` Markus Armbruster
  0 siblings, 2 replies; 44+ messages in thread
From: John Snow @ 2024-06-28 15:10 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, Qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Philippe Mathieu-Daudé, Lukas Straub, Igor Mammedov,
	Jason Wang, Yanan Wang, Hanna Reitz, Konstantin Kostiuk

[-- Attachment #1: Type: text/plain, Size: 5557 bytes --]

On Fri, Jun 28, 2024, 3:55 AM Markus Armbruster <armbru@redhat.com> wrote:

> John Snow <jsnow@redhat.com> writes:
>
> > Sphinx does not like sections without titles, because it wants to
> > convert every section into a reference. When there is no title, it
> > struggles to do this and transforms the tree inproperly.
> >
> > Depending on the rST used, this may result in an assertion error deep in
> > the docutils HTMLWriter.
> >
> > (Observed when using ".. admonition:: Notes" under such a section - When
> > this is transformed with its own <title> element, Sphinx is fooled into
> > believing this title belongs to the section and incorrect mutates the
> > docutils tree, leading to errors during rendering time.)
> >
> > When parsing an untagged section (free paragraphs), skip making a hollow
> > section and instead append the parse results to the prior section.
> >
> > Many Bothans died to bring us this information.
> >
> > Signed-off-by: John Snow <jsnow@redhat.com>
> > Acked-by: Markus Armbruster <armbru@redhat.com>
>
> Generated HTML changes, but the diff is hard to review due to id
> attribute changes all over the place.
>
> Generated qemu-ga-ref.7 also changes:
>
>     diff -rup old/qemu-ga-ref.7 new/qemu-ga-ref.7
>     --- old/qemu-ga-ref.7       2024-06-27 10:42:21.466096276 +0200
>     +++ new/qemu-ga-ref.7       2024-06-27 10:45:36.502414099 +0200
>     @@ -397,6 +397,7 @@ shutdown request, with no guarantee of s
>      .B \fBmode\fP: \fBstring\fP (optional)
>      \(dqhalt\(dq, \(dqpowerdown\(dq (default), or \(dqreboot\(dq
>      .UNINDENT
>     +.sp
>      This command does NOT return a response on success.  Success
>      condition is indicated by the VM exiting with a zero exit status or,
>      when running with \-\-no\-shutdown, by issuing the query\-status QMP
>     @@ -1348,6 +1349,7 @@ the new password entry string, base64 en
>      .B \fBcrypted\fP: \fBboolean\fP
>      true if password is already crypt()d, false if raw
>      .UNINDENT
>     +.sp
>      If the \fBcrypted\fP flag is true, it is the caller\(aqs
> responsibility to
>      ensure the correct crypt() encryption scheme is used.  This command
>      does not attempt to interpret or report on the encryption scheme.
>
> We add vertical space.  Visible when viewed with man.  Looks like an
> improvement to me.
>
> Here's the first of these two spots in HTML:
>
>     -<section id="qapidoc-31">
>     -<h3><a class="toc-backref" href="#id13" role="doc-backlink"><code
> class="docutils literal notranslate"><span
> class="pre">guest-shutdown</span></code> (Command)</a><a class="headerlink"
> href="#qapidoc-31" title="Permalink to this heading"></a></h3>
>     +<section id="qapidoc-30">
>     +<h3><a class="toc-backref" href="#id13" role="doc-backlink"><code
> class="docutils literal notranslate"><span
> class="pre">guest-shutdown</span></code> (Command)</a><a class="headerlink"
> href="#qapidoc-30" title="Permalink to this heading"></a></h3>
>      <p>Initiate guest-activated shutdown.  Note: this is an asynchronous
>      shutdown request, with no guarantee of successful shutdown.</p>
>      <section id="qapidoc-28">
>     @@ -502,22 +502,20 @@ shutdown request, with no guarantee of s
>      </dd>
>      </dl>
>      </section>
>     -<section id="qapidoc-29">
>      <p>This command does NOT return a response on success.  Success
>      condition is indicated by the VM exiting with a zero exit status or,
>      when running with –no-shutdown, by issuing the query-status QMP
>      command to confirm the VM status is “shutdown”.</p>
>     -</section>
>     -<section id="qapidoc-30">
>     -<h4>Since<a class="headerlink" href="#qapidoc-30" title="Permalink to
> this heading"></a></h4>
>     +<section id="qapidoc-29">
>     +<h4>Since<a class="headerlink" href="#qapidoc-29" title="Permalink to
> this heading"></a></h4>
>      <p>0.15.0</p>
>      </section>
>      </section>
>
> The id changes muddy the waters.  With them manually removed:
>
>      <section id="qapidoc-31">
>      <h3><a class="toc-backref" href="#id13" role="doc-backlink"><code
> class="docutils literal notranslate"><span
> class="pre">guest-shutdown</span></code> (Command)</a><a class="headerlink"
> href="#qapidoc-31" title="Permalink to this heading"></a></h3>
>      <p>Initiate guest-activated shutdown.  Note: this is an asynchronous
>      shutdown request, with no guarantee of successful shutdown.</p>
>      <section id="qapidoc-28">
>     @@ -502,22 +502,20 @@ shutdown request, with no guarantee of s
>      </dd>
>      </dl>
>      </section>
>     -<section id="qapidoc-29">
>      <p>This command does NOT return a response on success.  Success
>      condition is indicated by the VM exiting with a zero exit status or,
>      when running with –no-shutdown, by issuing the query-status QMP
>      command to confirm the VM status is “shutdown”.</p>
>     -</section>
>      <section id="qapidoc-30">
>      <h4>Since<a class="headerlink" href="#qapidoc-30" title="Permalink to
> this heading"></a></h4>
>      <p>0.15.0</p>
>      </section>
>      </section>
>
> Makes no visual difference in my browser.
>
> Do these differences match your expectations?
>

Yep!

It does change the output just a little, but Sphinx really doesn't like
title-less sections.

I thought the change looked fine, and I'm still planning on removing this
old generator anyway, so...

>

[-- Attachment #2: Type: text/html, Size: 7687 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 14/21] docs/qapidoc: factor out do_parse()
  2024-06-28 13:08   ` Markus Armbruster
@ 2024-06-28 15:16     ` John Snow
  0 siblings, 0 replies; 44+ messages in thread
From: John Snow @ 2024-06-28 15:16 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, Qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Philippe Mathieu-Daudé, Lukas Straub, Igor Mammedov,
	Jason Wang, Yanan Wang, Hanna Reitz, Konstantin Kostiuk

[-- Attachment #1: Type: text/plain, Size: 4820 bytes --]

On Fri, Jun 28, 2024, 9:09 AM Markus Armbruster <armbru@redhat.com> wrote:

> John Snow <jsnow@redhat.com> writes:
>
> > Factor out the compatibility parser helper so it can be shared by other
> > directives.
>
> Suggest "Factor out the compatibility parser helper into a base class,
> so it can be shared by other directives."


Sure. Haven't read the other mails yet. I'll make the change if you want a
v3, otherwise feel free to edit.


> >
> > Signed-off-by: John Snow <jsnow@redhat.com>
> > ---
> >  docs/sphinx/qapidoc.py | 64 +++++++++++++++++++++++-------------------
> >  1 file changed, 35 insertions(+), 29 deletions(-)
> >
> > diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py
> > index efcd84656fa..43dd99e21e6 100644
> > --- a/docs/sphinx/qapidoc.py
> > +++ b/docs/sphinx/qapidoc.py
> > @@ -494,7 +494,41 @@ def visit_module(self, name):
> >          super().visit_module(name)
> >
> >
> > -class QAPIDocDirective(Directive):
> > +class NestedDirective(Directive):
> > +    def run(self):
> > +        raise NotImplementedError
>
> Should this class be abstract?
>

It could be ...

*sneezes*

I plan to delete it by the end of the qapi-domain series anyway, or perhaps
I could even delete it *before* with a dedicated "require sphinx >= 3.x"
miniseries.

Actually, that's probably a really good idea...


> > +
> > +    def do_parse(self, rstlist, node):
> > +        """
> > +        Parse rST source lines and add them to the specified node
> > +
> > +        Take the list of rST source lines rstlist, parse them as
> > +        rST, and add the resulting docutils nodes as children of node.
> > +        The nodes are parsed in a way that allows them to include
> > +        subheadings (titles) without confusing the rendering of
> > +        anything else.
> > +        """
> > +        # This is from kerneldoc.py -- it works around an API change in
> > +        # Sphinx between 1.6 and 1.7. Unlike kerneldoc.py, we use
> > +        # sphinx.util.nodes.nested_parse_with_titles() rather than the
> > +        # plain self.state.nested_parse(), and so we can drop the saving
> > +        # of title_styles and section_level that kerneldoc.py does,
> > +        # because nested_parse_with_titles() does that for us.
> > +        if USE_SSI:
> > +            with switch_source_input(self.state, rstlist):
> > +                nested_parse_with_titles(self.state, rstlist, node)
> > +        else:
> > +            save = self.state.memo.reporter
> > +            self.state.memo.reporter = AutodocReporter(
> > +                rstlist, self.state.memo.reporter
> > +            )
> > +            try:
> > +                nested_parse_with_titles(self.state, rstlist, node)
> > +            finally:
> > +                self.state.memo.reporter = save
> > +
> > +
> > +class QAPIDocDirective(NestedDirective):
> >      """Extract documentation from the specified QAPI .json file"""
> >
> >      required_argument = 1
> > @@ -532,34 +566,6 @@ def run(self):
> >              # so they are displayed nicely to the user
> >              raise ExtensionError(str(err)) from err
> >
> > -    def do_parse(self, rstlist, node):
> > -        """Parse rST source lines and add them to the specified node
> > -
> > -        Take the list of rST source lines rstlist, parse them as
> > -        rST, and add the resulting docutils nodes as children of node.
> > -        The nodes are parsed in a way that allows them to include
> > -        subheadings (titles) without confusing the rendering of
> > -        anything else.
> > -        """
> > -        # This is from kerneldoc.py -- it works around an API change in
> > -        # Sphinx between 1.6 and 1.7. Unlike kerneldoc.py, we use
> > -        # sphinx.util.nodes.nested_parse_with_titles() rather than the
> > -        # plain self.state.nested_parse(), and so we can drop the saving
> > -        # of title_styles and section_level that kerneldoc.py does,
> > -        # because nested_parse_with_titles() does that for us.
> > -        if USE_SSI:
> > -            with switch_source_input(self.state, rstlist):
> > -                nested_parse_with_titles(self.state, rstlist, node)
> > -        else:
> > -            save = self.state.memo.reporter
> > -            self.state.memo.reporter = AutodocReporter(
> > -                rstlist, self.state.memo.reporter
> > -            )
> > -            try:
> > -                nested_parse_with_titles(self.state, rstlist, node)
> > -            finally:
> > -                self.state.memo.reporter = save
> > -
> >
> >  def setup(app):
> >      """Register qapi-doc directive with Sphinx"""
>
> Reviewed-by: Markus Armbruster <armbru@redhat.com>
>
>

[-- Attachment #2: Type: text/html, Size: 6871 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 15/21] docs/qapidoc: create qmp-example directive
  2024-06-28 13:24   ` Markus Armbruster
@ 2024-06-28 15:24     ` John Snow
  0 siblings, 0 replies; 44+ messages in thread
From: John Snow @ 2024-06-28 15:24 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, Qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Philippe Mathieu-Daudé, Lukas Straub, Igor Mammedov,
	Jason Wang, Yanan Wang, Hanna Reitz, Konstantin Kostiuk

[-- Attachment #1: Type: text/plain, Size: 6952 bytes --]

On Fri, Jun 28, 2024, 9:24 AM Markus Armbruster <armbru@redhat.com> wrote:

> John Snow <jsnow@redhat.com> writes:
>
> > This is a directive that creates a syntactic sugar for creating
> > "Example" boxes very similar to the ones already used in the bitmaps.rst
> > document, please see e.g.
> >
> https://www.qemu.org/docs/master/interop/bitmaps.html#creation-block-dirty-bitmap-add
> >
> > In its simplest form, when a custom title is not needed or wanted, and
> > the example body is *solely* a QMP example:
> >
> > ```
> > .. qmp-example::
> >
> >    {body}
> > ```
> >
> > is syntactic sugar for:
> >
> > ```
> > .. admonition:: Example:
> >
> >    .. code-block:: QMP
> >
> >       {body}
> > ```
> >
> > When a custom, plaintext title that describes the example is desired,
> > this form:
> >
> > ```
> > .. qmp-example::
> >    :title: Defrobnification
> >
> >    {body}
> > ```
> >
> > Is syntactic sugar for:
> >
> > ```
> > .. admonition:: Example: Defrobnification
> >
> >    .. code-block:: QMP
> >
> >       {body}
> > ```
> >
> > Lastly, when Examples are multi-step processes that require non-QMP
> > exposition, have lengthy titles, or otherwise involve prose with rST
> > markup (lists, cross-references, etc), the most complex form:
> >
> > ```
> > .. qmp-example::
> >    :annotated:
> >
> >    This example shows how to use `foo-command`::
> >
> >      {body}
> > ```
> >
> > Is desugared to:
> >
> > ```
> > .. admonition:: Example:
> >
> >    This example shows how to use `foo-command`::
> >
> >      {body}
> >
> >    For more information, please see `frobnozz`.
> > ```
>

^ Whoops, added prose in the desugar block without modifying the original.


> Can we combine the latter two?  Like this:
>
>   .. qmp-example::
>      :title: Defrobnification
>      :annotated:
>
>      This example shows how to use `foo-command`::
>
>        {body}
>

Yes! I only didn't use that form in the series because splitting longer
Examples into title and prose felt like an editorial decision, but
absolutely you can use both.


> > The primary benefit here being documentation source consistently using
> > the same directive for all forms of examples to ensure consistent visual
> > styling, and ensuring all relevant prose is visually grouped alongside
> > the code literal block.
> >
> > Note that as of this commit, the code-block rST syntax "::" does not
> > apply QMP highlighting; you would need to use ".. code-block:: QMP". The
> > very next commit changes this behavior to assume all "::" code blocks
> > within this directive are QMP blocks.
> >
> > Signed-off-by: John Snow <jsnow@redhat.com>
> > ---
> >  docs/sphinx/qapidoc.py | 60 ++++++++++++++++++++++++++++++++++++++++--
> >  1 file changed, 58 insertions(+), 2 deletions(-)
>
> No tests?  Hmm, I see you convert existing tests in PATCH 19-21.  While
> that works, test coverage now would make it easier to see how each patch
> affects doc generator output.
>

Mmm. Do you want me to move the test changes up to this patch ... ?


> > diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py
> > index 43dd99e21e6..a2fa05fc491 100644
> > --- a/docs/sphinx/qapidoc.py
> > +++ b/docs/sphinx/qapidoc.py
> > @@ -27,16 +27,19 @@
> >  import os
> >  import re
> >  import textwrap
> > +from typing import List
> >
> >  from docutils import nodes
> > -from docutils.parsers.rst import Directive, directives
> > +from docutils.parsers.rst import directives
> >  from docutils.statemachine import ViewList
> >  from qapi.error import QAPIError, QAPISemError
> >  from qapi.gen import QAPISchemaVisitor
> >  from qapi.schema import QAPISchema
> >
> >  import sphinx
> > +from sphinx.directives.code import CodeBlock
> >  from sphinx.errors import ExtensionError
> > +from sphinx.util.docutils import SphinxDirective
> >  from sphinx.util.nodes import nested_parse_with_titles
> >
> >
> > @@ -494,7 +497,7 @@ def visit_module(self, name):
> >          super().visit_module(name)
> >
> >
> > -class NestedDirective(Directive):
> > +class NestedDirective(SphinxDirective):
>
> What is this about?
>

Hmm. Strictly it's for access to sphinx configuration which I use only in
the next patch, but practically I suspect if I don't change it *here* that
the multiple inheritance from CodeBlock (which is a SphinxDirective) would
possibly be stranger.

I can try delaying that change by a patch and see if it hurts anything ...


> >      def run(self):
> >          raise NotImplementedError
> >
> > @@ -567,10 +570,63 @@ def run(self):
> >              raise ExtensionError(str(err)) from err
> >
> >
> > +class QMPExample(CodeBlock, NestedDirective):
> > +    """
> > +    Custom admonition for QMP code examples.
> > +
> > +    When the :annotated: option is present, the body of this directive
> > +    is parsed as normal rST instead. Code blocks must be explicitly
> > +    written by the user, but this allows for intermingling explanatory
> > +    paragraphs with arbitrary rST syntax and code blocks for more
> > +    involved examples.
> > +
> > +    When :annotated: is absent, the directive body is treated as a
> > +    simple standalone QMP code block literal.
> > +    """
> > +
> > +    required_argument = 0
> > +    optional_arguments = 0
> > +    has_content = True
> > +    option_spec = {
> > +        "annotated": directives.flag,
> > +        "title": directives.unchanged,
> > +    }
> > +
> > +    def admonition_wrap(self, *content) -> List[nodes.Node]:
> > +        title = "Example:"
> > +        if "title" in self.options:
> > +            title = f"{title} {self.options['title']}"
> > +
> > +        admon = nodes.admonition(
> > +            "",
> > +            nodes.title("", title),
> > +            *content,
> > +            classes=["admonition", "admonition-example"],
> > +        )
> > +        return [admon]
> > +
> > +    def run_annotated(self) -> List[nodes.Node]:
> > +        content_node: nodes.Element = nodes.section()
> > +        self.do_parse(self.content, content_node)
> > +        return content_node.children
> > +
> > +    def run(self) -> List[nodes.Node]:
> > +        annotated = "annotated" in self.options
> > +
> > +        if annotated:
> > +            content_nodes = self.run_annotated()
> > +        else:
> > +            self.arguments = ["QMP"]
> > +            content_nodes = super().run()
> > +
> > +        return self.admonition_wrap(*content_nodes)
> > +
> > +
> >  def setup(app):
> >      """Register qapi-doc directive with Sphinx"""
> >      app.add_config_value("qapidoc_srctree", None, "env")
> >      app.add_directive("qapi-doc", QAPIDocDirective)
> > +    app.add_directive("qmp-example", QMPExample)
> >
> >      return {
> >          "version": __version__,
>
>

[-- Attachment #2: Type: text/html, Size: 10009 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 07/21] docs/qapidoc: fix nested parsing under untagged sections
  2024-06-28 15:10     ` John Snow
@ 2024-06-28 15:28       ` John Snow
  2024-07-01  9:11       ` Markus Armbruster
  1 sibling, 0 replies; 44+ messages in thread
From: John Snow @ 2024-06-28 15:28 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, Qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Philippe Mathieu-Daudé, Lukas Straub, Igor Mammedov,
	Jason Wang, Yanan Wang, Hanna Reitz, Konstantin Kostiuk

[-- Attachment #1: Type: text/plain, Size: 5865 bytes --]

On Fri, Jun 28, 2024, 11:10 AM John Snow <jsnow@redhat.com> wrote:

>
>
> On Fri, Jun 28, 2024, 3:55 AM Markus Armbruster <armbru@redhat.com> wrote:
>
>> John Snow <jsnow@redhat.com> writes:
>>
>> > Sphinx does not like sections without titles, because it wants to
>> > convert every section into a reference. When there is no title, it
>> > struggles to do this and transforms the tree inproperly.
>> >
>> > Depending on the rST used, this may result in an assertion error deep in
>> > the docutils HTMLWriter.
>> >
>> > (Observed when using ".. admonition:: Notes" under such a section - When
>> > this is transformed with its own <title> element, Sphinx is fooled into
>> > believing this title belongs to the section and incorrect mutates the
>> > docutils tree, leading to errors during rendering time.)
>> >
>> > When parsing an untagged section (free paragraphs), skip making a hollow
>> > section and instead append the parse results to the prior section.
>> >
>> > Many Bothans died to bring us this information.
>> >
>> > Signed-off-by: John Snow <jsnow@redhat.com>
>> > Acked-by: Markus Armbruster <armbru@redhat.com>
>>
>> Generated HTML changes, but the diff is hard to review due to id
>> attribute changes all over the place.
>>
>> Generated qemu-ga-ref.7 also changes:
>>
>>     diff -rup old/qemu-ga-ref.7 new/qemu-ga-ref.7
>>     --- old/qemu-ga-ref.7       2024-06-27 10:42:21.466096276 +0200
>>     +++ new/qemu-ga-ref.7       2024-06-27 10:45:36.502414099 +0200
>>     @@ -397,6 +397,7 @@ shutdown request, with no guarantee of s
>>      .B \fBmode\fP: \fBstring\fP (optional)
>>      \(dqhalt\(dq, \(dqpowerdown\(dq (default), or \(dqreboot\(dq
>>      .UNINDENT
>>     +.sp
>>      This command does NOT return a response on success.  Success
>>      condition is indicated by the VM exiting with a zero exit status or,
>>      when running with \-\-no\-shutdown, by issuing the query\-status QMP
>>     @@ -1348,6 +1349,7 @@ the new password entry string, base64 en
>>      .B \fBcrypted\fP: \fBboolean\fP
>>      true if password is already crypt()d, false if raw
>>      .UNINDENT
>>     +.sp
>>      If the \fBcrypted\fP flag is true, it is the caller\(aqs
>> responsibility to
>>      ensure the correct crypt() encryption scheme is used.  This command
>>      does not attempt to interpret or report on the encryption scheme.
>>
>> We add vertical space.  Visible when viewed with man.  Looks like an
>> improvement to me.
>>
>> Here's the first of these two spots in HTML:
>>
>>     -<section id="qapidoc-31">
>>     -<h3><a class="toc-backref" href="#id13" role="doc-backlink"><code
>> class="docutils literal notranslate"><span
>> class="pre">guest-shutdown</span></code> (Command)</a><a class="headerlink"
>> href="#qapidoc-31" title="Permalink to this heading"></a></h3>
>>     +<section id="qapidoc-30">
>>     +<h3><a class="toc-backref" href="#id13" role="doc-backlink"><code
>> class="docutils literal notranslate"><span
>> class="pre">guest-shutdown</span></code> (Command)</a><a class="headerlink"
>> href="#qapidoc-30" title="Permalink to this heading"></a></h3>
>>      <p>Initiate guest-activated shutdown.  Note: this is an asynchronous
>>      shutdown request, with no guarantee of successful shutdown.</p>
>>      <section id="qapidoc-28">
>>     @@ -502,22 +502,20 @@ shutdown request, with no guarantee of s
>>      </dd>
>>      </dl>
>>      </section>
>>     -<section id="qapidoc-29">
>>      <p>This command does NOT return a response on success.  Success
>>      condition is indicated by the VM exiting with a zero exit status or,
>>      when running with –no-shutdown, by issuing the query-status QMP
>>      command to confirm the VM status is “shutdown”.</p>
>>     -</section>
>>     -<section id="qapidoc-30">
>>     -<h4>Since<a class="headerlink" href="#qapidoc-30" title="Permalink
>> to this heading"></a></h4>
>>     +<section id="qapidoc-29">
>>     +<h4>Since<a class="headerlink" href="#qapidoc-29" title="Permalink
>> to this heading"></a></h4>
>>      <p>0.15.0</p>
>>      </section>
>>      </section>
>>
>> The id changes muddy the waters.  With them manually removed:
>>
>>      <section id="qapidoc-31">
>>      <h3><a class="toc-backref" href="#id13" role="doc-backlink"><code
>> class="docutils literal notranslate"><span
>> class="pre">guest-shutdown</span></code> (Command)</a><a class="headerlink"
>> href="#qapidoc-31" title="Permalink to this heading"></a></h3>
>>      <p>Initiate guest-activated shutdown.  Note: this is an asynchronous
>>      shutdown request, with no guarantee of successful shutdown.</p>
>>      <section id="qapidoc-28">
>>     @@ -502,22 +502,20 @@ shutdown request, with no guarantee of s
>>      </dd>
>>      </dl>
>>      </section>
>>     -<section id="qapidoc-29">
>>      <p>This command does NOT return a response on success.  Success
>>      condition is indicated by the VM exiting with a zero exit status or,
>>      when running with –no-shutdown, by issuing the query-status QMP
>>      command to confirm the VM status is “shutdown”.</p>
>>     -</section>
>>      <section id="qapidoc-30">
>>      <h4>Since<a class="headerlink" href="#qapidoc-30" title="Permalink
>> to this heading"></a></h4>
>>      <p>0.15.0</p>
>>      </section>
>>      </section>
>>
>> Makes no visual difference in my browser.
>>
>> Do these differences match your expectations?
>>
>
> Yep!
>
> It does change the output just a little, but Sphinx really doesn't like
> title-less sections.
>
> I thought the change looked fine, and I'm still planning on removing this
> old generator anyway, so...
>

Oh, pro tip: try using the xml builder before and after for a cleaner
comparison.

--js

>

[-- Attachment #2: Type: text/html, Size: 8469 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 10/21] qapi: convert "Note" sections to plain rST
  2024-06-28  9:51   ` Markus Armbruster
@ 2024-06-28 15:44     ` John Snow
  0 siblings, 0 replies; 44+ messages in thread
From: John Snow @ 2024-06-28 15:44 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, Qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Philippe Mathieu-Daudé, Lukas Straub, Igor Mammedov,
	Jason Wang, Yanan Wang, Hanna Reitz, Konstantin Kostiuk

[-- Attachment #1: Type: text/plain, Size: 4921 bytes --]

On Fri, Jun 28, 2024, 5:52 AM Markus Armbruster <armbru@redhat.com> wrote:

> John Snow <jsnow@redhat.com> writes:
>
> > We do not need a dedicated section for notes. By eliminating a specially
> > parsed section, these notes can be treated as normal rST paragraphs in
> > the new QMP reference manual, and can be placed and styled much more
> > flexibly.
> >
> > Convert all existing "Note" and "Notes" sections to pure rST. As part of
> > the conversion, capitalize the first letter of each sentence and add
> > trailing punctuation where appropriate to ensure notes look sensible and
> > consistent in rendered HTML documentation. Markup is also re-aligned to
> > the de-facto standard of 3 spaces for directives.
> >
> > Update docs/devel/qapi-code-gen.rst to reflect the new paradigm, and
> > update the QAPI parser to prohibit "Note" sections while suggesting a
> > new syntax. The exact formatting to use is a matter of taste, but a good
> > candidate is simply:
> >
> > .. note:: lorem ipsum ...
> >    ... dolor sit amet ...
> >    ... consectetur adipiscing elit ...
> >
> > ... but there are other choices, too. The Sphinx readthedocs theme
> > offers theming for the following forms (capitalization unimportant); all
> > are adorned with a (!) symbol () in the title bar for rendered HTML
> > docs.
> >
> > See
> >
> https://sphinx-rtd-theme.readthedocs.io/en/stable/demo/demo.html#admonitions
> > for examples of each directive/admonition in use.
> >
> > These are rendered in orange:
> >
> > .. Attention:: ...
> > .. Caution:: ...
> > .. WARNING:: ...
> >
> > These are rendered in red:
> >
> > .. DANGER:: ...
> > .. Error:: ...
> >
> > These are rendered in green:
> >
> > .. Hint:: ...
> > .. Important:: ...
> > .. Tip:: ...
> >
> > These are rendered in blue:
> >
> > .. Note:: ...
> > .. admonition:: custom title
> >
> >    admonition body text
> >
> > This patch uses ".. note::" almost everywhere, with just two "caution"
> > directives. Several instances of "Notes:" have been converted to merely
> > ".. note::" where appropriate, but ".. admonition:: notes" is used in a
> > few places where we had an ordered list of multiple notes that would not
> > make sense as standalone/separate admonitions.
>
> I looked for hunks that don't 1:1 replace "Note:" or "Notes:" by
> ".. note::."  Findings:
>
> * Two hunks replace by ".. caution::" instead.  Commit message got it.
>   Good.
>
> * Four hunks replace by ".. admonition:: notes", one of them as a test.
>   Commit message got it.  Good.
>
> * Three hunks split "Notes:" into multiple ".. note::".  Good, but could
>   be mentioned in commit message.
>

I meant to imply it when discussing when admonition was used, but yeah.


> * Two hunks drop "Note:", changing it into paragraph.  The paragraph
>   merges into the preceding "Example" section.  Good, but should be
>   mentioned in the commit message, or turned into a separate patch.
>

Eh. we got enough commits. I think it's helpful to keep the whole
conversion in one giant bang so that the diff is helpful in illustrating
all of the different types of conversions.

(In fact, even though I split out Example conversion for your sake in
review, I think it'd be helpful to squash them together on merge for the
same exact reason.)

Let's just amend the commit message.


> * One hunk adjusts a test case for the removal of the "Note:" tag.
>   Good, but could be mentioned in the commit message.
>
> Perhaps tweak the paragraph above:
>
>   This patch uses ".. note::" almost everywhere, with just two "caution"
>   directives. Several instances of "Notes:" have been converted to
>   merely ".. note::", or multiple ".. note::" where appropriate.
>   ".. admonition:: notes" is used in a few places where we had an
>   ordered list of multiple notes that would not make sense as
>   standalone/separate admonitions.  Two "Note:" following "Example:"
>   have been turned into ordinary paragraphs within the example.
>
> Okay?
>

Yep, suits me fine.


> > NOTE: Because qapidoc.py does not attempt to preserve source ordering of
> > sections, the conversion of Notes from a "tagged section" to an
> > "untagged section" means that rendering order for some notes *may
> > change* as a result of this patch. The forthcoming qapidoc.py rewrite
> > strictly preserves source ordering in the rendered documentation, so
> > this issue will be rectified in the new generator.
> >
> > Signed-off-by: John Snow <jsnow@redhat.com>
> > Acked-by: Stefan Hajnoczi <stefanha@redhat.com> [for block*.json]
>
> I dislike the indentation changes, and may revert them in my tree.
>

😢

Would you take a patch adjusting the indent later, or will you then tell me
it's not worth the git blame fuzz? :)


> Reviewed-by: Markus Armbruster <armbru@redhat.com>
>
>

[-- Attachment #2: Type: text/html, Size: 7452 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 07/21] docs/qapidoc: fix nested parsing under untagged sections
  2024-06-28 15:10     ` John Snow
  2024-06-28 15:28       ` John Snow
@ 2024-07-01  9:11       ` Markus Armbruster
  1 sibling, 0 replies; 44+ messages in thread
From: Markus Armbruster @ 2024-07-01  9:11 UTC (permalink / raw)
  To: John Snow
  Cc: Markus Armbruster, qemu-devel, Mads Ynddal, Jiri Pirko,
	Stefan Hajnoczi, Eric Blake, Peter Maydell, Michael Roth,
	Michael S. Tsirkin, Alex Williamson, Pavel Dovgalyuk,
	Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, Qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Philippe Mathieu-Daudé, Lukas Straub, Igor Mammedov,
	Jason Wang, Yanan Wang, Hanna Reitz, Konstantin Kostiuk

John Snow <jsnow@redhat.com> writes:

> On Fri, Jun 28, 2024, 3:55 AM Markus Armbruster <armbru@redhat.com> wrote:
>
>> John Snow <jsnow@redhat.com> writes:
>>
>> > Sphinx does not like sections without titles, because it wants to
>> > convert every section into a reference. When there is no title, it
>> > struggles to do this and transforms the tree inproperly.
>> >
>> > Depending on the rST used, this may result in an assertion error deep in
>> > the docutils HTMLWriter.
>> >
>> > (Observed when using ".. admonition:: Notes" under such a section - When
>> > this is transformed with its own <title> element, Sphinx is fooled into
>> > believing this title belongs to the section and incorrect mutates the
>> > docutils tree, leading to errors during rendering time.)
>> >
>> > When parsing an untagged section (free paragraphs), skip making a hollow
>> > section and instead append the parse results to the prior section.
>> >
>> > Many Bothans died to bring us this information.
>> >
>> > Signed-off-by: John Snow <jsnow@redhat.com>
>> > Acked-by: Markus Armbruster <armbru@redhat.com>
>>
>> Generated HTML changes, but the diff is hard to review due to id
>> attribute changes all over the place.
>>
>> Generated qemu-ga-ref.7 also changes:
>>
>>     diff -rup old/qemu-ga-ref.7 new/qemu-ga-ref.7
>>     --- old/qemu-ga-ref.7       2024-06-27 10:42:21.466096276 +0200
>>     +++ new/qemu-ga-ref.7       2024-06-27 10:45:36.502414099 +0200
>>     @@ -397,6 +397,7 @@ shutdown request, with no guarantee of s
>>      .B \fBmode\fP: \fBstring\fP (optional)
>>      \(dqhalt\(dq, \(dqpowerdown\(dq (default), or \(dqreboot\(dq
>>      .UNINDENT
>>     +.sp
>>      This command does NOT return a response on success.  Success
>>      condition is indicated by the VM exiting with a zero exit status or,
>>      when running with \-\-no\-shutdown, by issuing the query\-status QMP
>>     @@ -1348,6 +1349,7 @@ the new password entry string, base64 en
>>      .B \fBcrypted\fP: \fBboolean\fP
>>      true if password is already crypt()d, false if raw
>>      .UNINDENT
>>     +.sp
>>      If the \fBcrypted\fP flag is true, it is the caller\(aqs
>> responsibility to
>>      ensure the correct crypt() encryption scheme is used.  This command
>>      does not attempt to interpret or report on the encryption scheme.
>>
>> We add vertical space.  Visible when viewed with man.  Looks like an
>> improvement to me.
>>
>> Here's the first of these two spots in HTML:

[...]

>> The id changes muddy the waters.  With them manually removed:

[...]

>> Makes no visual difference in my browser.
>>
>> Do these differences match your expectations?
>>
>
> Yep!
>
> It does change the output just a little, but Sphinx really doesn't like
> title-less sections.
>
> I thought the change looked fine, and I'm still planning on removing this
> old generator anyway, so...

I'll add to the commit message

    The resulting output changes are basically invisible.

Thanks!



^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 10/21] qapi: convert "Note" sections to plain rST
  2024-06-26 22:21 ` [PATCH v2 10/21] qapi: convert "Note" sections to plain rST John Snow
  2024-06-28  9:51   ` Markus Armbruster
@ 2024-07-01 15:08   ` Markus Armbruster
  1 sibling, 0 replies; 44+ messages in thread
From: Markus Armbruster @ 2024-07-01 15:08 UTC (permalink / raw)
  To: John Snow
  Cc: qemu-devel, Mads Ynddal, Jiri Pirko, Stefan Hajnoczi, Eric Blake,
	Peter Maydell, Michael Roth, Michael S. Tsirkin, Alex Williamson,
	Pavel Dovgalyuk, Victor Toso de Carvalho, Cédric Le Goater,
	Daniel P. Berrangé, qemu-block, Ani Sinha, Fabiano Rosas,
	Marcel Apfelbaum, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Kevin Wolf, Peter Xu, Eduardo Habkost,
	Philippe Mathieu-Daudé, Lukas Straub, Igor Mammedov,
	Jason Wang, Yanan Wang, Hanna Reitz, Konstantin Kostiuk

John Snow <jsnow@redhat.com> writes:

> We do not need a dedicated section for notes. By eliminating a specially
> parsed section, these notes can be treated as normal rST paragraphs in
> the new QMP reference manual, and can be placed and styled much more
> flexibly.
>
> Convert all existing "Note" and "Notes" sections to pure rST. As part of
> the conversion, capitalize the first letter of each sentence and add
> trailing punctuation where appropriate to ensure notes look sensible and
> consistent in rendered HTML documentation. Markup is also re-aligned to
> the de-facto standard of 3 spaces for directives.
>
> Update docs/devel/qapi-code-gen.rst to reflect the new paradigm, and
> update the QAPI parser to prohibit "Note" sections while suggesting a
> new syntax. The exact formatting to use is a matter of taste, but a good
> candidate is simply:
>
> .. note:: lorem ipsum ...
>    ... dolor sit amet ...
>    ... consectetur adipiscing elit ...
>
> ... but there are other choices, too. The Sphinx readthedocs theme
> offers theming for the following forms (capitalization unimportant); all
> are adorned with a (!) symbol () in the title bar for rendered HTML
> docs.
>
> See
> https://sphinx-rtd-theme.readthedocs.io/en/stable/demo/demo.html#admonitions
> for examples of each directive/admonition in use.
>
> These are rendered in orange:
>
> .. Attention:: ...
> .. Caution:: ...
> .. WARNING:: ...
>
> These are rendered in red:
>
> .. DANGER:: ...
> .. Error:: ...
>
> These are rendered in green:
>
> .. Hint:: ...
> .. Important:: ...
> .. Tip:: ...
>
> These are rendered in blue:
>
> .. Note:: ...
> .. admonition:: custom title
>
>    admonition body text
>
> This patch uses ".. note::" almost everywhere, with just two "caution"
> directives. Several instances of "Notes:" have been converted to merely
> ".. note::" where appropriate, but ".. admonition:: notes" is used in a
> few places where we had an ordered list of multiple notes that would not
> make sense as standalone/separate admonitions.
>
> NOTE: Because qapidoc.py does not attempt to preserve source ordering of
> sections, the conversion of Notes from a "tagged section" to an
> "untagged section" means that rendering order for some notes *may
> change* as a result of this patch. The forthcoming qapidoc.py rewrite
> strictly preserves source ordering in the rendered documentation, so
> this issue will be rectified in the new generator.
>
> Signed-off-by: John Snow <jsnow@redhat.com>
> Acked-by: Stefan Hajnoczi <stefanha@redhat.com> [for block*.json]

[...]

> diff --git a/qapi/migration.json b/qapi/migration.json
> index 9ec9ef36c47..26ad5e5e7a3 100644
> --- a/qapi/migration.json
> +++ b/qapi/migration.json
> @@ -1456,8 +1456,8 @@
>  #
>  # Cancel the current executing migration process.
>  #
> -# Notes: This command succeeds even if there is no migration process
> -#     running.
> +# .. note:: This command succeeds even if there is no migration process
> +#    running.
>  #
>  # Since: 0.14
>  #
> @@ -1589,16 +1589,16 @@
>  #
>  # Since: 0.14
>  #
> -# Notes:
> +# .. admonition:: Notes
>  #
>  #     1. The 'query-migrate' command should be used to check
>  #        migration's progress and final result (this information is
>  #        provided by the 'status' member)

Missing period, will touch up in my tree.

>  #
> -#     2. All boolean arguments default to false
> +#     2. All boolean arguments default to false.
>  #
>  #     3. The user Monitor's "detach" argument is invalid in QMP and
> -#        should not be used
> +#        should not be used.
>  #
>  #     4. The uri argument should have the Uniform Resource Identifier
>  #        of default destination VM. This connection will be bound to
> @@ -1672,7 +1672,7 @@
>  #
>  # Since: 2.3
>  #
> -# Notes:
> +# .. admonition:: Notes
>  #
>  #     1. It's a bad idea to use a string for the uri, but it needs to
>  #        stay compatible with -incoming and the format of the uri is

[...]



^ permalink raw reply	[flat|nested] 44+ messages in thread

end of thread, other threads:[~2024-07-01 15:09 UTC | newest]

Thread overview: 44+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-06-26 22:21 [PATCH v2 00/21] qapi: convert "Note" and "Example" sections to rST John Snow
2024-06-26 22:21 ` [PATCH v2 01/21] [DO-NOT-MERGE]: Add some ad-hoc linting helpers John Snow
2024-06-26 22:21 ` [PATCH v2 02/21] qapi: linter fixups John Snow
2024-06-26 22:21 ` [PATCH v2 03/21] docs/qapidoc: remove unused intersperse function John Snow
2024-06-27  6:02   ` Markus Armbruster
2024-06-27  6:12     ` John Snow
2024-06-27 10:46     ` Markus Armbruster
2024-06-27 10:43   ` Markus Armbruster
2024-06-26 22:21 ` [PATCH v2 04/21] docs/qapidoc: delint a tiny portion of the module John Snow
2024-06-28  7:29   ` Markus Armbruster
2024-06-28 14:36     ` John Snow
2024-06-26 22:21 ` [PATCH v2 05/21] qapi/parser: preserve indentation in QAPIDoc sections John Snow
2024-06-27  6:25   ` Markus Armbruster
2024-06-27  6:35     ` John Snow
2024-06-27 10:46     ` Markus Armbruster
2024-06-27 10:43   ` Markus Armbruster
2024-06-26 22:21 ` [PATCH v2 06/21] qapi/parser: fix comment parsing immediately following a doc block John Snow
2024-06-26 22:21 ` [PATCH v2 07/21] docs/qapidoc: fix nested parsing under untagged sections John Snow
2024-06-28  7:54   ` Markus Armbruster
2024-06-28 15:10     ` John Snow
2024-06-28 15:28       ` John Snow
2024-07-01  9:11       ` Markus Armbruster
2024-06-26 22:21 ` [PATCH v2 08/21] qapi: fix non-compliant JSON examples John Snow
2024-06-26 22:21 ` [PATCH v2 09/21] qapi: nail down convention that Errors sections are lists John Snow
2024-06-26 22:21 ` [PATCH v2 10/21] qapi: convert "Note" sections to plain rST John Snow
2024-06-28  9:51   ` Markus Armbruster
2024-06-28 15:44     ` John Snow
2024-07-01 15:08   ` Markus Armbruster
2024-06-26 22:21 ` [PATCH v2 11/21] qapi: update prose in note blocks John Snow
2024-06-26 22:21 ` [PATCH v2 12/21] qapi: add markup to " John Snow
2024-06-26 22:21 ` [PATCH v2 13/21] qapi/parser: don't parse rST markup as section headers John Snow
2024-06-27  7:47   ` Markus Armbruster
2024-06-26 22:21 ` [PATCH v2 14/21] docs/qapidoc: factor out do_parse() John Snow
2024-06-28 13:08   ` Markus Armbruster
2024-06-28 15:16     ` John Snow
2024-06-26 22:21 ` [PATCH v2 15/21] docs/qapidoc: create qmp-example directive John Snow
2024-06-28 13:24   ` Markus Armbruster
2024-06-28 15:24     ` John Snow
2024-06-26 22:21 ` [PATCH v2 16/21] docs/qapidoc: add QMP highlighting to annotated qmp-example blocks John Snow
2024-06-26 22:21 ` [PATCH v2 17/21] docs/sphinx: add CSS styling for qmp-example directive John Snow
2024-06-26 22:21 ` [PATCH v2 18/21] qapi: convert "Example" sections without titles John Snow
2024-06-26 22:21 ` [PATCH v2 19/21] qapi: convert "Example" sections with titles John Snow
2024-06-26 22:21 ` [PATCH v2 20/21] qapi: convert "Example" sections with longer prose John Snow
2024-06-26 22:21 ` [PATCH v2 21/21] qapi: remove "Example" doc section John Snow

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).