* [PATCH 0/8] qapi: enforce section ordering
@ 2026-03-16 18:25 John Snow
2026-03-16 18:26 ` [PATCH 1/8] qapi: differentiate "intro" and "details" sections John Snow
` (7 more replies)
0 siblings, 8 replies; 29+ messages in thread
From: John Snow @ 2026-03-16 18:25 UTC (permalink / raw)
To: qemu-devel
Cc: Pierrick Bouvier, Lukas Straub, Richard Henderson, Zhao Liu,
Jason Wang, Mauro Carvalho Chehab, Alex Bennée, Peter Xu,
Eric Blake, Daniel P. Berrangé, Fabiano Rosas,
Philippe Mathieu-Daudé, Cédric Le Goater, qemu-block,
Marc-André Lureau, Peter Maydell, Michael S. Tsirkin,
Stefan Berger, Alex Williamson, Marcel Apfelbaum, Kevin Wolf,
John Snow, Michael Roth, Stefano Garzarella, Stefan Hajnoczi,
Igor Mammedov, Jiri Pirko, Yanan Wang, Paolo Bonzini,
Kashyap Chamarthy, Markus Armbruster, Hanna Reitz, Ani Sinha
This is RFC quality and mostly meant for Markus to review, but if you're
curious about what we're up to, you're welcome to nose around :)
It's a hackish application of enforcing a strict source section ordering
in QAPIDoc and the accompanying patches that mend the source to respect
that order. The point of the series is to, ultimately, make it easier to
"inject" auto-generated documentation by enforcing a specific order to
sections so that it is easier to insert documentation that is missing or
can be implied from the source. A secondary goal is to more closely
align the source documentation ordering with what gets rendered on the
HTML documentation.
I am sending it to the list in this RFC state mostly to illustrate what
each specific imposition requires in terms of source doc changes, and as
a refresher for the specific restrictions I want to make to facilitate
the inliner feature.
I am not neccessarily married to any specific technique/implementation
for each specific restriction, but if it looks broadly OK to you
(Markus), I can work on any requested polish or corollary cleanups. If
you'd like to see a different approach, that's fine too. We may wish to
discuss the ability to add notes/addendums to sections and what syntax
would support that.
I had originally thought I'd work on the @oob project, but quickly
remembered that my approach to that feature required yet-another place
where we inject a doc section, and decided it would be best if I solved
"where do we inject this autogenerated section?" once and for all,
hence, you are getting this series first.
John Snow (8):
qapi: differentiate "intro" and "details" sections
qapi: prohibit 'details' sections between tagged sections
qapi: add "Details:" disambiguation marker
qapi: detect potentially semantically ambiguous intro paragraphs
qapi: re-order QAPI doc block sections
qapi: enforce doc block section ordering
qapi: re-order 'since' sections to always be last
qapi: enforce strict positioning for "Since:" section
docs/interop/firmware.json | 4 +-
docs/interop/vhost-user.json | 3 +-
docs/sphinx/qapidoc.py | 2 +-
qapi/accelerator.json | 12 +--
qapi/acpi.json | 8 +-
qapi/block-core.json | 183 ++++++++++++++++----------------
qapi/block-export.json | 20 ++--
qapi/block.json | 48 ++++-----
qapi/char.json | 36 +++----
qapi/control.json | 14 +--
qapi/dump.json | 16 +--
qapi/machine-s390x.json | 16 +--
qapi/machine.json | 144 +++++++++++++------------
qapi/migration.json | 102 ++++++++++--------
qapi/misc-arm.json | 6 +-
qapi/misc-i386.json | 40 ++++---
qapi/misc.json | 68 ++++++------
qapi/net.json | 42 ++++----
qapi/pci.json | 4 +-
qapi/qdev.json | 12 +--
qapi/qom.json | 34 +++---
qapi/replay.json | 16 +--
qapi/rocker.json | 16 +--
qapi/run-state.json | 66 +++++++-----
qapi/tpm.json | 12 +--
qapi/trace.json | 8 +-
qapi/transaction.json | 4 +-
qapi/ui.json | 76 +++++++------
qapi/vfio.json | 4 +-
qapi/virtio.json | 46 ++++----
qapi/yank.json | 2 +-
scripts/qapi/parser.py | 121 ++++++++++++++++++---
tests/qapi-schema/doc-good.json | 12 +--
tests/qapi-schema/doc-good.out | 10 +-
tests/qapi-schema/doc-good.txt | 18 ++--
35 files changed, 695 insertions(+), 530 deletions(-)
--
2.53.0
^ permalink raw reply [flat|nested] 29+ messages in thread* [PATCH 1/8] qapi: differentiate "intro" and "details" sections 2026-03-16 18:25 [PATCH 0/8] qapi: enforce section ordering John Snow @ 2026-03-16 18:26 ` John Snow 2026-03-20 12:24 ` Markus Armbruster 2026-03-16 18:26 ` [PATCH 2/8] qapi: prohibit 'details' sections between tagged sections John Snow ` (6 subsequent siblings) 7 siblings, 1 reply; 29+ messages in thread From: John Snow @ 2026-03-16 18:26 UTC (permalink / raw) To: qemu-devel Cc: Pierrick Bouvier, Lukas Straub, Richard Henderson, Zhao Liu, Jason Wang, Mauro Carvalho Chehab, Alex Bennée, Peter Xu, Eric Blake, Daniel P. Berrangé, Fabiano Rosas, Philippe Mathieu-Daudé, Cédric Le Goater, qemu-block, Marc-André Lureau, Peter Maydell, Michael S. Tsirkin, Stefan Berger, Alex Williamson, Marcel Apfelbaum, Kevin Wolf, John Snow, Michael Roth, Stefano Garzarella, Stefan Hajnoczi, Igor Mammedov, Jiri Pirko, Yanan Wang, Paolo Bonzini, Kashyap Chamarthy, Markus Armbruster, Hanna Reitz, Ani Sinha This patch begins distinguishing "Plain" sections as being either "Intro" or "Details" sections for the purpose of knowing when/where/how to inline those sections. The Intro section is always the first section of any doc block. It may be empty or any number of paragraphs. It is interrupted by any other non-plaintext section, i.e.; Members, Features, Errors, Returns, Since, and TODO. The details section, when present, is either the last section or the second-to-last section when a "Since:" section is present. It consists of any plain text in the doc block that follows any named sections if present. Signed-off-by: John Snow <jsnow@redhat.com> --- docs/sphinx/qapidoc.py | 2 +- scripts/qapi/parser.py | 35 +++++++++++++++++++++++----------- tests/qapi-schema/doc-good.out | 8 ++++---- 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py index c2f09bac16c..e359836f110 100644 --- a/docs/sphinx/qapidoc.py +++ b/docs/sphinx/qapidoc.py @@ -368,7 +368,7 @@ def visit_sections(self, ent: QAPISchemaDefinition) -> None: for i, section in enumerate(sections): section.text = self.reformat_arobase(section.text) - if section.kind == QAPIDoc.Kind.PLAIN: + if section.kind.name in ("INTRO", "DETAILS"): self.visit_paragraph(section) elif section.kind == QAPIDoc.Kind.MEMBER: assert isinstance(section, QAPIDoc.ArgSection) diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py index c3cf33904ef..da0ac32ad89 100644 --- a/scripts/qapi/parser.py +++ b/scripts/qapi/parser.py @@ -544,7 +544,7 @@ def get_doc(self) -> 'QAPIDoc': doc = QAPIDoc(info, symbol) self.accept(False) line = self.get_doc_line() - no_more_args = False + have_tagged = False while line is not None: # Blank lines @@ -573,10 +573,10 @@ def get_doc(self) -> 'QAPIDoc': if not doc.features: raise QAPIParseError( self, 'feature descriptions expected') - no_more_args = True + have_tagged = True elif match := self._match_at_name_colon(line): # description - if no_more_args: + if have_tagged: raise QAPIParseError( self, "description of '@%s:' follows a section" @@ -588,7 +588,7 @@ def get_doc(self) -> 'QAPIDoc': if text: doc.append_line(text) line = self.get_doc_indented(doc) - no_more_args = True + have_tagged = True elif match := re.match( r'(Returns|Errors|Since|Notes?|Examples?|TODO)' r'(?!::): *', @@ -629,10 +629,14 @@ def get_doc(self) -> 'QAPIDoc': if text: doc.append_line(text) line = self.get_doc_indented(doc) - no_more_args = True + have_tagged = True else: # plain paragraph - doc.ensure_untagged_section(self.info) + + # Paragraphs before tagged sections are "intro" paragraphs. + # Any appearing after are "detail" paragraphs. + intro = not have_tagged + doc.ensure_untagged_section(self.info, intro) doc.append_line(line) line = self.get_doc_paragraph(doc) else: @@ -674,13 +678,14 @@ class QAPIDoc: """ class Kind(enum.Enum): - PLAIN = 0 + INTRO = 0 MEMBER = 1 FEATURE = 2 RETURNS = 3 ERRORS = 4 SINCE = 5 TODO = 6 + DETAILS = 7 @staticmethod def from_string(kind: str) -> 'QAPIDoc.Kind': @@ -730,7 +735,7 @@ def __init__(self, info: QAPISourceInfo, symbol: Optional[str] = None): self.symbol: Optional[str] = symbol # the sections in textual order self.all_sections: List[QAPIDoc.Section] = [ - QAPIDoc.Section(info, QAPIDoc.Kind.PLAIN) + QAPIDoc.Section(info, QAPIDoc.Kind.INTRO) ] # the body section self.body: Optional[QAPIDoc.Section] = self.all_sections[0] @@ -748,12 +753,20 @@ def __init__(self, info: QAPISourceInfo, symbol: Optional[str] = None): def end(self) -> None: for section in self.all_sections: section.text = section.text.strip('\n') - if section.kind != QAPIDoc.Kind.PLAIN and section.text == '': + if ( + section.kind not in ( + QAPIDoc.Kind.INTRO, QAPIDoc.Kind.DETAILS + ) and section.text == '' + ): raise QAPISemError( section.info, "text required after '%s:'" % section.kind) - def ensure_untagged_section(self, info: QAPISourceInfo) -> None: - kind = QAPIDoc.Kind.PLAIN + def ensure_untagged_section( + self, + info: QAPISourceInfo, + intro: bool = True, + ) -> None: + kind = QAPIDoc.Kind.INTRO if intro else QAPIDoc.Kind.DETAILS if self.all_sections and self.all_sections[-1].kind == kind: # extend current section diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out index 04a55072646..04e29e8d50f 100644 --- a/tests/qapi-schema/doc-good.out +++ b/tests/qapi-schema/doc-good.out @@ -116,7 +116,7 @@ The _one_ {and only}, description on the same line Also _one_ {and only} feature=enum-member-feat a member feature - section=Plain + section=Details @two is undocumented doc symbol=Base body= @@ -175,7 +175,7 @@ description starts on the same line a feature feature=cmd-feat2 another feature - section=Plain + section=Details .. note:: @arg3 is undocumented section=Returns @Object @@ -183,7 +183,7 @@ another feature some section=Todo frobnicate - section=Plain + section=Details .. admonition:: Notes - Lorem ipsum dolor sit amet @@ -216,7 +216,7 @@ If you're bored enough to read this, go see a video of boxed cats a feature feature=cmd-feat2 another feature - section=Plain + section=Details .. qmp-example:: -> "this example" -- 2.53.0 ^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [PATCH 1/8] qapi: differentiate "intro" and "details" sections 2026-03-16 18:26 ` [PATCH 1/8] qapi: differentiate "intro" and "details" sections John Snow @ 2026-03-20 12:24 ` Markus Armbruster 2026-03-20 17:20 ` John Snow 0 siblings, 1 reply; 29+ messages in thread From: Markus Armbruster @ 2026-03-20 12:24 UTC (permalink / raw) To: John Snow Cc: qemu-devel, Pierrick Bouvier, Lukas Straub, Richard Henderson, Zhao Liu, Jason Wang, Mauro Carvalho Chehab, Alex Bennée, Peter Xu, Eric Blake, Daniel P. Berrangé, Fabiano Rosas, Philippe Mathieu-Daudé, Cédric Le Goater, qemu-block, Marc-André Lureau, Peter Maydell, Michael S. Tsirkin, Stefan Berger, Alex Williamson, Marcel Apfelbaum, Kevin Wolf, Michael Roth, Stefano Garzarella, Stefan Hajnoczi, Igor Mammedov, Jiri Pirko, Yanan Wang, Paolo Bonzini, Kashyap Chamarthy, Hanna Reitz, Ani Sinha John Snow <jsnow@redhat.com> writes: > This patch begins distinguishing "Plain" sections as being either > "Intro" or "Details" sections for the purpose of knowing when/where/how > to inline those sections. > > The Intro section is always the first section of any doc block. It may > be empty or any number of paragraphs. It is interrupted by any other > non-plaintext section, i.e.; Members, Features, Errors, Returns, Since, > and TODO. > > The details section, when present, is either the last section or the > second-to-last section when a "Since:" section is present. It consists > of any plain text in the doc block that follows any named sections if > present. > > Signed-off-by: John Snow <jsnow@redhat.com> The commit message explains what kinds INTRO and DETAILS are, but not why they're useful. My guess: 1. Represent the future "Details:" marker: the plain section before it is of kind INTRO, the one afterwards is of kind DETAILS. 2. Future programming convenience? With just PLAIN, code may have to understand the section's context to make decisions, and with INTRO and DETAILS is doesn't. Guess close enough? The commit message covers PLAIN sections at the beginning and at the end (modulo Since:). It doesn't cover PLAIN sections between tagged sections / member descriptions. You disallow these in PATCH 2. You can either cover them here, or get rid of them by swapping PATCH 1 and 2. Hmm, is your description of DETAILS accurate? Looks like it isn't; see my review of tests/qapi-schema/doc-good.out below. > --- > docs/sphinx/qapidoc.py | 2 +- > scripts/qapi/parser.py | 35 +++++++++++++++++++++++----------- > tests/qapi-schema/doc-good.out | 8 ++++---- > 3 files changed, 29 insertions(+), 16 deletions(-) [Skipping the Python code in my first pass...] > diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out > index 04a55072646..04e29e8d50f 100644 > --- a/tests/qapi-schema/doc-good.out > +++ b/tests/qapi-schema/doc-good.out > @@ -116,7 +116,7 @@ The _one_ {and only}, description on the same line > Also _one_ {and only} > feature=enum-member-feat > a member feature > - section=Plain > + section=Details > @two is undocumented The section containing "@two is undocumented" changes from PLAIN to DETAILS. Doc source: ## # @Enum: # # @one: The _one_ {and only}, description on the same line # # Features: # @enum-feat: Also _one_ {and only} # @enum-member-feat: a member feature # # @two is undocumented ## It is at the end. Good. > doc symbol=Base > body= > @@ -175,7 +175,7 @@ description starts on the same line > a feature > feature=cmd-feat2 > another feature > - section=Plain > + section=Details > .. note:: @arg3 is undocumented The section containing "@arg3 is undocumented" changes from PLAIN to DETAILS. Doc source: Doc source: ## # @cmd: # # @arg1: # description starts on a new line, # indented # # @arg2: description starts on the same line # remainder indented differently # # Returns: @Object # # Errors: some # # Features: # @cmd-feat1: a feature # @cmd-feat2: another feature # # .. note:: @arg3 is undocumented # # TODO: frobnicate # It is *not* at the end. Is the commit message inaccurate? > section=Returns > @Object > @@ -183,7 +183,7 @@ another feature > some > section=Todo > frobnicate > - section=Plain > + section=Details > .. admonition:: Notes > > - Lorem ipsum dolor sit amet - Ut enim ad minim veniam [some section body text elided for brevity...] Note:: Ceci n'est pas une note section=Since 2.10 The section starting with the adminition and ending after "Ceci n'est pas une note" changes from PLAIN to DETAILS. Doc source continued: # .. admonition:: Notes # # - Lorem ipsum dolor sit amet # - Ut enim ad minim veniam # [same text elided...] # # Note:: # Ceci n'est pas une note # # Since: 2.10 ## It is second-to-last, and the last section is SINCE. Good. > @@ -216,7 +216,7 @@ If you're bored enough to read this, go see a video of boxed cats > a feature > featurec=md-feat2 > another feature > - section=Plain > + section=Details > .. qmp-example:: > > -> "this example" This one is also at the end. Good. ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 1/8] qapi: differentiate "intro" and "details" sections 2026-03-20 12:24 ` Markus Armbruster @ 2026-03-20 17:20 ` John Snow 2026-03-23 8:15 ` Markus Armbruster 0 siblings, 1 reply; 29+ messages in thread From: John Snow @ 2026-03-20 17:20 UTC (permalink / raw) To: Markus Armbruster Cc: qemu-devel, Pierrick Bouvier, Lukas Straub, Richard Henderson, Zhao Liu, Jason Wang, Mauro Carvalho Chehab, Alex Bennée, Peter Xu, Eric Blake, Daniel P. Berrangé, Fabiano Rosas, Philippe Mathieu-Daudé, Cédric Le Goater, Qemu-block, Marc-André Lureau, Peter Maydell, Michael S. Tsirkin, Stefan Berger, Alex Williamson, Marcel Apfelbaum, Kevin Wolf, Michael Roth, Stefano Garzarella, Stefan Hajnoczi, Igor Mammedov, Jiri Pirko, Yanan Wang, Paolo Bonzini, Kashyap Chamarthy, Hanna Reitz, Ani Sinha [-- Attachment #1: Type: text/plain, Size: 6791 bytes --] On Fri, Mar 20, 2026, 8:24 AM Markus Armbruster <armbru@redhat.com> wrote: > John Snow <jsnow@redhat.com> writes: > > > This patch begins distinguishing "Plain" sections as being either > > "Intro" or "Details" sections for the purpose of knowing when/where/how > > to inline those sections. > > > > The Intro section is always the first section of any doc block. It may > > be empty or any number of paragraphs. It is interrupted by any other > > non-plaintext section, i.e.; Members, Features, Errors, Returns, Since, > > and TODO. > > > > The details section, when present, is either the last section or the > > second-to-last section when a "Since:" section is present. It consists > > of any plain text in the doc block that follows any named sections if > > present. > > > > Signed-off-by: John Snow <jsnow@redhat.com> > > The commit message explains what kinds INTRO and DETAILS are, but not > why they're useful. My guess: > Right, my apologies. Leaning on you having some existing knowledge here, and also going light on details because the series is still obviously in flux. Let me elaborate on the motivations here... > 1. Represent the future "Details:" marker: the plain section before it > is of kind INTRO, the one afterwards is of kind DETAILS. > Yes. > 2. Future programming convenience? With just PLAIN, code may have to > understand the section's context to make decisions, and with INTRO and > DETAILS is doesn't. > > Guess close enough? > Pretty much. Originally, I thought I'd inline things like this: Intro (child) Intro (parent) ...other sections... Details (parent) Details (child) Last time we went over this, you mused that there was likely never a sufficient reason to actually inline the intro. I recall believing and accepting this. So functionally what this does for us is: (1) Explicitly delineate what comes before the tabular section of the docs (members, Returns, Errors, features) and what comes after. (2) Explicitly defines what will not be inlined. > The commit message covers PLAIN sections at the beginning and at the end > (modulo Since:). It doesn't cover PLAIN sections between tagged > sections / member descriptions. You disallow these in PATCH 2. You can > either cover them here, or get rid of them by swapping PATCH 1 and 2. > Sure. For now they're separated just to separate concerns in review, but if you believe both should be all-at-once, that's fine too. I think there's not a regression by separating it, though. It's just a semantic change from details meaning "anything after the intro" to "specifically the closing section". The intermediate meaning exists for only one patch. > Hmm, is your description of DETAILS accurate? Looks like it isn't; see > my review of tests/qapi-schema/doc-good.out below. > Whoops, future-think. It winds up being true, but isn't true yet as of this commit. Well, almost. See below. > > --- > > docs/sphinx/qapidoc.py | 2 +- > > scripts/qapi/parser.py | 35 +++++++++++++++++++++++----------- > > tests/qapi-schema/doc-good.out | 8 ++++---- > > 3 files changed, 29 insertions(+), 16 deletions(-) > > [Skipping the Python code in my first pass...] > > > diff --git a/tests/qapi-schema/doc-good.out > b/tests/qapi-schema/doc-good.out > > index 04a55072646..04e29e8d50f 100644 > > --- a/tests/qapi-schema/doc-good.out > > +++ b/tests/qapi-schema/doc-good.out > > @@ -116,7 +116,7 @@ The _one_ {and only}, description on the same line > > Also _one_ {and only} > > feature=enum-member-feat > > a member feature > > - section=Plain > > + section=Details > > @two is undocumented > > The section containing "@two is undocumented" changes from PLAIN to > DETAILS. Doc source: > > ## > # @Enum: > # > # @one: The _one_ {and only}, description on the same line > # > # Features: > # @enum-feat: Also _one_ {and only} > # @enum-member-feat: a member feature > # > # @two is undocumented > ## > > It is at the end. Good. > > > doc symbol=Base > > body= > > @@ -175,7 +175,7 @@ description starts on the same line > > a feature > > feature=cmd-feat2 > > another feature > > - section=Plain > > + section=Details > > .. note:: @arg3 is undocumented > > The section containing "@arg3 is undocumented" changes from PLAIN to > DETAILS. Doc source: > > Doc source: > > ## > # @cmd: > # > # @arg1: > # description starts on a new line, > # indented > # > # @arg2: description starts on the same line > # remainder indented differently > # > # Returns: @Object > # > # Errors: some > # > # Features: > # @cmd-feat1: a feature > # @cmd-feat2: another feature > # > # .. note:: @arg3 is undocumented > # > # TODO: frobnicate > # > > It is *not* at the end. Is the commit message inaccurate? > Ah. I wasn't considering TODO... Since it is a comment I mentally elided it. What I mean to say is that Details is (will be) essentially the last content section that is actually rendered. In the HTML, it will always be last if present because both TODO and Since are actually entirely removed from the flow of the document. Though as we both point out, what i write is not technically true here. (It can currently be an intermediate section AND Since is not the only section that may follow it.) > > section=Returns > > @Object > > @@ -183,7 +183,7 @@ another feature > > some > > section=Todo > > frobnicate > > - section=Plain > > + section=Details > > .. admonition:: Notes > > > > - Lorem ipsum dolor sit amet > - Ut enim ad minim veniam > > [some section body text elided for brevity...] > > Note:: > Ceci n'est pas une note > section=Since > 2.10 > > The section starting with the adminition and ending after "Ceci n'est > pas une note" changes from PLAIN to DETAILS. Doc source continued: > > # .. admonition:: Notes > # > # - Lorem ipsum dolor sit amet > # - Ut enim ad minim veniam > # > [same text elided...] > # > # Note:: > # Ceci n'est pas une note > # > # Since: 2.10 > ## > > It is second-to-last, and the last section is SINCE. Good. > > > @@ -216,7 +216,7 @@ If you're bored enough to read this, go see a video > of boxed cats > > a feature > > featurec=md-feat2 > > another feature > > - section=Plain > > + section=Details > > .. qmp-example:: > > > > -> "this example" > > This one is also at the end. Good. > > [-- Attachment #2: Type: text/html, Size: 10222 bytes --] ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 1/8] qapi: differentiate "intro" and "details" sections 2026-03-20 17:20 ` John Snow @ 2026-03-23 8:15 ` Markus Armbruster 0 siblings, 0 replies; 29+ messages in thread From: Markus Armbruster @ 2026-03-23 8:15 UTC (permalink / raw) To: John Snow Cc: qemu-devel, Pierrick Bouvier, Lukas Straub, Richard Henderson, Zhao Liu, Jason Wang, Mauro Carvalho Chehab, Alex Bennée, Peter Xu, Eric Blake, Daniel P. Berrangé, Fabiano Rosas, Philippe Mathieu-Daudé, Cédric Le Goater, Qemu-block, Marc-André Lureau, Peter Maydell, Michael S. Tsirkin, Stefan Berger, Alex Williamson, Marcel Apfelbaum, Kevin Wolf, Michael Roth, Stefano Garzarella, Stefan Hajnoczi, Igor Mammedov, Jiri Pirko, Yanan Wang, Paolo Bonzini, Kashyap Chamarthy, Hanna Reitz, Ani Sinha John Snow <jsnow@redhat.com> writes: > On Fri, Mar 20, 2026, 8:24 AM Markus Armbruster <armbru@redhat.com> wrote: > >> John Snow <jsnow@redhat.com> writes: >> >> > This patch begins distinguishing "Plain" sections as being either >> > "Intro" or "Details" sections for the purpose of knowing when/where/how >> > to inline those sections. >> > >> > The Intro section is always the first section of any doc block. It may >> > be empty or any number of paragraphs. It is interrupted by any other >> > non-plaintext section, i.e.; Members, Features, Errors, Returns, Since, >> > and TODO. >> > >> > The details section, when present, is either the last section or the >> > second-to-last section when a "Since:" section is present. It consists >> > of any plain text in the doc block that follows any named sections if >> > present. >> > >> > Signed-off-by: John Snow <jsnow@redhat.com> >> >> The commit message explains what kinds INTRO and DETAILS are, but not >> why they're useful. My guess: >> > > Right, my apologies. Leaning on you having some existing knowledge here, > and also going light on details because the series is still obviously in > flux. No worries! > Let me elaborate on the motivations here... > > >> 1. Represent the future "Details:" marker: the plain section before it >> is of kind INTRO, the one afterwards is of kind DETAILS. >> > > Yes. > > >> 2. Future programming convenience? With just PLAIN, code may have to >> understand the section's context to make decisions, and with INTRO and >> DETAILS is doesn't. >> >> Guess close enough? >> > > Pretty much. > > Originally, I thought I'd inline things like this: > > Intro (child) > Intro (parent) > ...other sections... > Details (parent) > Details (child) > > Last time we went over this, you mused that there was likely never a > sufficient reason to actually inline the intro. I recall believing and > accepting this. Turns out we use the first section (i.e. INTRO) for describing the thing being defined. Inlining such descriptions results in nonsense. For instance, here's SevGuestProperties and its base SevGuestProperties: ## # @SevCommonProperties: # # Properties common to objects that are derivatives of sev-common. # [...] ## # @SevGuestProperties: # # Properties for sev-guest objects. # # @dh-cert-file: guest owners DH certificate (encoded with base64) # [...] Inlining the base as you originally thought would result in something like Object SevGuestProperties (Since: 2.12) Properties for sev-guest objects. Properties common to objects that are derivatives of sev-common. Members: * dh-cert-file (string, optional) -- guest owners DH certificate (encoded with base64) The intro paragraph inlined from the base is nonsense. We either stop writing such descriptions (ugh), or we drop them on inlining. If we drop, code needs to recognize them. The only method I can see is to assume INTRO is description. Now, the QAPI generator cannot stop people from putting stuff in INTRO is *not* description and *should* be inlined. This is a risk we will have to accept to gain the benefits of inlining. For the inliner's initial merge, we'll want to review all the INTRO sections the inliner drops. If almost all of them are fine, the risk is low. > So functionally what this does for us is: > > (1) Explicitly delineate what comes before the tabular section of the docs > (members, Returns, Errors, features) and what comes after. > > (2) Explicitly defines what will not be inlined. Yes. I think we'll want to at least hint at this in the final commit message. The full story would be too much, I guess. >> The commit message covers PLAIN sections at the beginning and at the end >> (modulo Since:). It doesn't cover PLAIN sections between tagged >> sections / member descriptions. You disallow these in PATCH 2. You can >> either cover them here, or get rid of them by swapping PATCH 1 and 2. >> > > Sure. For now they're separated just to separate concerns in review, but if > you believe both should be all-at-once, that's fine too. I think there's > not a regression by separating it, though. It's just a semantic change from > details meaning "anything after the intro" to "specifically the closing > section". The intermediate meaning exists for only one patch. Have you tried swapping the patches? If that's bothersome, squashing them together may well do. >> Hmm, is your description of DETAILS accurate? Looks like it isn't; see >> my review of tests/qapi-schema/doc-good.out below. >> > > Whoops, future-think. It winds up being true, but isn't true yet as of this > commit. Well, almost. See below. > > >> > --- >> > docs/sphinx/qapidoc.py | 2 +- >> > scripts/qapi/parser.py | 35 +++++++++++++++++++++++----------- >> > tests/qapi-schema/doc-good.out | 8 ++++---- >> > 3 files changed, 29 insertions(+), 16 deletions(-) >> >> [Skipping the Python code in my first pass...] >> >> > diff --git a/tests/qapi-schema/doc-good.out >> b/tests/qapi-schema/doc-good.out >> > index 04a55072646..04e29e8d50f 100644 >> > --- a/tests/qapi-schema/doc-good.out >> > +++ b/tests/qapi-schema/doc-good.out >> > @@ -116,7 +116,7 @@ The _one_ {and only}, description on the same line >> > Also _one_ {and only} >> > feature=enum-member-feat >> > a member feature >> > - section=Plain >> > + section=Details >> > @two is undocumented >> >> The section containing "@two is undocumented" changes from PLAIN to >> DETAILS. Doc source: >> >> ## >> # @Enum: >> # >> # @one: The _one_ {and only}, description on the same line >> # >> # Features: >> # @enum-feat: Also _one_ {and only} >> # @enum-member-feat: a member feature >> # >> # @two is undocumented >> ## >> >> It is at the end. Good. >> >> > doc symbol=Base >> > body= >> > @@ -175,7 +175,7 @@ description starts on the same line >> > a feature >> > feature=cmd-feat2 >> > another feature >> > - section=Plain >> > + section=Details >> > .. note:: @arg3 is undocumented >> >> The section containing "@arg3 is undocumented" changes from PLAIN to >> DETAILS. Doc source: >> >> Doc source: >> >> ## >> # @cmd: >> # >> # @arg1: >> # description starts on a new line, >> # indented >> # >> # @arg2: description starts on the same line >> # remainder indented differently >> # >> # Returns: @Object >> # >> # Errors: some >> # >> # Features: >> # @cmd-feat1: a feature >> # @cmd-feat2: another feature >> # >> # .. note:: @arg3 is undocumented >> # >> # TODO: frobnicate >> # >> >> It is *not* at the end. Is the commit message inaccurate? >> > > Ah. I wasn't considering TODO... Since it is a comment I mentally elided it. > > What I mean to say is that Details is (will be) essentially the last > content section that is actually rendered. > > In the HTML, it will always be last if present because both TODO and Since > are actually entirely removed from the flow of the document. We can handwave these two away, but the issue persists until the next patch. Consider this change to the test before the series: diff --git a/tests/qapi-schema/doc-good.json b/tests/qapi-schema/doc-good.json index fac13425b7..4d586b043f 100644 --- a/tests/qapi-schema/doc-good.json +++ b/tests/qapi-schema/doc-good.json @@ -169,6 +169,8 @@ # # Returns: @Object # +# plain in the middle +# # Errors: some # # TODO: frobnicate diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out index 04a5507264..040e901474 100644 --- a/tests/qapi-schema/doc-good.out +++ b/tests/qapi-schema/doc-good.out @@ -179,6 +179,8 @@ another feature .. note:: @arg3 is undocumented section=Returns @Object + section=Plain +plain in the middle section=Errors some section=Todo The current patch then acquires another hunk: diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out index 04e29e8d50..28abb1d98e 100644 --- a/tests/qapi-schema/doc-good.out +++ b/tests/qapi-schema/doc-good.out @@ -179,6 +179,8 @@ another feature .. note:: @arg3 is undocumented section=Returns @Object + section=Details +plain in the middle section=Errors some section=Todo > Though as we both point out, what i write is not technically true here. (It > can currently be an intermediate section AND Since is not the only section > that may follow it.) [...] ^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 2/8] qapi: prohibit 'details' sections between tagged sections 2026-03-16 18:25 [PATCH 0/8] qapi: enforce section ordering John Snow 2026-03-16 18:26 ` [PATCH 1/8] qapi: differentiate "intro" and "details" sections John Snow @ 2026-03-16 18:26 ` John Snow 2026-03-20 12:46 ` Markus Armbruster 2026-03-20 13:46 ` Markus Armbruster 2026-03-16 18:26 ` [PATCH 3/8] qapi: add "Details:" disambiguation marker John Snow ` (5 subsequent siblings) 7 siblings, 2 replies; 29+ messages in thread From: John Snow @ 2026-03-16 18:26 UTC (permalink / raw) To: qemu-devel Cc: Pierrick Bouvier, Lukas Straub, Richard Henderson, Zhao Liu, Jason Wang, Mauro Carvalho Chehab, Alex Bennée, Peter Xu, Eric Blake, Daniel P. Berrangé, Fabiano Rosas, Philippe Mathieu-Daudé, Cédric Le Goater, qemu-block, Marc-André Lureau, Peter Maydell, Michael S. Tsirkin, Stefan Berger, Alex Williamson, Marcel Apfelbaum, Kevin Wolf, John Snow, Michael Roth, Stefano Garzarella, Stefan Hajnoczi, Igor Mammedov, Jiri Pirko, Yanan Wang, Paolo Bonzini, Kashyap Chamarthy, Markus Armbruster, Hanna Reitz, Ani Sinha This patch prohibits plain documentation sections from appearing between "tagged" sections. The two existing uses of this pattern are patched out. This is being done primarily to ensure consistency between the source documents and the final, rendered HTML output. Because member/feature/returns/error sections will always appear in a visually grouped element in the HTML output, prohibiting plain paragraphs between those sections ensures ordering consistency between source and the final render. Additionally, prohibiting such "middle" text paragraphs allows us to classify all plain text sections as either "intro" or "details" sections, because these sections must either appear before structured/tagged sections ("intro") or afterwards ("details"). This keeps the inlining algorithm simpler with fewer "splice" points when merging multiple documentation blocks. Signed-off-by: John Snow <jsnow@redhat.com> --- qapi/qom.json | 4 ++-- scripts/qapi/parser.py | 17 +++++++++++++++++ tests/qapi-schema/doc-good.json | 4 ++-- tests/qapi-schema/doc-good.out | 4 ++-- tests/qapi-schema/doc-good.txt | 8 ++++---- 5 files changed, 27 insertions(+), 10 deletions(-) diff --git a/qapi/qom.json b/qapi/qom.json index c653248f85d..1b47abd44e9 100644 --- a/qapi/qom.json +++ b/qapi/qom.json @@ -243,12 +243,12 @@ # # @typename: the type name of an object # +# Returns: a list describing object 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. # -# Returns: a list describing object properties -# # Since: 2.12 ## { 'command': 'qom-list-properties', diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py index da0ac32ad89..dea056df30d 100644 --- a/scripts/qapi/parser.py +++ b/scripts/qapi/parser.py @@ -545,6 +545,19 @@ def get_doc(self) -> 'QAPIDoc': self.accept(False) line = self.get_doc_line() have_tagged = False + no_more_tags = False + + def _tag_check(what: str) -> None: + if what in ('TODO', 'Since'): + return + + if no_more_tags: + raise QAPIParseError( + self, + f"'{what}' section cannot appear after plain " + "paragraphs that follow other tagged sections\n" + "Move this section up above the plain paragraph(s)." + ) while line is not None: # Blank lines @@ -558,6 +571,7 @@ def get_doc(self) -> 'QAPIDoc': if doc.features: raise QAPIParseError( self, "duplicated 'Features:' line") + _tag_check("Features") self.accept(False) line = self.get_doc_line() while line == '': @@ -621,6 +635,7 @@ def get_doc(self) -> 'QAPIDoc': ) raise QAPIParseError(self, emsg) + _tag_check(match.group(1)) doc.new_tagged_section( self.info, QAPIDoc.Kind.from_string(match.group(1)) @@ -632,6 +647,8 @@ def get_doc(self) -> 'QAPIDoc': have_tagged = True else: # plain paragraph + if have_tagged: + no_more_tags = True # Paragraphs before tagged sections are "intro" paragraphs. # Any appearing after are "detail" paragraphs. diff --git a/tests/qapi-schema/doc-good.json b/tests/qapi-schema/doc-good.json index fac13425b72..9103fed472e 100644 --- a/tests/qapi-schema/doc-good.json +++ b/tests/qapi-schema/doc-good.json @@ -165,12 +165,12 @@ # @cmd-feat1: a feature # @cmd-feat2: another feature # -# .. note:: @arg3 is undocumented -# # Returns: @Object # # Errors: some # +# .. note:: @arg3 is undocumented +# # TODO: frobnicate # # .. admonition:: Notes diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out index 04e29e8d50f..6a0167ad580 100644 --- a/tests/qapi-schema/doc-good.out +++ b/tests/qapi-schema/doc-good.out @@ -175,12 +175,12 @@ description starts on the same line a feature feature=cmd-feat2 another feature - section=Details -.. note:: @arg3 is undocumented section=Returns @Object section=Errors some + section=Details +.. note:: @arg3 is undocumented section=Todo frobnicate section=Details diff --git a/tests/qapi-schema/doc-good.txt b/tests/qapi-schema/doc-good.txt index 74b73681d32..ded699dd596 100644 --- a/tests/qapi-schema/doc-good.txt +++ b/tests/qapi-schema/doc-good.txt @@ -120,16 +120,16 @@ Command cmd (Since: 2.10) * **cmd-feat2** -- another feature - Note: - - "arg3" is undocumented - Return: "Object" -- "Object" Errors: some + Note: + + "arg3" is undocumented + Notes: * Lorem ipsum dolor sit amet -- 2.53.0 ^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [PATCH 2/8] qapi: prohibit 'details' sections between tagged sections 2026-03-16 18:26 ` [PATCH 2/8] qapi: prohibit 'details' sections between tagged sections John Snow @ 2026-03-20 12:46 ` Markus Armbruster 2026-03-20 17:40 ` John Snow 2026-03-20 13:46 ` Markus Armbruster 1 sibling, 1 reply; 29+ messages in thread From: Markus Armbruster @ 2026-03-20 12:46 UTC (permalink / raw) To: John Snow Cc: qemu-devel, Pierrick Bouvier, Lukas Straub, Richard Henderson, Zhao Liu, Jason Wang, Mauro Carvalho Chehab, Alex Bennée, Peter Xu, Eric Blake, Daniel P. Berrangé, Fabiano Rosas, Philippe Mathieu-Daudé, Cédric Le Goater, qemu-block, Marc-André Lureau, Peter Maydell, Michael S. Tsirkin, Stefan Berger, Alex Williamson, Marcel Apfelbaum, Kevin Wolf, Michael Roth, Stefano Garzarella, Stefan Hajnoczi, Igor Mammedov, Jiri Pirko, Yanan Wang, Paolo Bonzini, Kashyap Chamarthy, Hanna Reitz, Ani Sinha John Snow <jsnow@redhat.com> writes: > This patch prohibits plain documentation sections from appearing between > "tagged" sections. The two existing uses of this pattern are patched > out. One real use, and one just for test coverage. > This is being done primarily to ensure consistency between the source > documents and the final, rendered HTML output. Because > member/feature/returns/error sections will always appear in a visually > grouped element in the HTML output, prohibiting plain paragraphs between > those sections ensures ordering consistency between source and the final > render. Is consistency an actual problem being fixed, or a future problem being avoided? I'm guessing the latter, based on my review of qom.json below. > Additionally, prohibiting such "middle" text paragraphs allows us to > classify all plain text sections as either "intro" or "details" sections, > because these sections must either appear before structured/tagged > sections ("intro") or afterwards ("details"). Huh? The previous patch already classified all plain text sections as either INTRO or DETAILS. I think the paragraph would make sense if this patch came before the previous one. > This keeps the inlining algorithm simpler with fewer "splice" points > when merging multiple documentation blocks. > > Signed-off-by: John Snow <jsnow@redhat.com> > --- > qapi/qom.json | 4 ++-- > scripts/qapi/parser.py | 17 +++++++++++++++++ > tests/qapi-schema/doc-good.json | 4 ++-- > tests/qapi-schema/doc-good.out | 4 ++-- > tests/qapi-schema/doc-good.txt | 8 ++++---- > 5 files changed, 27 insertions(+), 10 deletions(-) > > diff --git a/qapi/qom.json b/qapi/qom.json > index c653248f85d..1b47abd44e9 100644 > --- a/qapi/qom.json > +++ b/qapi/qom.json > @@ -243,12 +243,12 @@ > # > # @typename: the type name of an object > # > +# Returns: a list describing object 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. > # > -# Returns: a list describing object properties > -# > # Since: 2.12 > ## > { 'command': 'qom-list-properties', Rendered documentation before the patch: Command qom-list-properties (Since: 2.12) List properties associated with a QOM object. Arguments: * typename (string) -- 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. Return: [ObjectPropertyInfo] -- a list describing object properties Afterwards: Command qom-list-properties (Since: 2.12) List properties associated with a QOM object. Arguments: * typename (string) -- the type name of an object Return: [ObjectPropertyInfo] -- a list describing object 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. Fine. [Skipping the Python code in my first pass...] > diff --git a/tests/qapi-schema/doc-good.json b/tests/qapi-schema/doc-good.json > index fac13425b72..9103fed472e 100644 > --- a/tests/qapi-schema/doc-good.json > +++ b/tests/qapi-schema/doc-good.json > @@ -165,12 +165,12 @@ > # @cmd-feat1: a feature > # @cmd-feat2: another feature > # > -# .. note:: @arg3 is undocumented > -# > # Returns: @Object > # > # Errors: some > # > +# .. note:: @arg3 is undocumented > +# > # TODO: frobnicate > # > # .. admonition:: Notes > diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out > index 04e29e8d50f..6a0167ad580 100644 > --- a/tests/qapi-schema/doc-good.out > +++ b/tests/qapi-schema/doc-good.out > @@ -175,12 +175,12 @@ description starts on the same line > a feature > feature=cmd-feat2 > another feature > - section=Details > -.. note:: @arg3 is undocumented > section=Returns > @Object > section=Errors > some > + section=Details > +.. note:: @arg3 is undocumented > section=Todo > frobnicate > section=Details The Details section is still between tagged sections. The code prohibiting it must have a hole :) > diff --git a/tests/qapi-schema/doc-good.txt b/tests/qapi-schema/doc-good.txt > index 74b73681d32..ded699dd596 100644 > --- a/tests/qapi-schema/doc-good.txt > +++ b/tests/qapi-schema/doc-good.txt > @@ -120,16 +120,16 @@ Command cmd (Since: 2.10) > > * **cmd-feat2** -- another feature > > - Note: > - > - "arg3" is undocumented > - > Return: > "Object" -- "Object" > > Errors: > some > > + Note: > + > + "arg3" is undocumented > + > Notes: > > * Lorem ipsum dolor sit amet ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 2/8] qapi: prohibit 'details' sections between tagged sections 2026-03-20 12:46 ` Markus Armbruster @ 2026-03-20 17:40 ` John Snow 2026-03-23 8:41 ` Markus Armbruster 0 siblings, 1 reply; 29+ messages in thread From: John Snow @ 2026-03-20 17:40 UTC (permalink / raw) To: Markus Armbruster Cc: qemu-devel, Pierrick Bouvier, Lukas Straub, Richard Henderson, Zhao Liu, Jason Wang, Mauro Carvalho Chehab, Alex Bennée, Peter Xu, Eric Blake, Daniel P. Berrangé, Fabiano Rosas, Philippe Mathieu-Daudé, Cédric Le Goater, Qemu-block, Marc-André Lureau, Peter Maydell, Michael S. Tsirkin, Stefan Berger, Alex Williamson, Marcel Apfelbaum, Kevin Wolf, Michael Roth, Stefano Garzarella, Stefan Hajnoczi, Igor Mammedov, Jiri Pirko, Yanan Wang, Paolo Bonzini, Kashyap Chamarthy, Hanna Reitz, Ani Sinha [-- Attachment #1: Type: text/plain, Size: 8483 bytes --] On Fri, Mar 20, 2026, 8:46 AM Markus Armbruster <armbru@redhat.com> wrote: > John Snow <jsnow@redhat.com> writes: > > > This patch prohibits plain documentation sections from appearing between > > "tagged" sections. The two existing uses of this pattern are patched > > out. > > One real use, and one just for test coverage. > > > This is being done primarily to ensure consistency between the source > > documents and the final, rendered HTML output. Because > > member/feature/returns/error sections will always appear in a visually > > grouped element in the HTML output, prohibiting plain paragraphs between > > those sections ensures ordering consistency between source and the final > > render. > > Is consistency an actual problem being fixed, or a future problem being > avoided? I'm guessing the latter, based on my review of qom.json below. > With just one actual use, it's *mostly* avoiding future problems. It does correct one instance in the rendered HTML of a plain text paragraph interrupting the tabular fields, which is not a "bug" per se but a visual inconsistency I wish to eliminate. The problem is minimal now, but intensifies when considering inlining. Prohibiting the insertion of any section into the "tabular region" helps ensure consistent, good looking HTML manual output. A goal is for source order to match rendered order. Rendered order looks best with all tabular elements grouped together without root-level paragraphs interrupting them. Thus, the desire to restrict source order. (i.e. we allow only one intro section and only one details section.) > > Additionally, prohibiting such "middle" text paragraphs allows us to > > classify all plain text sections as either "intro" or "details" sections, > > because these sections must either appear before structured/tagged > > sections ("intro") or afterwards ("details"). > > Huh? > > The previous patch already classified all plain text sections as either > INTRO or DETAILS. > > I think the paragraph would make sense if this patch came before the > previous one. > Mmm. The previous patch is confusingly worded and I didn't do better here. Previous patch categorizes all plaintext sections as intro or details, but technically allows multiple details sections. This patch enforces that we only have one. (...I think. Currently not clear on how TODO and Since behave with this logic. Maybe we end up with multiple details sections interrupted only by non-rendered sections... Edit: yes, you find such a case below.) > > This keeps the inlining algorithm simpler with fewer "splice" points > > when merging multiple documentation blocks. > > > > Signed-off-by: John Snow <jsnow@redhat.com> > > --- > > qapi/qom.json | 4 ++-- > > scripts/qapi/parser.py | 17 +++++++++++++++++ > > tests/qapi-schema/doc-good.json | 4 ++-- > > tests/qapi-schema/doc-good.out | 4 ++-- > > tests/qapi-schema/doc-good.txt | 8 ++++---- > > 5 files changed, 27 insertions(+), 10 deletions(-) > > > > diff --git a/qapi/qom.json b/qapi/qom.json > > index c653248f85d..1b47abd44e9 100644 > > --- a/qapi/qom.json > > +++ b/qapi/qom.json > > @@ -243,12 +243,12 @@ > > # > > # @typename: the type name of an object > > # > > +# Returns: a list describing object 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. > > # > > -# Returns: a list describing object properties > > -# > > # Since: 2.12 > > ## > > { 'command': 'qom-list-properties', > > Rendered documentation before the patch: > > Command qom-list-properties (Since: 2.12) > > List properties associated with a QOM object. > > Arguments: > * typename (string) -- 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. > > Return: > [ObjectPropertyInfo] -- a list describing object properties > > Afterwards: > > Command qom-list-properties (Since: 2.12) > > List properties associated with a QOM object. > > Arguments: > * typename (string) -- the type name of an object > > Return: > [ObjectPropertyInfo] -- a list describing object 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. > > Fine. > > [Skipping the Python code in my first pass...] > > > diff --git a/tests/qapi-schema/doc-good.json > b/tests/qapi-schema/doc-good.json > > index fac13425b72..9103fed472e 100644 > > --- a/tests/qapi-schema/doc-good.json > > +++ b/tests/qapi-schema/doc-good.json > > @@ -165,12 +165,12 @@ > > # @cmd-feat1: a feature > > # @cmd-feat2: another feature > > # > > -# .. note:: @arg3 is undocumented > > -# > > # Returns: @Object > > # > > # Errors: some > > # > > +# .. note:: @arg3 is undocumented > > +# > > # TODO: frobnicate > > # > > # .. admonition:: Notes > > diff --git a/tests/qapi-schema/doc-good.out > b/tests/qapi-schema/doc-good.out > > index 04e29e8d50f..6a0167ad580 100644 > > --- a/tests/qapi-schema/doc-good.out > > +++ b/tests/qapi-schema/doc-good.out > > @@ -175,12 +175,12 @@ description starts on the same line > > a feature > > feature=cmd-feat2 > > another feature > > - section=Details > > -.. note:: @arg3 is undocumented > > section=Returns > > @Object > > section=Errors > > some > > + section=Details > > +.. note:: @arg3 is undocumented > > section=Todo > > frobnicate > > section=Details > > The Details section is still between tagged sections. The code > prohibiting it must have a hole :) > Well, there's the answer to my above self-musing on Since/TODO... After reading my replies, is it clear what I am concerned with accomplishing? If not, the goal for *rendered output* is this: 1. Intro (literally and truly only ever one section, both in the QAPIDoc sense and in the rendered HTML output sense) 2. All tabular sections (members, returns, Errors, features) 3. Details You'll notice I didn't bother specifying Since and TODO here. TODO is removed from rendered output, so I don't actually care where it goes in the QAPIDoc source list. Since is also removed from the flow in the HTML output, so I also don't care about it. (However, you requested that it specifically go last, so I do address that in this series and later prohibit any details sections from appearing after a Since marker.) The true "semantic" goals here are two things: (1) Prohibiting free text from appearing within the tabular section region (2) Delineating free text that appears before the tabular region from free text that appears after it. I apologize for conflating "section order" with "rendered section order". You are right to point out that these sections i do not care about may, in the source, impact the classification of other sections and the total number thereof. (i.e. TODO is enough to terminate the intro without an explicit details marker, and Since/TODO can create multiple details sections after the tabular region. They are merged visually but not in the QAPIDoc sections list. I don't consider this a bug per se, but it is the source of a lot of confusion here in this series when I am eliding that technicality.) > > diff --git a/tests/qapi-schema/doc-good.txt > b/tests/qapi-schema/doc-good.txt > > index 74b73681d32..ded699dd596 100644 > > --- a/tests/qapi-schema/doc-good.txt > > +++ b/tests/qapi-schema/doc-good.txt > > @@ -120,16 +120,16 @@ Command cmd (Since: 2.10) > > > > * **cmd-feat2** -- another feature > > > > - Note: > > - > > - "arg3" is undocumented > > - > > Return: > > "Object" -- "Object" > > > > Errors: > > some > > > > + Note: > > + > > + "arg3" is undocumented > > + > > Notes: > > > > * Lorem ipsum dolor sit amet > > [-- Attachment #2: Type: text/html, Size: 11734 bytes --] ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 2/8] qapi: prohibit 'details' sections between tagged sections 2026-03-20 17:40 ` John Snow @ 2026-03-23 8:41 ` Markus Armbruster 0 siblings, 0 replies; 29+ messages in thread From: Markus Armbruster @ 2026-03-23 8:41 UTC (permalink / raw) To: John Snow Cc: qemu-devel, Pierrick Bouvier, Lukas Straub, Richard Henderson, Zhao Liu, Jason Wang, Mauro Carvalho Chehab, Alex Bennée, Peter Xu, Eric Blake, Daniel P. Berrangé, Fabiano Rosas, Philippe Mathieu-Daudé, Cédric Le Goater, Qemu-block, Marc-André Lureau, Peter Maydell, Michael S. Tsirkin, Stefan Berger, Alex Williamson, Marcel Apfelbaum, Kevin Wolf, Michael Roth, Stefano Garzarella, Stefan Hajnoczi, Igor Mammedov, Jiri Pirko, Yanan Wang, Paolo Bonzini, Kashyap Chamarthy, Hanna Reitz, Ani Sinha John Snow <jsnow@redhat.com> writes: > On Fri, Mar 20, 2026, 8:46 AM Markus Armbruster <armbru@redhat.com> wrote: > >> John Snow <jsnow@redhat.com> writes: >> >> > This patch prohibits plain documentation sections from appearing between >> > "tagged" sections. The two existing uses of this pattern are patched >> > out. >> >> One real use, and one just for test coverage. >> >> > This is being done primarily to ensure consistency between the source >> > documents and the final, rendered HTML output. Because >> > member/feature/returns/error sections will always appear in a visually >> > grouped element in the HTML output, prohibiting plain paragraphs between >> > those sections ensures ordering consistency between source and the final >> > render. >> >> Is consistency an actual problem being fixed, or a future problem being >> avoided? I'm guessing the latter, based on my review of qom.json below. >> > > With just one actual use, it's *mostly* avoiding future problems. It does > correct one instance in the rendered HTML of a plain text paragraph > interrupting the tabular fields, which is not a "bug" per se but a visual > inconsistency I wish to eliminate. A visual blemish you wish to eliminate is not an inconsistency between doc source and rendered doc. It would become one if you made the generator move the PLAIN section out to fix the blemish, but that's not the plan. Instead, you fix the blemish by making doc writers move their PLAIN sections out. > The problem is minimal now, but intensifies when considering inlining. Would inlining make it necessary for the generator to move PLAIN sections around? Why? If yes, this patch eliminates a visual blemish now *and* avoids inconsistency later. > Prohibiting the insertion of any section into the "tabular region" helps > ensure consistent, good looking HTML manual output. > > A goal is for source order to match rendered order. Rendered order looks > best with all tabular elements grouped together without root-level > paragraphs interrupting them. > > Thus, the desire to restrict source order. > > (i.e. we allow only one intro section and only one details section.) I'm not opposed to that, I just want a clearer commit message :) >> > Additionally, prohibiting such "middle" text paragraphs allows us to >> > classify all plain text sections as either "intro" or "details" sections, >> > because these sections must either appear before structured/tagged >> > sections ("intro") or afterwards ("details"). >> >> Huh? >> >> The previous patch already classified all plain text sections as either >> INTRO or DETAILS. >> >> I think the paragraph would make sense if this patch came before the >> previous one. >> > > Mmm. > > The previous patch is confusingly worded and I didn't do better here. > > Previous patch categorizes all plaintext sections as intro or details, but > technically allows multiple details sections. > > This patch enforces that we only have one. > > (...I think. Currently not clear on how TODO and Since behave with this > logic. Maybe we end up with multiple details sections interrupted only by > non-rendered sections... Edit: yes, you find such a case below.) > > >> > This keeps the inlining algorithm simpler with fewer "splice" points >> > when merging multiple documentation blocks. >> > >> > Signed-off-by: John Snow <jsnow@redhat.com> >> > --- >> > qapi/qom.json | 4 ++-- >> > scripts/qapi/parser.py | 17 +++++++++++++++++ >> > tests/qapi-schema/doc-good.json | 4 ++-- >> > tests/qapi-schema/doc-good.out | 4 ++-- >> > tests/qapi-schema/doc-good.txt | 8 ++++---- >> > 5 files changed, 27 insertions(+), 10 deletions(-) >> > >> > diff --git a/qapi/qom.json b/qapi/qom.json >> > index c653248f85d..1b47abd44e9 100644 >> > --- a/qapi/qom.json >> > +++ b/qapi/qom.json >> > @@ -243,12 +243,12 @@ >> > # >> > # @typename: the type name of an object >> > # >> > +# Returns: a list describing object 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. >> > # >> > -# Returns: a list describing object properties >> > -# >> > # Since: 2.12 >> > ## >> > { 'command': 'qom-list-properties', >> >> Rendered documentation before the patch: >> >> Command qom-list-properties (Since: 2.12) >> >> List properties associated with a QOM object. >> >> Arguments: >> * typename (string) -- 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. >> >> Return: >> [ObjectPropertyInfo] -- a list describing object properties >> >> Afterwards: >> >> Command qom-list-properties (Since: 2.12) >> >> List properties associated with a QOM object. >> >> Arguments: >> * typename (string) -- the type name of an object >> >> Return: >> [ObjectPropertyInfo] -- a list describing object 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. >> >> Fine. >> >> [Skipping the Python code in my first pass...] >> >> > diff --git a/tests/qapi-schema/doc-good.json b/tests/qapi-schema/doc-good.json >> > index fac13425b72..9103fed472e 100644 >> > --- a/tests/qapi-schema/doc-good.json >> > +++ b/tests/qapi-schema/doc-good.json >> > @@ -165,12 +165,12 @@ >> > # @cmd-feat1: a feature >> > # @cmd-feat2: another feature >> > # >> > -# .. note:: @arg3 is undocumented >> > -# >> > # Returns: @Object >> > # >> > # Errors: some >> > # >> > +# .. note:: @arg3 is undocumented >> > +# >> > # TODO: frobnicate >> > # >> > # .. admonition:: Notes >> > diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out >> > index 04e29e8d50f..6a0167ad580 100644 >> > --- a/tests/qapi-schema/doc-good.out >> > +++ b/tests/qapi-schema/doc-good.out >> > @@ -175,12 +175,12 @@ description starts on the same line >> > a feature >> > feature=cmd-feat2 >> > another feature >> > - section=Details >> > -.. note:: @arg3 is undocumented >> > section=Returns >> > @Object >> > section=Errors >> > some >> > + section=Details >> > +.. note:: @arg3 is undocumented >> > section=Todo >> > frobnicate >> > section=Details >> >> The Details section is still between tagged sections. The code >> prohibiting it must have a hole :) >> > > Well, there's the answer to my above self-musing on Since/TODO... > After reading my replies, is it clear what I am concerned with > accomplishing? > > If not, the goal for *rendered output* is this: > > 1. Intro (literally and truly only ever one section, both in the QAPIDoc > sense and in the rendered HTML output sense) > > 2. All tabular sections (members, returns, Errors, features) > > 3. Details > > You'll notice I didn't bother specifying Since and TODO here. TODO is > removed from rendered output, so I don't actually care where it goes in the > QAPIDoc source list. > > Since is also removed from the flow in the HTML output, so I also don't > care about it. (However, you requested that it specifically go last, so I > do address that in this series and later prohibit any details sections from > appearing after a Since marker.) Understood. > The true "semantic" goals here are two things: > > (1) Prohibiting free text from appearing within the tabular section region > > (2) Delineating free text that appears before the tabular region from free > text that appears after it. > > I apologize for conflating "section order" with "rendered section order". > > You are right to point out that these sections i do not care about may, in > the source, impact the classification of other sections and the total > number thereof. > > (i.e. TODO is enough to terminate the intro without an explicit details > marker, and Since/TODO can create multiple details sections after the > tabular region. They are merged visually but not in the QAPIDoc sections > list. I don't consider this a bug per se, but it is the source of a lot of > confusion here in this series when I am eliding that technicality.) A commit message needs to explain why and how the patch is useful. When details distract from the core argument too much, it can be beneficial to gloss over them. Glossing over is not the same as not mentioning. Commit message readers use it to build a mental model of things. A good model simplifies reality. A bad model misleads about reality. If the commit message completely elides details that matter, readers end up with bad models and unwarranted confidence in them. They'll then struggle with the patch. If the commit message at least hints at the details elided, readers may still end up with bad models, but they'll hopefully understand their limitations, treat them as incomplete, and fill in the details from the patch. [...] ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 2/8] qapi: prohibit 'details' sections between tagged sections 2026-03-16 18:26 ` [PATCH 2/8] qapi: prohibit 'details' sections between tagged sections John Snow 2026-03-20 12:46 ` Markus Armbruster @ 2026-03-20 13:46 ` Markus Armbruster 2026-03-20 17:42 ` John Snow 1 sibling, 1 reply; 29+ messages in thread From: Markus Armbruster @ 2026-03-20 13:46 UTC (permalink / raw) To: John Snow Cc: qemu-devel, Pierrick Bouvier, Lukas Straub, Richard Henderson, Zhao Liu, Jason Wang, Mauro Carvalho Chehab, Alex Bennée, Peter Xu, Eric Blake, Daniel P. Berrangé, Fabiano Rosas, Philippe Mathieu-Daudé, Cédric Le Goater, qemu-block, Marc-André Lureau, Peter Maydell, Michael S. Tsirkin, Stefan Berger, Alex Williamson, Marcel Apfelbaum, Kevin Wolf, Michael Roth, Stefano Garzarella, Stefan Hajnoczi, Igor Mammedov, Jiri Pirko, Yanan Wang, Paolo Bonzini, Kashyap Chamarthy, Hanna Reitz, Ani Sinha John Snow <jsnow@redhat.com> writes: > This patch prohibits plain documentation sections from appearing between > "tagged" sections. The two existing uses of this pattern are patched > out. > > This is being done primarily to ensure consistency between the source > documents and the final, rendered HTML output. Because > member/feature/returns/error sections will always appear in a visually > grouped element in the HTML output, prohibiting plain paragraphs between > those sections ensures ordering consistency between source and the final > render. > > Additionally, prohibiting such "middle" text paragraphs allows us to > classify all plain text sections as either "intro" or "details" sections, > because these sections must either appear before structured/tagged > sections ("intro") or afterwards ("details"). > > This keeps the inlining algorithm simpler with fewer "splice" points > when merging multiple documentation blocks. > > Signed-off-by: John Snow <jsnow@redhat.com> > --- > qapi/qom.json | 4 ++-- > scripts/qapi/parser.py | 17 +++++++++++++++++ > tests/qapi-schema/doc-good.json | 4 ++-- > tests/qapi-schema/doc-good.out | 4 ++-- > tests/qapi-schema/doc-good.txt | 8 ++++---- > 5 files changed, 27 insertions(+), 10 deletions(-) Missing: update to docs/devel/qapi-code-gen.rst. Suggest to put in a FIXME, so we don't forget. Missing: negative test case for the new error. ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 2/8] qapi: prohibit 'details' sections between tagged sections 2026-03-20 13:46 ` Markus Armbruster @ 2026-03-20 17:42 ` John Snow 0 siblings, 0 replies; 29+ messages in thread From: John Snow @ 2026-03-20 17:42 UTC (permalink / raw) To: Markus Armbruster Cc: qemu-devel, Pierrick Bouvier, Lukas Straub, Richard Henderson, Zhao Liu, Jason Wang, Mauro Carvalho Chehab, Alex Bennée, Peter Xu, Eric Blake, Daniel P. Berrangé, Fabiano Rosas, Philippe Mathieu-Daudé, Cédric Le Goater, Qemu-block, Marc-André Lureau, Peter Maydell, Michael S. Tsirkin, Stefan Berger, Alex Williamson, Marcel Apfelbaum, Kevin Wolf, Michael Roth, Stefano Garzarella, Stefan Hajnoczi, Igor Mammedov, Jiri Pirko, Yanan Wang, Paolo Bonzini, Kashyap Chamarthy, Hanna Reitz, Ani Sinha [-- Attachment #1: Type: text/plain, Size: 1769 bytes --] On Fri, Mar 20, 2026, 9:47 AM Markus Armbruster <armbru@redhat.com> wrote: > John Snow <jsnow@redhat.com> writes: > > > This patch prohibits plain documentation sections from appearing between > > "tagged" sections. The two existing uses of this pattern are patched > > out. > > > > This is being done primarily to ensure consistency between the source > > documents and the final, rendered HTML output. Because > > member/feature/returns/error sections will always appear in a visually > > grouped element in the HTML output, prohibiting plain paragraphs between > > those sections ensures ordering consistency between source and the final > > render. > > > > Additionally, prohibiting such "middle" text paragraphs allows us to > > classify all plain text sections as either "intro" or "details" sections, > > because these sections must either appear before structured/tagged > > sections ("intro") or afterwards ("details"). > > > > This keeps the inlining algorithm simpler with fewer "splice" points > > when merging multiple documentation blocks. > > > > Signed-off-by: John Snow <jsnow@redhat.com> > > --- > > qapi/qom.json | 4 ++-- > > scripts/qapi/parser.py | 17 +++++++++++++++++ > > tests/qapi-schema/doc-good.json | 4 ++-- > > tests/qapi-schema/doc-good.out | 4 ++-- > > tests/qapi-schema/doc-good.txt | 8 ++++---- > > 5 files changed, 27 insertions(+), 10 deletions(-) > > Missing: update to docs/devel/qapi-code-gen.rst. Suggest to put in a > FIXME, so we don't forget. > I will add a FIXME. > Missing: negative test case for the new error. > I will add a FIXME here as well and implement the test once we agree on the approach, implementation, and wording. > [-- Attachment #2: Type: text/html, Size: 2954 bytes --] ^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 3/8] qapi: add "Details:" disambiguation marker 2026-03-16 18:25 [PATCH 0/8] qapi: enforce section ordering John Snow 2026-03-16 18:26 ` [PATCH 1/8] qapi: differentiate "intro" and "details" sections John Snow 2026-03-16 18:26 ` [PATCH 2/8] qapi: prohibit 'details' sections between tagged sections John Snow @ 2026-03-16 18:26 ` John Snow 2026-03-20 13:45 ` Markus Armbruster 2026-03-16 18:26 ` [PATCH 4/8] qapi: detect potentially semantically ambiguous intro paragraphs John Snow ` (4 subsequent siblings) 7 siblings, 1 reply; 29+ messages in thread From: John Snow @ 2026-03-16 18:26 UTC (permalink / raw) To: qemu-devel Cc: Pierrick Bouvier, Lukas Straub, Richard Henderson, Zhao Liu, Jason Wang, Mauro Carvalho Chehab, Alex Bennée, Peter Xu, Eric Blake, Daniel P. Berrangé, Fabiano Rosas, Philippe Mathieu-Daudé, Cédric Le Goater, qemu-block, Marc-André Lureau, Peter Maydell, Michael S. Tsirkin, Stefan Berger, Alex Williamson, Marcel Apfelbaum, Kevin Wolf, John Snow, Michael Roth, Stefano Garzarella, Stefan Hajnoczi, Igor Mammedov, Jiri Pirko, Yanan Wang, Paolo Bonzini, Kashyap Chamarthy, Markus Armbruster, Hanna Reitz, Ani Sinha When a documentation block consists only of plaintext, there is nothing to semantically differentiate the "intro" from the "details" section. For the purposes of the inliner, the intro section is likely to be dropped while the details section will be merged onto the end of the parent's details section. When the delineation between "intro" and "details" is not clear because there is no intervening "members", "features", "errors", "returns", "TODO", or "Since" section, the parser assumes the entire text section is an "intro" section. This may not always be semantically true, so this patch clarifies certain sections explicitly as "details" sections by using an empty "Details:" marker. Signed-off-by: John Snow <jsnow@redhat.com> --- qapi/block-core.json | 3 +++ qapi/machine.json | 2 +- qapi/migration.json | 8 ++++++-- qapi/net.json | 2 +- qapi/qom.json | 4 ++++ qapi/yank.json | 2 +- scripts/qapi/parser.py | 8 ++++++++ 7 files changed, 24 insertions(+), 5 deletions(-) diff --git a/qapi/block-core.json b/qapi/block-core.json index f8d446b3d6e..c5ff15ae7a1 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -5007,6 +5007,9 @@ # @blockdev-reopen: # # Reopens one or more block devices using the given set of options. +# +# Details: +# # Any option not specified will be reset to its default value # regardless of its previous status. If an option cannot be changed # or a particular driver does not support reopening then the command diff --git a/qapi/machine.json b/qapi/machine.json index 685e4e29b87..bc2279b2526 100644 --- a/qapi/machine.json +++ b/qapi/machine.json @@ -1259,7 +1259,7 @@ # Return the amount of initially allocated and present hotpluggable # (if enabled) memory in bytes. # -# TODO: This line is a hack to separate the example from the body +# Details: # # .. qmp-example:: # diff --git a/qapi/migration.json b/qapi/migration.json index 7134d4ce47e..558b4f145ed 100644 --- a/qapi/migration.json +++ b/qapi/migration.json @@ -1633,7 +1633,7 @@ # # Query replication status while the vm is running. # -# TODO: This line is a hack to separate the example from the body +# Details: # # .. qmp-example:: # @@ -1651,6 +1651,8 @@ # # Xen uses this command to notify replication to trigger a checkpoint. # +# Details: +# # .. qmp-example:: # # -> { "execute": "xen-colo-do-checkpoint" } @@ -1687,7 +1689,7 @@ # # Query COLO status while the vm is running. # -# TODO: This line is a hack to separate the example from the body +# Details: # # .. qmp-example:: # @@ -1724,6 +1726,8 @@ # # Pause a migration. Currently it only supports postcopy. # +# Details: +# # .. qmp-example:: # # -> { "execute": "migrate-pause" } diff --git a/qapi/net.json b/qapi/net.json index 118bd349651..c011d6dc1a9 100644 --- a/qapi/net.json +++ b/qapi/net.json @@ -1070,7 +1070,7 @@ # switches. This can be useful when network bonds fail-over the # active slave. # -# TODO: This line is a hack to separate the example from the body +# Details: # # .. qmp-example:: # diff --git a/qapi/qom.json b/qapi/qom.json index 1b47abd44e9..568b7d4b997 100644 --- a/qapi/qom.json +++ b/qapi/qom.json @@ -777,6 +777,8 @@ # # Properties for memory-backend-shm objects. # +# Details: +# # This memory backend supports only shared memory, which is the # default. # @@ -792,6 +794,8 @@ # # Properties for memory-backend-epc objects. # +# Details: +# # The @merge boolean option is false by default with epc # # The @dump boolean option is false by default with epc diff --git a/qapi/yank.json b/qapi/yank.json index f3cd5c15d60..2854a8a9d2a 100644 --- a/qapi/yank.json +++ b/qapi/yank.json @@ -104,7 +104,7 @@ # # Query yank instances. See `YankInstance` for more information. # -# TODO: This line is a hack to separate the example from the body +# Details: # # .. qmp-example:: # diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py index dea056df30d..da47ee55bdd 100644 --- a/scripts/qapi/parser.py +++ b/scripts/qapi/parser.py @@ -588,6 +588,14 @@ def _tag_check(what: str) -> None: raise QAPIParseError( self, 'feature descriptions expected') have_tagged = True + elif line == 'Details:': + _tag_check("Details") + self.accept(False) + line = self.get_doc_line() + while line == '': + self.accept(False) + line = self.get_doc_line() + have_tagged = True elif match := self._match_at_name_colon(line): # description if have_tagged: -- 2.53.0 ^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [PATCH 3/8] qapi: add "Details:" disambiguation marker 2026-03-16 18:26 ` [PATCH 3/8] qapi: add "Details:" disambiguation marker John Snow @ 2026-03-20 13:45 ` Markus Armbruster 2026-03-20 18:25 ` John Snow 0 siblings, 1 reply; 29+ messages in thread From: Markus Armbruster @ 2026-03-20 13:45 UTC (permalink / raw) To: John Snow Cc: qemu-devel, Pierrick Bouvier, Lukas Straub, Richard Henderson, Zhao Liu, Jason Wang, Mauro Carvalho Chehab, Alex Bennée, Peter Xu, Eric Blake, Daniel P. Berrangé, Fabiano Rosas, Philippe Mathieu-Daudé, Cédric Le Goater, qemu-block, Marc-André Lureau, Peter Maydell, Michael S. Tsirkin, Stefan Berger, Alex Williamson, Marcel Apfelbaum, Kevin Wolf, Michael Roth, Stefano Garzarella, Stefan Hajnoczi, Igor Mammedov, Jiri Pirko, Yanan Wang, Paolo Bonzini, Kashyap Chamarthy, Hanna Reitz, Ani Sinha John Snow <jsnow@redhat.com> writes: > When a documentation block consists only of plaintext, there is nothing > to semantically differentiate the "intro" from the "details" > section. For the purposes of the inliner, the intro section is likely to > be dropped while the details section will be merged onto the end of the > parent's details section. > > When the delineation between "intro" and "details" is not clear because > there is no intervening "members", "features", "errors", "returns", > "TODO", or "Since" section, the parser assumes the entire text section > is an "intro" section. This may not always be semantically true, so this > patch clarifies certain sections explicitly as "details" sections by > using an empty "Details:" marker. > > Signed-off-by: John Snow <jsnow@redhat.com> > --- > qapi/block-core.json | 3 +++ > qapi/machine.json | 2 +- > qapi/migration.json | 8 ++++++-- > qapi/net.json | 2 +- > qapi/qom.json | 4 ++++ > qapi/yank.json | 2 +- > scripts/qapi/parser.py | 8 ++++++++ > 7 files changed, 24 insertions(+), 5 deletions(-) Missing: update to docs/devel/qapi-code-gen.rst. Suggest to put in a FIXME, so we don't forget. > > diff --git a/qapi/block-core.json b/qapi/block-core.json > index f8d446b3d6e..c5ff15ae7a1 100644 > --- a/qapi/block-core.json > +++ b/qapi/block-core.json > @@ -5007,6 +5007,9 @@ > # @blockdev-reopen: > # > # Reopens one or more block devices using the given set of options. > +# > +# Details: > +# > # Any option not specified will be reset to its default value > # regardless of its previous status. If an option cannot be changed > # or a particular driver does not support reopening then the command Rendered documentation before the patch: Command blockdev-reopen (Since: 6.1) Reopens one or more block devices using the given set of options. Any option not specified will be reset to its default value regardless of its previous status. If an option cannot be changed or a particular driver does not support reopening then the command will return an error. All devices in the list are reopened in one transaction, so if one of them fails then the whole transaction is cancelled. [...] Unlike with "blockdev-add", the "backing" option must always be present unless the node being reopened does not have a backing file and its image does not have a default backing file name as part of its metadata. Arguments: * options ([BlockdevOptions]) -- Not documented The command's single argument is undocumented, and the doc generator papered over this (sadly common defect) by splicing in this "Not documented" description. Aside: why not boxed, like blockdev-add? Design mistake? The patch moves the splice point. Not wrong, but we should really fill in the document gap instead. > diff --git a/qapi/machine.json b/qapi/machine.json > index 685e4e29b87..bc2279b2526 100644 > --- a/qapi/machine.json > +++ b/qapi/machine.json > @@ -1259,7 +1259,7 @@ > # Return the amount of initially allocated and present hotpluggable > # (if enabled) memory in bytes. > # > -# TODO: This line is a hack to separate the example from the body > +# Details: This replaces a hack by a proper solution. More of the same below, not mentioning this again. > # > # .. qmp-example:: > # > diff --git a/qapi/migration.json b/qapi/migration.json > index 7134d4ce47e..558b4f145ed 100644 > --- a/qapi/migration.json > +++ b/qapi/migration.json > @@ -1633,7 +1633,7 @@ > # > # Query replication status while the vm is running. > # > -# TODO: This line is a hack to separate the example from the body > +# Details: > # > # .. qmp-example:: > # > @@ -1651,6 +1651,8 @@ > # > # Xen uses this command to notify replication to trigger a checkpoint. > # > +# Details: > +# > # .. qmp-example:: > # > # -> { "execute": "xen-colo-do-checkpoint" } No change to generated documentation. I guess this is needed to avoid the yelping added in the next patch. Correct? > @@ -1687,7 +1689,7 @@ > # > # Query COLO status while the vm is running. > # > -# TODO: This line is a hack to separate the example from the body > +# Details: > # > # .. qmp-example:: > # > @@ -1724,6 +1726,8 @@ > # > # Pause a migration. Currently it only supports postcopy. > # > +# Details: > +# > # .. qmp-example:: > # > # -> { "execute": "migrate-pause" } Likewise? > diff --git a/qapi/net.json b/qapi/net.json > index 118bd349651..c011d6dc1a9 100644 > --- a/qapi/net.json > +++ b/qapi/net.json > @@ -1070,7 +1070,7 @@ > # switches. This can be useful when network bonds fail-over the > # active slave. > # > -# TODO: This line is a hack to separate the example from the body > +# Details: > # > # .. qmp-example:: > # > diff --git a/qapi/qom.json b/qapi/qom.json > index 1b47abd44e9..568b7d4b997 100644 > --- a/qapi/qom.json > +++ b/qapi/qom.json > @@ -777,6 +777,8 @@ > # > # Properties for memory-backend-shm objects. > # > +# Details: > +# > # This memory backend supports only shared memory, which is the > # default. > # Rendered documentation changes from Object MemoryBackendShmProperties (Since: 9.1) Availability: CONFIG_POSIX Properties for memory-backend-shm objects. This memory backend supports only shared memory, which is the default. Members: * The members of MemoryBackendProperties. to Object MemoryBackendShmProperties (Since: 9.1) Availability: CONFIG_POSIX Properties for memory-backend-shm objects. Members: * The members of MemoryBackendProperties. This memory backend supports only shared memory, which is the default. Feels like a wash. I guess we need a "Details:" somewhere to avoid yelping. Correct? > @@ -792,6 +794,8 @@ > # > # Properties for memory-backend-epc objects. > # > +# Details: > +# > # The @merge boolean option is false by default with epc > # > # The @dump boolean option is false by default with epc Similar change to rendered documentation, same request to confirm yelping. > diff --git a/qapi/yank.json b/qapi/yank.json > index f3cd5c15d60..2854a8a9d2a 100644 > --- a/qapi/yank.json > +++ b/qapi/yank.json > @@ -104,7 +104,7 @@ > # > # Query yank instances. See `YankInstance` for more information. > # > -# TODO: This line is a hack to separate the example from the body > +# Details: > # > # .. qmp-example:: > # [Skipping the Python code in my first pass...] I'd be tempted to split the patch into hack replacement and yelping avoidance. ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 3/8] qapi: add "Details:" disambiguation marker 2026-03-20 13:45 ` Markus Armbruster @ 2026-03-20 18:25 ` John Snow 2026-03-23 8:55 ` Markus Armbruster 0 siblings, 1 reply; 29+ messages in thread From: John Snow @ 2026-03-20 18:25 UTC (permalink / raw) To: Markus Armbruster Cc: qemu-devel, Pierrick Bouvier, Lukas Straub, Richard Henderson, Zhao Liu, Jason Wang, Mauro Carvalho Chehab, Alex Bennée, Peter Xu, Eric Blake, Daniel P. Berrangé, Fabiano Rosas, Philippe Mathieu-Daudé, Cédric Le Goater, Qemu-block, Marc-André Lureau, Peter Maydell, Michael S. Tsirkin, Stefan Berger, Alex Williamson, Marcel Apfelbaum, Kevin Wolf, Michael Roth, Stefano Garzarella, Stefan Hajnoczi, Igor Mammedov, Jiri Pirko, Yanan Wang, Paolo Bonzini, Kashyap Chamarthy, Hanna Reitz, Ani Sinha [-- Attachment #1: Type: text/plain, Size: 8985 bytes --] On Fri, Mar 20, 2026, 9:45 AM Markus Armbruster <armbru@redhat.com> wrote: > John Snow <jsnow@redhat.com> writes: > > > When a documentation block consists only of plaintext, there is nothing > > to semantically differentiate the "intro" from the "details" > > section. For the purposes of the inliner, the intro section is likely to > > be dropped while the details section will be merged onto the end of the > > parent's details section. > > > > When the delineation between "intro" and "details" is not clear because > > there is no intervening "members", "features", "errors", "returns", > > "TODO", or "Since" section, the parser assumes the entire text section > > is an "intro" section. This may not always be semantically true, so this > > patch clarifies certain sections explicitly as "details" sections by > > using an empty "Details:" marker. > > > > Signed-off-by: John Snow <jsnow@redhat.com> > > --- > > qapi/block-core.json | 3 +++ > > qapi/machine.json | 2 +- > > qapi/migration.json | 8 ++++++-- > > qapi/net.json | 2 +- > > qapi/qom.json | 4 ++++ > > qapi/yank.json | 2 +- > > scripts/qapi/parser.py | 8 ++++++++ > > 7 files changed, 24 insertions(+), 5 deletions(-) > > Missing: update to docs/devel/qapi-code-gen.rst. Suggest to put in a > FIXME, so we don't forget. > ACK > > > > diff --git a/qapi/block-core.json b/qapi/block-core.json > > index f8d446b3d6e..c5ff15ae7a1 100644 > > --- a/qapi/block-core.json > > +++ b/qapi/block-core.json > > @@ -5007,6 +5007,9 @@ > > # @blockdev-reopen: > > # > > # Reopens one or more block devices using the given set of options. > > +# > > +# Details: > > +# > > # Any option not specified will be reset to its default value > > # regardless of its previous status. If an option cannot be changed > > # or a particular driver does not support reopening then the command > > Rendered documentation before the patch: > > Command blockdev-reopen (Since: 6.1) > > Reopens one or more block devices using the given set of options. > Any option not specified will be reset to its default value > regardless of its previous status. If an option cannot be changed > or a particular driver does not support reopening then the command > will return an error. All devices in the list are reopened in one > transaction, so if one of them fails then the whole transaction is > cancelled. > > [...] > > Unlike with "blockdev-add", the "backing" option must always be > present unless the node being reopened does not have a backing file > and its image does not have a default backing file name as part of > its metadata. > > Arguments: > * options ([BlockdevOptions]) -- Not documented > > The command's single argument is undocumented, and the doc generator > papered over this (sadly common defect) by splicing in this "Not > documented" description. > > Aside: why not boxed, like blockdev-add? Design mistake? > > The patch moves the splice point. Not wrong, but we should really fill > in the document gap instead. > Sure, but I'm worried about other things for the time being. I don't disagree but I think I'm the wrong person for intricate doc cleanup work of that sort. > > diff --git a/qapi/machine.json b/qapi/machine.json > > index 685e4e29b87..bc2279b2526 100644 > > --- a/qapi/machine.json > > +++ b/qapi/machine.json > > @@ -1259,7 +1259,7 @@ > > # Return the amount of initially allocated and present hotpluggable > > # (if enabled) memory in bytes. > > # > > -# TODO: This line is a hack to separate the example from the body > > +# Details: > > This replaces a hack by a proper solution. More of the same below, not > mentioning this again. > > > # > > # .. qmp-example:: > > # > > diff --git a/qapi/migration.json b/qapi/migration.json > > index 7134d4ce47e..558b4f145ed 100644 > > --- a/qapi/migration.json > > +++ b/qapi/migration.json > > @@ -1633,7 +1633,7 @@ > > # > > # Query replication status while the vm is running. > > # > > -# TODO: This line is a hack to separate the example from the body > > +# Details: > > # > > # .. qmp-example:: > > # > > @@ -1651,6 +1651,8 @@ > > # > > # Xen uses this command to notify replication to trigger a checkpoint. > > # > > +# Details: > > +# > > # .. qmp-example:: > > # > > # -> { "execute": "xen-colo-do-checkpoint" } > > No change to generated documentation. I guess this is needed to avoid > the yelping added in the next patch. Correct? > Yes, probably. I didn't differentiate the cases... > > @@ -1687,7 +1689,7 @@ > > # > > # Query COLO status while the vm is running. > > # > > -# TODO: This line is a hack to separate the example from the body > > +# Details: > > # > > # .. qmp-example:: > > # > > @@ -1724,6 +1726,8 @@ > > # > > # Pause a migration. Currently it only supports postcopy. > > # > > +# Details: > > +# > > # .. qmp-example:: > > # > > # -> { "execute": "migrate-pause" } > > Likewise? > > > diff --git a/qapi/net.json b/qapi/net.json > > index 118bd349651..c011d6dc1a9 100644 > > --- a/qapi/net.json > > +++ b/qapi/net.json > > @@ -1070,7 +1070,7 @@ > > # switches. This can be useful when network bonds fail-over the > > # active slave. > > # > > -# TODO: This line is a hack to separate the example from the body > > +# Details: > > # > > # .. qmp-example:: > > # > > diff --git a/qapi/qom.json b/qapi/qom.json > > index 1b47abd44e9..568b7d4b997 100644 > > --- a/qapi/qom.json > > +++ b/qapi/qom.json > > @@ -777,6 +777,8 @@ > > # > > # Properties for memory-backend-shm objects. > > # > > +# Details: > > +# > > # This memory backend supports only shared memory, which is the > > # default. > > # > > Rendered documentation changes from > > Object MemoryBackendShmProperties (Since: 9.1) > Availability: CONFIG_POSIX > > Properties for memory-backend-shm objects. > > This memory backend supports only shared memory, which is the > default. > > Members: > * The members of MemoryBackendProperties. > > to > > Object MemoryBackendShmProperties (Since: 9.1) > Availability: CONFIG_POSIX > > Properties for memory-backend-shm objects. > > Members: > * The members of MemoryBackendProperties. > > This memory backend supports only shared memory, which is the > default. > > Feels like a wash. > > I guess we need a "Details:" somewhere to avoid yelping. Correct? > If we choose to formally include the yelper patch. I included it to show all of the cases where this *might* make a difference. There's likely other heuristics we could employ to reduce how often we yelp. For instance, things that are never inlined from, or never inline, could likely be skipped as it won't make a difference. I think the trick here is to come up with a blanket "rule" that makes sense and is easy to understand for the uninitiated, even if that rule covers more cases than strictly necessary. This patch used a very broad algorithm with almost no edge cases to yelp. Concern: if I do not make the parser yelp, we may see new cases added in the future that render in unintended ways. If I make the yelper too yelpy, it's just annoying without providing sufficient benefit. Truth is likely in the middle somewhere. This patch is an effort to find and flush out that truth by brute force. > > @@ -792,6 +794,8 @@ > > # > > # Properties for memory-backend-epc objects. > > # > > +# Details: > > +# > > # The @merge boolean option is false by default with epc > > # > > # The @dump boolean option is false by default with epc > > Similar change to rendered documentation, same request to confirm > yelping. > > > diff --git a/qapi/yank.json b/qapi/yank.json > > index f3cd5c15d60..2854a8a9d2a 100644 > > --- a/qapi/yank.json > > +++ b/qapi/yank.json > > @@ -104,7 +104,7 @@ > > # > > # Query yank instances. See `YankInstance` for more information. > > # > > -# TODO: This line is a hack to separate the example from the body > > +# Details: > > # > > # .. qmp-example:: > > # > > [Skipping the Python code in my first pass...] > > I'd be tempted to split the patch into hack replacement and yelping > avoidance. > ACK, I can do that. It will take a moment to audit which cause real html output changes and which are solely yelp avoidance, but it can be done. Note that some changes may appear to be yelp avoidance only without the inliner active. Some cases *may* produce tangible differences with the inliner active. I don't have an example at hand or a method currently to identify them, it's just a heads up for the possibility. > [-- Attachment #2: Type: text/html, Size: 12388 bytes --] ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 3/8] qapi: add "Details:" disambiguation marker 2026-03-20 18:25 ` John Snow @ 2026-03-23 8:55 ` Markus Armbruster 0 siblings, 0 replies; 29+ messages in thread From: Markus Armbruster @ 2026-03-23 8:55 UTC (permalink / raw) To: John Snow Cc: qemu-devel, Pierrick Bouvier, Lukas Straub, Richard Henderson, Zhao Liu, Jason Wang, Mauro Carvalho Chehab, Alex Bennée, Peter Xu, Eric Blake, Daniel P. Berrangé, Fabiano Rosas, Philippe Mathieu-Daudé, Cédric Le Goater, Qemu-block, Marc-André Lureau, Peter Maydell, Michael S. Tsirkin, Stefan Berger, Alex Williamson, Marcel Apfelbaum, Kevin Wolf, Michael Roth, Stefano Garzarella, Stefan Hajnoczi, Igor Mammedov, Jiri Pirko, Yanan Wang, Paolo Bonzini, Kashyap Chamarthy, Hanna Reitz, Ani Sinha John Snow <jsnow@redhat.com> writes: > On Fri, Mar 20, 2026, 9:45 AM Markus Armbruster <armbru@redhat.com> wrote: > >> John Snow <jsnow@redhat.com> writes: >> >> > When a documentation block consists only of plaintext, there is nothing >> > to semantically differentiate the "intro" from the "details" >> > section. For the purposes of the inliner, the intro section is likely to >> > be dropped while the details section will be merged onto the end of the >> > parent's details section. >> > >> > When the delineation between "intro" and "details" is not clear because >> > there is no intervening "members", "features", "errors", "returns", >> > "TODO", or "Since" section, the parser assumes the entire text section >> > is an "intro" section. This may not always be semantically true, so this >> > patch clarifies certain sections explicitly as "details" sections by >> > using an empty "Details:" marker. >> > >> > Signed-off-by: John Snow <jsnow@redhat.com> >> > --- >> > qapi/block-core.json | 3 +++ >> > qapi/machine.json | 2 +- >> > qapi/migration.json | 8 ++++++-- >> > qapi/net.json | 2 +- >> > qapi/qom.json | 4 ++++ >> > qapi/yank.json | 2 +- >> > scripts/qapi/parser.py | 8 ++++++++ >> > 7 files changed, 24 insertions(+), 5 deletions(-) >> >> Missing: update to docs/devel/qapi-code-gen.rst. Suggest to put in a >> FIXME, so we don't forget. >> > > ACK > > >> > >> > diff --git a/qapi/block-core.json b/qapi/block-core.json >> > index f8d446b3d6e..c5ff15ae7a1 100644 >> > --- a/qapi/block-core.json >> > +++ b/qapi/block-core.json >> > @@ -5007,6 +5007,9 @@ >> > # @blockdev-reopen: >> > # >> > # Reopens one or more block devices using the given set of options. >> > +# >> > +# Details: >> > +# >> > # Any option not specified will be reset to its default value >> > # regardless of its previous status. If an option cannot be changed >> > # or a particular driver does not support reopening then the command >> >> Rendered documentation before the patch: >> >> Command blockdev-reopen (Since: 6.1) >> >> Reopens one or more block devices using the given set of options. >> Any option not specified will be reset to its default value >> regardless of its previous status. If an option cannot be changed >> or a particular driver does not support reopening then the command >> will return an error. All devices in the list are reopened in one >> transaction, so if one of them fails then the whole transaction is >> cancelled. >> >> [...] >> >> Unlike with "blockdev-add", the "backing" option must always be >> present unless the node being reopened does not have a backing file >> and its image does not have a default backing file name as part of >> its metadata. >> >> Arguments: >> * options ([BlockdevOptions]) -- Not documented >> >> The command's single argument is undocumented, and the doc generator >> papered over this (sadly common defect) by splicing in this "Not >> documented" description. >> >> Aside: why not boxed, like blockdev-add? Design mistake? >> >> The patch moves the splice point. Not wrong, but we should really fill >> in the document gap instead. >> > > Sure, but I'm worried about other things for the time being. I don't > disagree but I think I'm the wrong person for intricate doc cleanup work of > that sort. Put in a TODO for now? >> > diff --git a/qapi/machine.json b/qapi/machine.json >> > index 685e4e29b87..bc2279b2526 100644 >> > --- a/qapi/machine.json >> > +++ b/qapi/machine.json >> > @@ -1259,7 +1259,7 @@ >> > # Return the amount of initially allocated and present hotpluggable >> > # (if enabled) memory in bytes. >> > # >> > -# TODO: This line is a hack to separate the example from the body >> > +# Details: >> >> This replaces a hack by a proper solution. More of the same below, not >> mentioning this again. >> >> > # >> > # .. qmp-example:: >> > # >> > diff --git a/qapi/migration.json b/qapi/migration.json >> > index 7134d4ce47e..558b4f145ed 100644 >> > --- a/qapi/migration.json >> > +++ b/qapi/migration.json >> > @@ -1633,7 +1633,7 @@ >> > # >> > # Query replication status while the vm is running. >> > # >> > -# TODO: This line is a hack to separate the example from the body >> > +# Details: >> > # >> > # .. qmp-example:: >> > # >> > @@ -1651,6 +1651,8 @@ >> > # >> > # Xen uses this command to notify replication to trigger a checkpoint. >> > # >> > +# Details: >> > +# >> > # .. qmp-example:: >> > # >> > # -> { "execute": "xen-colo-do-checkpoint" } >> >> No change to generated documentation. I guess this is needed to avoid >> the yelping added in the next patch. Correct? >> > > Yes, probably. I didn't differentiate the cases... > > >> > @@ -1687,7 +1689,7 @@ >> > # >> > # Query COLO status while the vm is running. >> > # >> > -# TODO: This line is a hack to separate the example from the body >> > +# Details: >> > # >> > # .. qmp-example:: >> > # >> > @@ -1724,6 +1726,8 @@ >> > # >> > # Pause a migration. Currently it only supports postcopy. >> > # >> > +# Details: >> > +# >> > # .. qmp-example:: >> > # >> > # -> { "execute": "migrate-pause" } >> >> Likewise? >> >> > diff --git a/qapi/net.json b/qapi/net.json >> > index 118bd349651..c011d6dc1a9 100644 >> > --- a/qapi/net.json >> > +++ b/qapi/net.json >> > @@ -1070,7 +1070,7 @@ >> > # switches. This can be useful when network bonds fail-over the >> > # active slave. >> > # >> > -# TODO: This line is a hack to separate the example from the body >> > +# Details: >> > # >> > # .. qmp-example:: >> > # >> > diff --git a/qapi/qom.json b/qapi/qom.json >> > index 1b47abd44e9..568b7d4b997 100644 >> > --- a/qapi/qom.json >> > +++ b/qapi/qom.json >> > @@ -777,6 +777,8 @@ >> > # >> > # Properties for memory-backend-shm objects. >> > # >> > +# Details: >> > +# >> > # This memory backend supports only shared memory, which is the >> > # default. >> > # >> >> Rendered documentation changes from >> >> Object MemoryBackendShmProperties (Since: 9.1) >> Availability: CONFIG_POSIX >> >> Properties for memory-backend-shm objects. >> >> This memory backend supports only shared memory, which is the >> default. >> >> Members: >> * The members of MemoryBackendProperties. >> >> to >> >> Object MemoryBackendShmProperties (Since: 9.1) >> Availability: CONFIG_POSIX >> >> Properties for memory-backend-shm objects. >> >> Members: >> * The members of MemoryBackendProperties. >> >> This memory backend supports only shared memory, which is the >> default. >> >> Feels like a wash. >> >> I guess we need a "Details:" somewhere to avoid yelping. Correct? >> > > If we choose to formally include the yelper patch. I included it to show > all of the cases where this *might* make a difference. > > There's likely other heuristics we could employ to reduce how often we > yelp. For instance, things that are never inlined from, or never inline, > could likely be skipped as it won't make a difference. > > I think the trick here is to come up with a blanket "rule" that makes sense > and is easy to understand for the uninitiated, even if that rule covers > more cases than strictly necessary. Yes. I think it's better to keep the rules around "Details:" as simple as possible, even if that means we have to write it more often. The decision whether and where to write it should be as obvious as we can make it. The less obvious is it, the more often we'll get it wrong[*]. > This patch used a very broad algorithm with almost no edge cases to yelp. > > Concern: if I do not make the parser yelp, we may see new cases added in > the future that render in unintended ways. If I make the yelper too yelpy, > it's just annoying without providing sufficient benefit. Yes, this is still an open problem. > Truth is likely in the middle somewhere. This patch is an effort to find > and flush out that truth by brute force. Good. >> > @@ -792,6 +794,8 @@ >> > # >> > # Properties for memory-backend-epc objects. >> > # >> > +# Details: >> > +# >> > # The @merge boolean option is false by default with epc >> > # >> > # The @dump boolean option is false by default with epc >> >> Similar change to rendered documentation, same request to confirm >> yelping. >> >> > diff --git a/qapi/yank.json b/qapi/yank.json >> > index f3cd5c15d60..2854a8a9d2a 100644 >> > --- a/qapi/yank.json >> > +++ b/qapi/yank.json >> > @@ -104,7 +104,7 @@ >> > # >> > # Query yank instances. See `YankInstance` for more information. >> > # >> > -# TODO: This line is a hack to separate the example from the body >> > +# Details: >> > # >> > # .. qmp-example:: >> > # >> >> [Skipping the Python code in my first pass...] >> >> I'd be tempted to split the patch into hack replacement and yelping >> avoidance. >> > > ACK, I can do that. It will take a moment to audit which cause real html > output changes and which are solely yelp avoidance, but it can be done. Thanks! > Note that some changes may appear to be yelp avoidance only without the > inliner active. Some cases *may* produce tangible differences with the > inliner active. > > I don't have an example at hand or a method currently to identify them, > it's just a heads up for the possibility. [*] A glance at rendered documentation should catch most instances of wrong, but in developers generally don't do that. ^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 4/8] qapi: detect potentially semantically ambiguous intro paragraphs 2026-03-16 18:25 [PATCH 0/8] qapi: enforce section ordering John Snow ` (2 preceding siblings ...) 2026-03-16 18:26 ` [PATCH 3/8] qapi: add "Details:" disambiguation marker John Snow @ 2026-03-16 18:26 ` John Snow 2026-03-20 13:51 ` Markus Armbruster 2026-03-16 18:26 ` [PATCH 5/8] qapi: re-order QAPI doc block sections John Snow ` (3 subsequent siblings) 7 siblings, 1 reply; 29+ messages in thread From: John Snow @ 2026-03-16 18:26 UTC (permalink / raw) To: qemu-devel Cc: Pierrick Bouvier, Lukas Straub, Richard Henderson, Zhao Liu, Jason Wang, Mauro Carvalho Chehab, Alex Bennée, Peter Xu, Eric Blake, Daniel P. Berrangé, Fabiano Rosas, Philippe Mathieu-Daudé, Cédric Le Goater, qemu-block, Marc-André Lureau, Peter Maydell, Michael S. Tsirkin, Stefan Berger, Alex Williamson, Marcel Apfelbaum, Kevin Wolf, John Snow, Michael Roth, Stefano Garzarella, Stefan Hajnoczi, Igor Mammedov, Jiri Pirko, Yanan Wang, Paolo Bonzini, Kashyap Chamarthy, Markus Armbruster, Hanna Reitz, Ani Sinha Cajole the QAPI Doc parser into yelping if a QAPI Doc Block contains more than one paragraph of plaintext and has no instances of Members, Errors, Returns, or Features that would naturally delineate an introduction from additional details such as notes, examples, and additional details. Signed-off-by: John Snow <jsnow@redhat.com> --- scripts/qapi/parser.py | 44 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py index da47ee55bdd..9e8dfc67208 100644 --- a/scripts/qapi/parser.py +++ b/scripts/qapi/parser.py @@ -960,3 +960,47 @@ def check_args_section( check_args_section(self.args, 'member') check_args_section(self.features, 'feature') + + # Ignore free-form documentation sections + if self.symbol is None: + return + + n_intro_para = 0 + has_intro = False + has_other = False + + for section in self.all_sections: + # Ignore Since: and TODO: sections + if section.kind in (QAPIDoc.Kind.SINCE, QAPIDoc.Kind.TODO): + continue + + # Ignore empty plaintext sections + if section.kind in (QAPIDoc.Kind.INTRO, QAPIDoc.Kind.DETAILS): + if not section.text: + continue + + if section.kind == QAPIDoc.Kind.INTRO: + has_intro = True + n_intro_para = len(section.text.split("\n\n")) + elif not ( + section.kind == QAPIDoc.Kind.MEMBER and not section.text + ): + # This section is something other than an Intro section; + # but we explicitly exclude stub entries for members + # (undocumented fields with no text) from consideration + # because they were auto-generated; they are not useful + # for identifying the case "There are multiple intro + # paragraphs and no other explicit source sections." + has_other = True + + # If an intro section is only a single paragraph, we are + # confident it is well and truly just an introduction. If we + # have a single, multi-paragraph intro section and *no other* + # explicit sections in source code, it is potentially a semantic + # goof-em-up where the intro and details sections have bled + # together. Warn about this case. + if has_intro and n_intro_para > 1 and not has_other: + print( + f"Warning: paragraphs for {self.symbol} are ambiguous " + "and could be either intro or details paragraphs." + ) -- 2.53.0 ^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [PATCH 4/8] qapi: detect potentially semantically ambiguous intro paragraphs 2026-03-16 18:26 ` [PATCH 4/8] qapi: detect potentially semantically ambiguous intro paragraphs John Snow @ 2026-03-20 13:51 ` Markus Armbruster 2026-03-20 18:26 ` John Snow 0 siblings, 1 reply; 29+ messages in thread From: Markus Armbruster @ 2026-03-20 13:51 UTC (permalink / raw) To: John Snow Cc: qemu-devel, Pierrick Bouvier, Lukas Straub, Richard Henderson, Zhao Liu, Jason Wang, Mauro Carvalho Chehab, Alex Bennée, Peter Xu, Eric Blake, Daniel P. Berrangé, Fabiano Rosas, Philippe Mathieu-Daudé, Cédric Le Goater, qemu-block, Marc-André Lureau, Peter Maydell, Michael S. Tsirkin, Stefan Berger, Alex Williamson, Marcel Apfelbaum, Kevin Wolf, Michael Roth, Stefano Garzarella, Stefan Hajnoczi, Igor Mammedov, Jiri Pirko, Yanan Wang, Paolo Bonzini, Kashyap Chamarthy, Hanna Reitz, Ani Sinha John Snow <jsnow@redhat.com> writes: > Cajole the QAPI Doc parser into yelping if a QAPI Doc Block contains > more than one paragraph of plaintext and has no instances of Members, > Errors, Returns, or Features that would naturally delineate an > introduction from additional details such as notes, examples, and > additional details. > > Signed-off-by: John Snow <jsnow@redhat.com> > --- > scripts/qapi/parser.py | 44 ++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 44 insertions(+) Test coverage, please. ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 4/8] qapi: detect potentially semantically ambiguous intro paragraphs 2026-03-20 13:51 ` Markus Armbruster @ 2026-03-20 18:26 ` John Snow 0 siblings, 0 replies; 29+ messages in thread From: John Snow @ 2026-03-20 18:26 UTC (permalink / raw) To: Markus Armbruster Cc: qemu-devel, Pierrick Bouvier, Lukas Straub, Richard Henderson, Zhao Liu, Jason Wang, Mauro Carvalho Chehab, Alex Bennée, Peter Xu, Eric Blake, Daniel P. Berrangé, Fabiano Rosas, Philippe Mathieu-Daudé, Cédric Le Goater, Qemu-block, Marc-André Lureau, Peter Maydell, Michael S. Tsirkin, Stefan Berger, Alex Williamson, Marcel Apfelbaum, Kevin Wolf, Michael Roth, Stefano Garzarella, Stefan Hajnoczi, Igor Mammedov, Jiri Pirko, Yanan Wang, Paolo Bonzini, Kashyap Chamarthy, Hanna Reitz, Ani Sinha [-- Attachment #1: Type: text/plain, Size: 776 bytes --] On Fri, Mar 20, 2026, 9:52 AM Markus Armbruster <armbru@redhat.com> wrote: > John Snow <jsnow@redhat.com> writes: > > > Cajole the QAPI Doc parser into yelping if a QAPI Doc Block contains > > more than one paragraph of plaintext and has no instances of Members, > > Errors, Returns, or Features that would naturally delineate an > > introduction from additional details such as notes, examples, and > > additional details. > > > > Signed-off-by: John Snow <jsnow@redhat.com> > > --- > > scripts/qapi/parser.py | 44 ++++++++++++++++++++++++++++++++++++++++++ > > 1 file changed, 44 insertions(+) > > Test coverage, please. > Adding a FIXME for now. This patch is kind of a hack and we may find we want to refine it before merging, or maybe not. > [-- Attachment #2: Type: text/html, Size: 1535 bytes --] ^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 5/8] qapi: re-order QAPI doc block sections 2026-03-16 18:25 [PATCH 0/8] qapi: enforce section ordering John Snow ` (3 preceding siblings ...) 2026-03-16 18:26 ` [PATCH 4/8] qapi: detect potentially semantically ambiguous intro paragraphs John Snow @ 2026-03-16 18:26 ` John Snow 2026-03-20 14:11 ` Markus Armbruster 2026-03-16 18:26 ` [PATCH 6/8] qapi: enforce doc block section ordering John Snow ` (2 subsequent siblings) 7 siblings, 1 reply; 29+ messages in thread From: John Snow @ 2026-03-16 18:26 UTC (permalink / raw) To: qemu-devel Cc: Pierrick Bouvier, Lukas Straub, Richard Henderson, Zhao Liu, Jason Wang, Mauro Carvalho Chehab, Alex Bennée, Peter Xu, Eric Blake, Daniel P. Berrangé, Fabiano Rosas, Philippe Mathieu-Daudé, Cédric Le Goater, qemu-block, Marc-André Lureau, Peter Maydell, Michael S. Tsirkin, Stefan Berger, Alex Williamson, Marcel Apfelbaum, Kevin Wolf, John Snow, Michael Roth, Stefano Garzarella, Stefan Hajnoczi, Igor Mammedov, Jiri Pirko, Yanan Wang, Paolo Bonzini, Kashyap Chamarthy, Markus Armbruster, Hanna Reitz, Ani Sinha A forthcoming patch will enforce a rigid source order of QAPI Doc block sections: (1) Intro (2) Members (3) Returns (4) Errors (5) Features (6) Details (7) Since This patch specifically ensures the source ordering of items #1-6, with the positioning of "Since:" left for the following patch as it is a much bigger patch. Signed-off-by: John Snow <jsnow@redhat.com> --- qapi/accelerator.json | 4 +-- qapi/block-core.json | 44 +++++++++++++------------- qapi/block-export.json | 20 ++++++------ qapi/block.json | 8 ++--- qapi/machine-s390x.json | 8 ++--- qapi/machine.json | 56 ++++++++++++++++----------------- qapi/misc.json | 4 +-- qapi/qom.json | 6 ++-- qapi/virtio.json | 32 +++++++++---------- tests/qapi-schema/doc-good.json | 8 ++--- tests/qapi-schema/doc-good.txt | 10 +++--- 11 files changed, 100 insertions(+), 100 deletions(-) diff --git a/qapi/accelerator.json b/qapi/accelerator.json index 0cf5e0f9d94..d333a772384 100644 --- a/qapi/accelerator.json +++ b/qapi/accelerator.json @@ -43,12 +43,12 @@ # # Query accelerator statistics # +# Returns: accelerator statistics +# # Features: # # @unstable: This command is meant for debugging. # -# Returns: accelerator statistics -# # Since: 10.1 ## { 'command': 'x-accel-stats', diff --git a/qapi/block-core.json b/qapi/block-core.json index c5ff15ae7a1..dc97bcb9b66 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -1955,14 +1955,14 @@ # `job-dismiss`. When true, this job will automatically disappear # without user intervention. Defaults to true. (Since 3.1) # +# Errors: +# - If @device does not exist, DeviceNotFound +# # Features: # # @deprecated: Members @base and @top are deprecated. Use @base-node # and @top-node instead. # -# Errors: -# - If @device does not exist, DeviceNotFound -# # Since: 1.3 # # .. qmp-example:: @@ -1993,14 +1993,14 @@ # 'backup'. The operation can be stopped before it has completed # using the `job-cancel` or `block-job-cancel` command. # +# Errors: +# - If @device is not a valid block device, GenericError +# # Features: # # @deprecated: This command is deprecated. Use `blockdev-backup` # instead. # -# Errors: -# - If @device is not a valid block device, GenericError -# # Since: 1.6 # # .. qmp-example:: @@ -2558,14 +2558,14 @@ # # Get bitmap SHA256. # -# Features: -# -# @unstable: This command is meant for debugging. -# # Errors: # - If @node is not a valid block device, DeviceNotFound # - If @name is not found or if hashing has failed, GenericError # +# Features: +# +# @unstable: This command is meant for debugging. +# # Since: 2.10 ## { 'command': 'x-debug-block-dirty-bitmap-sha256', @@ -3068,15 +3068,15 @@ # the name of the parameter), but since QEMU 2.7 it can have other # values. # +# Errors: +# - If no background operation is active on this device, +# DeviceNotActive +# # Features: # # @deprecated: This command is deprecated. Use `job-pause` # instead. # -# Errors: -# - If no background operation is active on this device, -# DeviceNotActive -# # Since: 1.3 ## { 'command': 'block-job-pause', 'data': { 'device': 'str' }, @@ -3097,15 +3097,15 @@ # the name of the parameter), but since QEMU 2.7 it can have other # values. # +# Errors: +# - If no background operation is active on this device, +# DeviceNotActive +# # Features: # # @deprecated: This command is deprecated. Use `job-resume` # instead. # -# Errors: -# - If no background operation is active on this device, -# DeviceNotActive -# # Since: 1.3 ## { 'command': 'block-job-resume', 'data': { 'device': 'str' }, @@ -3137,15 +3137,15 @@ # the name of the parameter), but since QEMU 2.7 it can have other # values. # +# Errors: +# - If no background operation is active on this device, +# DeviceNotActive +# # Features: # # @deprecated: This command is deprecated. Use `job-complete` # instead. # -# Errors: -# - If no background operation is active on this device, -# DeviceNotActive -# # Since: 1.3 ## { 'command': 'block-job-complete', 'data': { 'device': 'str' }, diff --git a/qapi/block-export.json b/qapi/block-export.json index dd724acf1cb..d44b509968e 100644 --- a/qapi/block-export.json +++ b/qapi/block-export.json @@ -249,15 +249,15 @@ # The export name will be used as the id for the resulting block # export. # -# Features: -# -# @deprecated: This command is deprecated. Use `block-export-add` -# instead. -# # Errors: # - if the server is not running # - if an export with the same name already exists # +# Features: +# +# @deprecated: This command is deprecated. Use `block-export-add` +# instead. +# # Since: 1.3 ## { 'command': 'nbd-server-add', @@ -297,16 +297,16 @@ # @mode: Mode of command operation. See `BlockExportRemoveMode` # description. Default is 'safe'. # -# Features: -# -# @deprecated: This command is deprecated. Use `block-export-del` -# instead. -# # Errors: # - if the server is not running # - if export is not found # - if mode is 'safe' and there are existing connections # +# Features: +# +# @deprecated: This command is deprecated. Use `block-export-del` +# instead. +# # Since: 2.12 ## { 'command': 'nbd-server-remove', diff --git a/qapi/block.json b/qapi/block.json index 46955bbb3e3..54bc0056318 100644 --- a/qapi/block.json +++ b/qapi/block.json @@ -109,13 +109,13 @@ # @force: If true, eject regardless of whether the drive is locked. # If not specified, the default value is false. # -# Features: -# -# @deprecated: Member @device is deprecated. Use @id instead. -# # Errors: # - If @device is not a valid block device, DeviceNotFound # +# Features: +# +# @deprecated: Member @device is deprecated. Use @id instead. +# # .. note:: Ejecting a device with no media results in success. # # Since: 0.14 diff --git a/qapi/machine-s390x.json b/qapi/machine-s390x.json index ea430e1b889..e67f180a272 100644 --- a/qapi/machine-s390x.json +++ b/qapi/machine-s390x.json @@ -108,12 +108,12 @@ ## # @query-s390x-cpu-polarization: # -# Features: -# -# @unstable: This command is experimental. -# # Returns: the machine's CPU polarization # +# Features: +# +# @unstable: This command is experimental. +# # Since: 8.2 ## { 'command': 'query-s390x-cpu-polarization', 'returns': 'CpuPolarizationInfo', diff --git a/qapi/machine.json b/qapi/machine.json index bc2279b2526..2052ebbbb5b 100644 --- a/qapi/machine.json +++ b/qapi/machine.json @@ -1674,12 +1674,12 @@ # # Query interrupt statistics # -# Features: -# -# @unstable: This command is meant for debugging. -# # Returns: interrupt statistics # +# Features: +# +# @unstable: This command is meant for debugging. +# # Since: 6.2 ## { 'command': 'x-query-irq', @@ -1691,12 +1691,12 @@ # # Query TCG compiler statistics # -# Features: -# -# @unstable: This command is meant for debugging. -# # Returns: TCG compiler statistics # +# Features: +# +# @unstable: This command is meant for debugging. +# # Since: 6.2 ## { 'command': 'x-query-jit', @@ -1709,12 +1709,12 @@ # # Query NUMA topology information # -# Features: -# -# @unstable: This command is meant for debugging. -# # Returns: topology information # +# Features: +# +# @unstable: This command is meant for debugging. +# # Since: 6.2 ## { 'command': 'x-query-numa', @@ -1726,12 +1726,12 @@ # # Query system ramblock information # -# Features: -# -# @unstable: This command is meant for debugging. -# # Returns: system ramblock information # +# Features: +# +# @unstable: This command is meant for debugging. +# # Since: 6.2 ## { 'command': 'x-query-ramblock', @@ -1743,12 +1743,12 @@ # # Query information on the registered ROMS # -# Features: -# -# @unstable: This command is meant for debugging. -# # Returns: registered ROMs # +# Features: +# +# @unstable: This command is meant for debugging. +# # Since: 6.2 ## { 'command': 'x-query-roms', @@ -1760,12 +1760,12 @@ # # Query information on the USB devices # -# Features: -# -# @unstable: This command is meant for debugging. -# # Returns: USB device information # +# Features: +# +# @unstable: This command is meant for debugging. +# # Since: 6.2 ## { 'command': 'x-query-usb', @@ -1829,12 +1829,12 @@ # # Query information on interrupt controller devices # -# Features: -# -# @unstable: This command is meant for debugging. -# # Returns: Interrupt controller devices information # +# Features: +# +# @unstable: This command is meant for debugging. +# # Since: 9.1 ## { 'command': 'x-query-interrupt-controllers', diff --git a/qapi/misc.json b/qapi/misc.json index 28c641fe2fe..05866837f09 100644 --- a/qapi/misc.json +++ b/qapi/misc.json @@ -209,14 +209,14 @@ # # @cpu-index: The CPU to use for commands that require an implicit CPU # +# Returns: the output of the command as a string +# # Features: # # @savevm-monitor-nodes: If present, HMP command savevm only snapshots # monitor-owned nodes if they have no parents. This allows the # use of 'savevm' with -blockdev. (since 4.2) # -# Returns: the output of the command as a string -# # Since: 0.14 # # .. note:: This command only exists as a stop-gap. Its use is highly diff --git a/qapi/qom.json b/qapi/qom.json index 568b7d4b997..fd88be07e13 100644 --- a/qapi/qom.json +++ b/qapi/qom.json @@ -161,12 +161,12 @@ # @paths: The absolute or partial path for each object, as described # in `qom-get`. # -# Errors: -# - If any path is not valid or is ambiguous -# # Returns: A list where each element is the result for the # corresponding element of @paths. # +# Errors: +# - If any path is not valid or is ambiguous +# # Since 10.1 ## { 'command': 'qom-list-get', diff --git a/qapi/virtio.json b/qapi/virtio.json index 09dd0e6d05a..447fc182625 100644 --- a/qapi/virtio.json +++ b/qapi/virtio.json @@ -28,12 +28,12 @@ # # Return a list of all realized VirtIODevices # -# Features: -# -# @unstable: This command is meant for debugging. -# # Returns: List of gathered VirtIODevices # +# Features: +# +# @unstable: This command is meant for debugging. +# # Since: 7.2 # # .. qmp-example:: @@ -197,12 +197,12 @@ # # @path: Canonical QOM path of the VirtIODevice # -# Features: -# -# @unstable: This command is meant for debugging. -# # Returns: Status of the virtio device # +# Features: +# +# @unstable: This command is meant for debugging. +# # Since: 7.2 # # .. qmp-example:: @@ -566,12 +566,12 @@ # # @queue: VirtQueue index to examine # -# Features: -# -# @unstable: This command is meant for debugging. -# # Returns: Status of the queue # +# Features: +# +# @unstable: This command is meant for debugging. +# # .. 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 @@ -701,12 +701,12 @@ # # @queue: vhost_virtqueue index to examine # -# Features: -# -# @unstable: This command is meant for debugging. -# # Returns: Status of the vhost_virtqueue # +# Features: +# +# @unstable: This command is meant for debugging. +# # Since: 7.2 # # .. qmp-example:: diff --git a/tests/qapi-schema/doc-good.json b/tests/qapi-schema/doc-good.json index 9103fed472e..5b567824280 100644 --- a/tests/qapi-schema/doc-good.json +++ b/tests/qapi-schema/doc-good.json @@ -161,14 +161,14 @@ # @arg2: description starts on the same line # remainder indented differently # -# Features: -# @cmd-feat1: a feature -# @cmd-feat2: another feature -# # Returns: @Object # # Errors: some # +# Features: +# @cmd-feat1: a feature +# @cmd-feat2: another feature +# # .. note:: @arg3 is undocumented # # TODO: frobnicate diff --git a/tests/qapi-schema/doc-good.txt b/tests/qapi-schema/doc-good.txt index ded699dd596..226c3d27a36 100644 --- a/tests/qapi-schema/doc-good.txt +++ b/tests/qapi-schema/doc-good.txt @@ -115,17 +115,17 @@ Command cmd (Since: 2.10) * **arg3** ("boolean") -- Not documented - Features: - * **cmd-feat1** -- a feature - - * **cmd-feat2** -- another feature - Return: "Object" -- "Object" Errors: some + Features: + * **cmd-feat1** -- a feature + + * **cmd-feat2** -- another feature + Note: "arg3" is undocumented -- 2.53.0 ^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [PATCH 5/8] qapi: re-order QAPI doc block sections 2026-03-16 18:26 ` [PATCH 5/8] qapi: re-order QAPI doc block sections John Snow @ 2026-03-20 14:11 ` Markus Armbruster 2026-03-20 18:27 ` John Snow 0 siblings, 1 reply; 29+ messages in thread From: Markus Armbruster @ 2026-03-20 14:11 UTC (permalink / raw) To: John Snow Cc: qemu-devel, Pierrick Bouvier, Lukas Straub, Richard Henderson, Zhao Liu, Jason Wang, Mauro Carvalho Chehab, Alex Bennée, Peter Xu, Eric Blake, Daniel P. Berrangé, Fabiano Rosas, Philippe Mathieu-Daudé, Cédric Le Goater, qemu-block, Marc-André Lureau, Peter Maydell, Michael S. Tsirkin, Stefan Berger, Alex Williamson, Marcel Apfelbaum, Kevin Wolf, Michael Roth, Stefano Garzarella, Stefan Hajnoczi, Igor Mammedov, Jiri Pirko, Yanan Wang, Paolo Bonzini, Kashyap Chamarthy, Hanna Reitz, Ani Sinha John Snow <jsnow@redhat.com> writes: > A forthcoming patch will enforce a rigid source order of QAPI Doc block > sections: > > (1) Intro > (2) Members > (3) Returns > (4) Errors > (5) Features > (6) Details > (7) Since > > This patch specifically ensures the source ordering of items #1-6, with > the positioning of "Since:" left for the following patch as it is a much > bigger patch. It's actually the one after next. Suggest "left for a later patch". > > Signed-off-by: John Snow <jsnow@redhat.com> ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 5/8] qapi: re-order QAPI doc block sections 2026-03-20 14:11 ` Markus Armbruster @ 2026-03-20 18:27 ` John Snow 0 siblings, 0 replies; 29+ messages in thread From: John Snow @ 2026-03-20 18:27 UTC (permalink / raw) To: Markus Armbruster Cc: qemu-devel, Pierrick Bouvier, Lukas Straub, Richard Henderson, Zhao Liu, Jason Wang, Mauro Carvalho Chehab, Alex Bennée, Peter Xu, Eric Blake, Daniel P. Berrangé, Fabiano Rosas, Philippe Mathieu-Daudé, Cédric Le Goater, Qemu-block, Marc-André Lureau, Peter Maydell, Michael S. Tsirkin, Stefan Berger, Alex Williamson, Marcel Apfelbaum, Kevin Wolf, Michael Roth, Stefano Garzarella, Stefan Hajnoczi, Igor Mammedov, Jiri Pirko, Yanan Wang, Paolo Bonzini, Kashyap Chamarthy, Hanna Reitz, Ani Sinha [-- Attachment #1: Type: text/plain, Size: 663 bytes --] On Fri, Mar 20, 2026, 10:11 AM Markus Armbruster <armbru@redhat.com> wrote: > John Snow <jsnow@redhat.com> writes: > > > A forthcoming patch will enforce a rigid source order of QAPI Doc block > > sections: > > > > (1) Intro > > (2) Members > > (3) Returns > > (4) Errors > > (5) Features > > (6) Details > > (7) Since > > > > This patch specifically ensures the source ordering of items #1-6, with > > the positioning of "Since:" left for the following patch as it is a much > > bigger patch. > > It's actually the one after next. Suggest "left for a later patch". > :) > > > > Signed-off-by: John Snow <jsnow@redhat.com> > > [-- Attachment #2: Type: text/html, Size: 1699 bytes --] ^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 6/8] qapi: enforce doc block section ordering 2026-03-16 18:25 [PATCH 0/8] qapi: enforce section ordering John Snow ` (4 preceding siblings ...) 2026-03-16 18:26 ` [PATCH 5/8] qapi: re-order QAPI doc block sections John Snow @ 2026-03-16 18:26 ` John Snow 2026-03-20 14:13 ` Markus Armbruster 2026-03-16 18:26 ` [PATCH 7/8] qapi: re-order 'since' sections to always be last John Snow 2026-03-16 18:26 ` [PATCH 8/8] qapi: enforce strict positioning for "Since:" section John Snow 7 siblings, 1 reply; 29+ messages in thread From: John Snow @ 2026-03-16 18:26 UTC (permalink / raw) To: qemu-devel Cc: Pierrick Bouvier, Lukas Straub, Richard Henderson, Zhao Liu, Jason Wang, Mauro Carvalho Chehab, Alex Bennée, Peter Xu, Eric Blake, Daniel P. Berrangé, Fabiano Rosas, Philippe Mathieu-Daudé, Cédric Le Goater, qemu-block, Marc-André Lureau, Peter Maydell, Michael S. Tsirkin, Stefan Berger, Alex Williamson, Marcel Apfelbaum, Kevin Wolf, John Snow, Michael Roth, Stefano Garzarella, Stefan Hajnoczi, Igor Mammedov, Jiri Pirko, Yanan Wang, Paolo Bonzini, Kashyap Chamarthy, Markus Armbruster, Hanna Reitz, Ani Sinha Ugly hack, gets the job done. Likely many simplifications can be made as a result, but I didn't make any of them. There are some inconsistencies with human-readable vs ENUM_NAMES in error messages in this patch, but it appears to work anyway. Consider this patch more of a rough idea and not anything approximating the kind of code you'd want to see from an Enterprise Linux Senior Software Engineer. Signed-off-by: John Snow <jsnow@redhat.com> --- scripts/qapi/parser.py | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py index 9e8dfc67208..1a7856bf213 100644 --- a/scripts/qapi/parser.py +++ b/scripts/qapi/parser.py @@ -545,19 +545,25 @@ def get_doc(self) -> 'QAPIDoc': self.accept(False) line = self.get_doc_line() have_tagged = False - no_more_tags = False + last_section = QAPIDoc.Kind.INTRO def _tag_check(what: str) -> None: + nonlocal last_section + if what in ('TODO', 'Since'): return - if no_more_tags: + this_section = QAPIDoc.Kind.from_string(what) + if this_section.value < last_section.value: raise QAPIParseError( self, - f"'{what}' section cannot appear after plain " - "paragraphs that follow other tagged sections\n" - "Move this section up above the plain paragraph(s)." + f"'{what}' section cannot appear after " + f"'{last_section!s}' section, please re-order the " + "sections and adjust phrasing as necessary to ensure " + "consistent documentation flow between the source " + "code and the rendered HTML manual" ) + last_section = this_section while line is not None: # Blank lines @@ -571,7 +577,7 @@ def _tag_check(what: str) -> None: if doc.features: raise QAPIParseError( self, "duplicated 'Features:' line") - _tag_check("Features") + _tag_check("FEATURE") self.accept(False) line = self.get_doc_line() while line == '': @@ -589,7 +595,7 @@ def _tag_check(what: str) -> None: self, 'feature descriptions expected') have_tagged = True elif line == 'Details:': - _tag_check("Details") + _tag_check("DETAILS") self.accept(False) line = self.get_doc_line() while line == '': @@ -598,6 +604,7 @@ def _tag_check(what: str) -> None: have_tagged = True elif match := self._match_at_name_colon(line): # description + _tag_check("MEMBER") if have_tagged: raise QAPIParseError( self, @@ -654,13 +661,10 @@ def _tag_check(what: str) -> None: line = self.get_doc_indented(doc) have_tagged = True else: - # plain paragraph - if have_tagged: - no_more_tags = True - # Paragraphs before tagged sections are "intro" paragraphs. # Any appearing after are "detail" paragraphs. intro = not have_tagged + _tag_check("INTRO" if intro else "DETAILS") doc.ensure_untagged_section(self.info, intro) doc.append_line(line) line = self.get_doc_paragraph(doc) @@ -703,14 +707,17 @@ class QAPIDoc: """ class Kind(enum.Enum): + # The order here is the order in which sections must appear in + # source code; with the exception of 'TODO' which may appear + # anywhere but is treated as a comment. INTRO = 0 MEMBER = 1 - FEATURE = 2 - RETURNS = 3 - ERRORS = 4 - SINCE = 5 + RETURNS = 2 + ERRORS = 3 + FEATURE = 4 + DETAILS = 5 TODO = 6 - DETAILS = 7 + SINCE = 7 @staticmethod def from_string(kind: str) -> 'QAPIDoc.Kind': -- 2.53.0 ^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [PATCH 6/8] qapi: enforce doc block section ordering 2026-03-16 18:26 ` [PATCH 6/8] qapi: enforce doc block section ordering John Snow @ 2026-03-20 14:13 ` Markus Armbruster 2026-03-20 18:28 ` John Snow 0 siblings, 1 reply; 29+ messages in thread From: Markus Armbruster @ 2026-03-20 14:13 UTC (permalink / raw) To: John Snow Cc: qemu-devel, Pierrick Bouvier, Lukas Straub, Richard Henderson, Zhao Liu, Jason Wang, Mauro Carvalho Chehab, Alex Bennée, Peter Xu, Eric Blake, Daniel P. Berrangé, Fabiano Rosas, Philippe Mathieu-Daudé, Cédric Le Goater, qemu-block, Marc-André Lureau, Peter Maydell, Michael S. Tsirkin, Stefan Berger, Alex Williamson, Marcel Apfelbaum, Kevin Wolf, Michael Roth, Stefano Garzarella, Stefan Hajnoczi, Igor Mammedov, Jiri Pirko, Yanan Wang, Paolo Bonzini, Kashyap Chamarthy, Hanna Reitz, Ani Sinha John Snow <jsnow@redhat.com> writes: > Ugly hack, gets the job done. Likely many simplifications can be made as > a result, but I didn't make any of them. There are some inconsistencies > with human-readable vs ENUM_NAMES in error messages in this patch, but > it appears to work anyway. > > Consider this patch more of a rough idea and not anything approximating > the kind of code you'd want to see from an Enterprise Linux Senior > Software Engineer. > > Signed-off-by: John Snow <jsnow@redhat.com> > --- > scripts/qapi/parser.py | 39 +++++++++++++++++++++++---------------- > 1 file changed, 23 insertions(+), 16 deletions(-) Missing: update to docs/devel/qapi-code-gen.rst. Suggest to put in a FIXME, so we don't forget. Missing: test coverage. ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 6/8] qapi: enforce doc block section ordering 2026-03-20 14:13 ` Markus Armbruster @ 2026-03-20 18:28 ` John Snow 2026-03-23 8:56 ` Markus Armbruster 0 siblings, 1 reply; 29+ messages in thread From: John Snow @ 2026-03-20 18:28 UTC (permalink / raw) To: Markus Armbruster Cc: qemu-devel, Pierrick Bouvier, Lukas Straub, Richard Henderson, Zhao Liu, Jason Wang, Mauro Carvalho Chehab, Alex Bennée, Peter Xu, Eric Blake, Daniel P. Berrangé, Fabiano Rosas, Philippe Mathieu-Daudé, Cédric Le Goater, Qemu-block, Marc-André Lureau, Peter Maydell, Michael S. Tsirkin, Stefan Berger, Alex Williamson, Marcel Apfelbaum, Kevin Wolf, Michael Roth, Stefano Garzarella, Stefan Hajnoczi, Igor Mammedov, Jiri Pirko, Yanan Wang, Paolo Bonzini, Kashyap Chamarthy, Hanna Reitz, Ani Sinha [-- Attachment #1: Type: text/plain, Size: 1002 bytes --] On Fri, Mar 20, 2026, 10:13 AM Markus Armbruster <armbru@redhat.com> wrote: > John Snow <jsnow@redhat.com> writes: > > > Ugly hack, gets the job done. Likely many simplifications can be made as > > a result, but I didn't make any of them. There are some inconsistencies > > with human-readable vs ENUM_NAMES in error messages in this patch, but > > it appears to work anyway. > > > > Consider this patch more of a rough idea and not anything approximating > > the kind of code you'd want to see from an Enterprise Linux Senior > > Software Engineer. > > > > Signed-off-by: John Snow <jsnow@redhat.com> > > --- > > scripts/qapi/parser.py | 39 +++++++++++++++++++++++---------------- > > 1 file changed, 23 insertions(+), 16 deletions(-) > > Missing: update to docs/devel/qapi-code-gen.rst. Suggest to put in a > FIXME, so we don't forget. > ACK > Missing: test coverage. > Do we need to test every possible sequence, or just some characteristic examples...? > [-- Attachment #2: Type: text/html, Size: 2246 bytes --] ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 6/8] qapi: enforce doc block section ordering 2026-03-20 18:28 ` John Snow @ 2026-03-23 8:56 ` Markus Armbruster 0 siblings, 0 replies; 29+ messages in thread From: Markus Armbruster @ 2026-03-23 8:56 UTC (permalink / raw) To: John Snow Cc: qemu-devel, Pierrick Bouvier, Lukas Straub, Richard Henderson, Zhao Liu, Jason Wang, Mauro Carvalho Chehab, Alex Bennée, Peter Xu, Eric Blake, Daniel P. Berrangé, Fabiano Rosas, Philippe Mathieu-Daudé, Cédric Le Goater, Qemu-block, Marc-André Lureau, Peter Maydell, Michael S. Tsirkin, Stefan Berger, Alex Williamson, Marcel Apfelbaum, Kevin Wolf, Michael Roth, Stefano Garzarella, Stefan Hajnoczi, Igor Mammedov, Jiri Pirko, Yanan Wang, Paolo Bonzini, Kashyap Chamarthy, Hanna Reitz, Ani Sinha John Snow <jsnow@redhat.com> writes: > On Fri, Mar 20, 2026, 10:13 AM Markus Armbruster <armbru@redhat.com> wrote: > >> John Snow <jsnow@redhat.com> writes: >> >> > Ugly hack, gets the job done. Likely many simplifications can be made as >> > a result, but I didn't make any of them. There are some inconsistencies >> > with human-readable vs ENUM_NAMES in error messages in this patch, but >> > it appears to work anyway. >> > >> > Consider this patch more of a rough idea and not anything approximating >> > the kind of code you'd want to see from an Enterprise Linux Senior >> > Software Engineer. >> > >> > Signed-off-by: John Snow <jsnow@redhat.com> >> > --- >> > scripts/qapi/parser.py | 39 +++++++++++++++++++++++---------------- >> > 1 file changed, 23 insertions(+), 16 deletions(-) >> >> Missing: update to docs/devel/qapi-code-gen.rst. Suggest to put in a >> FIXME, so we don't forget. >> > > ACK > > >> Missing: test coverage. >> > > Do we need to test every possible sequence, or just some characteristic > examples...? Let's start with characteristic examples. ^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 7/8] qapi: re-order 'since' sections to always be last 2026-03-16 18:25 [PATCH 0/8] qapi: enforce section ordering John Snow ` (5 preceding siblings ...) 2026-03-16 18:26 ` [PATCH 6/8] qapi: enforce doc block section ordering John Snow @ 2026-03-16 18:26 ` John Snow 2026-03-20 14:23 ` Markus Armbruster 2026-03-16 18:26 ` [PATCH 8/8] qapi: enforce strict positioning for "Since:" section John Snow 7 siblings, 1 reply; 29+ messages in thread From: John Snow @ 2026-03-16 18:26 UTC (permalink / raw) To: qemu-devel Cc: Pierrick Bouvier, Lukas Straub, Richard Henderson, Zhao Liu, Jason Wang, Mauro Carvalho Chehab, Alex Bennée, Peter Xu, Eric Blake, Daniel P. Berrangé, Fabiano Rosas, Philippe Mathieu-Daudé, Cédric Le Goater, qemu-block, Marc-André Lureau, Peter Maydell, Michael S. Tsirkin, Stefan Berger, Alex Williamson, Marcel Apfelbaum, Kevin Wolf, John Snow, Michael Roth, Stefano Garzarella, Stefan Hajnoczi, Igor Mammedov, Jiri Pirko, Yanan Wang, Paolo Bonzini, Kashyap Chamarthy, Markus Armbruster, Hanna Reitz, Ani Sinha Note that with "Since" being moved to the last position, we open up a good many new cases of ambiguos intro-vs-details text which must be corrected with "Details:" tags. This patch doesn't only add these markers where it would definitively impact inlining - it adds them to *any* doc block that has more than one paragraph of plaintext and no other distinguishing features (members, features, errors, returns). It may well be the case that not every last one of these *needs* to be amended in this way, but this is the broad coverage shotgun approach that demonstrates which places in the code may cause footguns with regards to automated stub insertions of members/arguments/etc, returns, or inlining order ambiguities. Signed-off-by: John Snow <jsnow@redhat.com> --- docs/interop/firmware.json | 4 +- docs/interop/vhost-user.json | 3 +- qapi/accelerator.json | 8 +-- qapi/acpi.json | 8 ++- qapi/block-core.json | 136 ++++++++++++++++++----------------- qapi/block.json | 40 +++++------ qapi/char.json | 36 +++++----- qapi/control.json | 14 ++-- qapi/dump.json | 16 ++--- qapi/machine-s390x.json | 8 +-- qapi/machine.json | 86 ++++++++++++---------- qapi/migration.json | 94 ++++++++++++------------ qapi/misc-arm.json | 6 +- qapi/misc-i386.json | 40 ++++++----- qapi/misc.json | 64 +++++++++-------- qapi/net.json | 40 +++++------ qapi/pci.json | 4 +- qapi/qdev.json | 12 ++-- qapi/qom.json | 20 +++--- qapi/replay.json | 16 +++-- qapi/rocker.json | 16 ++--- qapi/run-state.json | 66 ++++++++++------- qapi/tpm.json | 12 ++-- qapi/trace.json | 8 +-- qapi/transaction.json | 4 +- qapi/ui.json | 76 +++++++++++--------- qapi/vfio.json | 4 +- qapi/virtio.json | 20 +++--- 28 files changed, 463 insertions(+), 398 deletions(-) diff --git a/docs/interop/firmware.json b/docs/interop/firmware.json index 421bee0e5ed..bdfb6ccb717 100644 --- a/docs/interop/firmware.json +++ b/docs/interop/firmware.json @@ -551,8 +551,6 @@ # debugging purposes only, and management software shall # explicitly ignore it. # -# Since: 3.0 -# # .. qmp-example:: # # { @@ -752,6 +750,8 @@ # "-D DEBUG_PRINT_ERROR_LEVEL=0x80000000" # ] # } +# +# Since: 3.0 ## { 'struct' : 'Firmware', 'data' : { 'description' : 'str', diff --git a/docs/interop/vhost-user.json b/docs/interop/vhost-user.json index 29c84e86e55..fbcf409838d 100644 --- a/docs/interop/vhost-user.json +++ b/docs/interop/vhost-user.json @@ -264,8 +264,6 @@ # development and debugging purposes only, and management software # shall explicitly ignore it. # -# Since: 4.0 -# # .. qmp-example: # # { @@ -278,6 +276,7 @@ # ] # } # +# Since: 4.0 ## { 'struct' : 'VhostUserBackend', diff --git a/qapi/accelerator.json b/qapi/accelerator.json index d333a772384..5624b5d88b7 100644 --- a/qapi/accelerator.json +++ b/qapi/accelerator.json @@ -29,12 +29,12 @@ # # Return information about KVM acceleration # -# Since: 0.14 -# # .. qmp-example:: # # -> { "execute": "query-kvm" } # <- { "return": { "enabled": true, "present": true } } +# +# Since: 0.14 ## { 'command': 'query-kvm', 'returns': 'KvmInfo' } @@ -101,11 +101,11 @@ # # Returns: @AcceleratorInfo # -# Since: 10.2.0 -# # .. qmp-example:: # # -> { "execute": "query-accelerators" } # <- { "return": { "enabled": "mshv", "present": ["kvm", "mshv", "qtest", "tcg"] } } +# +# Since: 10.2.0 ## { 'command': 'query-accelerators', 'returns': 'AcceleratorInfo' } diff --git a/qapi/acpi.json b/qapi/acpi.json index 906b3687a55..8dd87fd8f22 100644 --- a/qapi/acpi.json +++ b/qapi/acpi.json @@ -111,7 +111,7 @@ # Return a list of `ACPIOSTInfo` for devices that support status # reporting via ACPI _OST method. # -# Since: 2.1 +# Details: # # .. qmp-example:: # @@ -121,6 +121,8 @@ # { "slot": "2", "slot-type": "DIMM", "source": 0, "status": 0}, # { "slot": "3", "slot-type": "DIMM", "source": 0, "status": 0} # ]} +# +# Since: 2.1 ## { 'command': 'query-acpi-ospm-status', 'returns': ['ACPIOSTInfo'] } @@ -131,14 +133,14 @@ # # @info: OSPM Status Indication # -# Since: 2.1 -# # .. qmp-example:: # # <- { "event": "ACPI_DEVICE_OST", # "data": { "info": { "device": "d1", "slot": "0", # "slot-type": "DIMM", "source": 1, "status": 0 } }, # "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } +# +# Since: 2.1 ## { 'event': 'ACPI_DEVICE_OST', 'data': { 'info': 'ACPIOSTInfo' } } diff --git a/qapi/block-core.json b/qapi/block-core.json index dc97bcb9b66..a979b79fdc2 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -862,8 +862,6 @@ # Returns: a list describing each virtual block device. Filter nodes # that were created implicitly are skipped over. # -# Since: 0.14 -# # .. qmp-example:: # # -> { "execute": "query-block" } @@ -947,6 +945,8 @@ # } # ] # } +# +# Since: 0.14 ## { 'command': 'query-block', 'returns': ['BlockInfo'], 'data': { '*flat': 'bool' }, @@ -1267,8 +1267,6 @@ # # Returns: A list of statistics for each virtual block device. # -# Since: 0.14 -# # .. qmp-example:: # # -> { "execute": "query-blockstats" } @@ -1370,6 +1368,8 @@ # } # ] # } +# +# Since: 0.14 ## { 'command': 'query-blockstats', 'data': { '*query-nodes': 'bool' }, @@ -1560,13 +1560,13 @@ # Errors: # - If @device is not a valid block device, DeviceNotFound # -# Since: 0.14 -# # .. qmp-example:: # # -> { "execute": "block_resize", # "arguments": { "device": "scratch", "size": 1073741824 } } # <- { "return": {} } +# +# Since: 0.14 ## { 'command': 'block_resize', 'data': { '*device': 'str', @@ -1788,8 +1788,6 @@ # Errors: # - If @device is not a valid block device, DeviceNotFound # -# Since: 0.14 -# # .. qmp-example:: # # -> { "execute": "blockdev-snapshot-sync", @@ -1798,6 +1796,8 @@ # "/some/place/my-image", # "format": "qcow2" } } # <- { "return": {} } +# +# Since: 0.14 ## { 'command': 'blockdev-snapshot-sync', 'data': 'BlockdevSnapshotSync', @@ -1820,8 +1820,6 @@ # backing file of a destination of a `blockdev-mirror`. # (since 5.0) # -# Since: 2.5 -# # .. qmp-example:: # # -> { "execute": "blockdev-add", @@ -1837,6 +1835,8 @@ # "arguments": { "node": "ide-hd0", # "overlay": "node1534" } } # <- { "return": {} } +# +# Since: 2.5 ## { 'command': 'blockdev-snapshot', 'data': 'BlockdevSnapshot', @@ -1963,14 +1963,14 @@ # @deprecated: Members @base and @top are deprecated. Use @base-node # and @top-node instead. # -# Since: 1.3 -# # .. qmp-example:: # # -> { "execute": "block-commit", # "arguments": { "device": "virtio0", # "top": "/tmp/snap1.qcow2" } } # <- { "return": {} } +# +# Since: 1.3 ## { 'command': 'block-commit', 'data': { '*job-id': 'str', 'device': 'str', '*base-node': 'str', @@ -2001,8 +2001,6 @@ # @deprecated: This command is deprecated. Use `blockdev-backup` # instead. # -# Since: 1.6 -# # .. qmp-example:: # # -> { "execute": "drive-backup", @@ -2010,6 +2008,8 @@ # "sync": "full", # "target": "backup.img" } } # <- { "return": {} } +# +# Since: 1.6 ## { 'command': 'drive-backup', 'boxed': true, 'data': 'DriveBackup', 'features': ['deprecated'], @@ -2027,8 +2027,6 @@ # Errors: # - If @device is not a valid block device, DeviceNotFound # -# Since: 2.3 -# # .. qmp-example:: # # -> { "execute": "blockdev-backup", @@ -2036,6 +2034,8 @@ # "sync": "full", # "target": "tgt-id" } } # <- { "return": {} } +# +# Since: 2.3 ## { 'command': 'blockdev-backup', 'boxed': true, 'data': 'BlockdevBackup', @@ -2049,8 +2049,6 @@ # @flat: Omit the nested data about backing image ("backing-image" # key) if true. Default is false (Since 5.0) # -# Since: 2.0 -# # .. qmp-example:: # # -> { "execute": "query-named-block-nodes" } @@ -2099,6 +2097,8 @@ # "virtual-size":2048000 # } # } } ] } +# +# Since: 2.0 ## { 'command': 'query-named-block-nodes', 'returns': [ 'BlockDeviceInfo' ], @@ -2230,8 +2230,6 @@ # Errors: # - If @device is not a valid block device, GenericError # -# Since: 1.3 -# # .. qmp-example:: # # -> { "execute": "drive-mirror", @@ -2240,6 +2238,8 @@ # "sync": "full", # "format": "qcow2" } } # <- { "return": {} } +# +# Since: 1.3 ## { 'command': 'drive-mirror', 'boxed': true, 'data': 'DriveMirror', @@ -2407,13 +2407,13 @@ # - If @node is not a valid block device or node, DeviceNotFound # - If @name is already taken, GenericError # -# Since: 2.4 -# # .. qmp-example:: # # -> { "execute": "block-dirty-bitmap-add", # "arguments": { "node": "drive0", "name": "bitmap0" } } # <- { "return": {} } +# +# Since: 2.4 ## { 'command': 'block-dirty-bitmap-add', 'data': 'BlockDirtyBitmapAdd', @@ -2431,13 +2431,13 @@ # - If @name is not found, GenericError # - if @name is frozen by an operation, GenericError # -# Since: 2.4 -# # .. qmp-example:: # # -> { "execute": "block-dirty-bitmap-remove", # "arguments": { "node": "drive0", "name": "bitmap0" } } # <- { "return": {} } +# +# Since: 2.4 ## { 'command': 'block-dirty-bitmap-remove', 'data': 'BlockDirtyBitmap', @@ -2454,13 +2454,13 @@ # - If @node is not a valid block device, DeviceNotFound # - If @name is not found, GenericError # -# Since: 2.4 -# # .. qmp-example:: # # -> { "execute": "block-dirty-bitmap-clear", # "arguments": { "node": "drive0", "name": "bitmap0" } } # <- { "return": {} } +# +# Since: 2.4 ## { 'command': 'block-dirty-bitmap-clear', 'data': 'BlockDirtyBitmap', @@ -2475,13 +2475,13 @@ # - If @node is not a valid block device, DeviceNotFound # - If @name is not found, GenericError # -# Since: 4.0 -# # .. qmp-example:: # # -> { "execute": "block-dirty-bitmap-enable", # "arguments": { "node": "drive0", "name": "bitmap0" } } # <- { "return": {} } +# +# Since: 4.0 ## { 'command': 'block-dirty-bitmap-enable', 'data': 'BlockDirtyBitmap', @@ -2496,13 +2496,13 @@ # - If @node is not a valid block device, DeviceNotFound # - If @name is not found, GenericError # -# Since: 4.0 -# # .. qmp-example:: # # -> { "execute": "block-dirty-bitmap-disable", # "arguments": { "node": "drive0", "name": "bitmap0" } } # <- { "return": {} } +# +# Since: 4.0 ## { 'command': 'block-dirty-bitmap-disable', 'data': 'BlockDirtyBitmap', @@ -2528,14 +2528,14 @@ # - If any of the bitmaps have different sizes or granularities, # GenericError # -# Since: 4.0 -# # .. qmp-example:: # # -> { "execute": "block-dirty-bitmap-merge", # "arguments": { "node": "drive0", "target": "bitmap0", # "bitmaps": ["bitmap1"] } } # <- { "return": {} } +# +# Since: 4.0 ## { 'command': 'block-dirty-bitmap-merge', 'data': 'BlockDirtyBitmapMerge', @@ -2637,8 +2637,6 @@ # mirror. Setting this to true when the destination is not # actually all zero can corrupt the destination. (Since 10.1) # -# Since: 2.6 -# # .. qmp-example:: # # -> { "execute": "blockdev-mirror", @@ -2646,6 +2644,8 @@ # "target": "target0", # "sync": "full" } } # <- { "return": {} } +# +# Since: 2.6 ## { 'command': 'blockdev-mirror', 'data': { '*job-id': 'str', 'device': 'str', 'target': 'str', @@ -2962,14 +2962,14 @@ # Errors: # - If @device does not exist, DeviceNotFound. # -# Since: 1.1 -# # .. qmp-example:: # # -> { "execute": "block-stream", # "arguments": { "device": "virtio0", # "base": "/tmp/master.qcow2" } } # <- { "return": {} } +# +# Since: 1.1 ## { 'command': 'block-stream', 'data': { '*job-id': 'str', 'device': 'str', '*base': 'str', @@ -4958,7 +4958,7 @@ # # Creates a new block device. # -# Since: 2.9 +# Details: # # .. qmp-example:: # @@ -4999,6 +4999,8 @@ # } # # <- { "return": {} } +# +# Since: 2.9 ## { 'command': 'blockdev-add', 'data': 'BlockdevOptions', 'boxed': true, 'allow-preconfig': true } @@ -5062,8 +5064,6 @@ # # @node-name: Name of the graph node to delete. # -# Since: 2.9 -# # .. qmp-example:: # # -> { "execute": "blockdev-add", @@ -5082,6 +5082,8 @@ # "arguments": { "node-name": "node0" } # } # <- { "return": {} } +# +# Since: 2.9 ## { 'command': 'blockdev-del', 'data': { 'node-name': 'str' }, 'allow-preconfig': true } @@ -5102,8 +5104,6 @@ # @active: true if the nodes should be active when the command returns # success, false if they should be inactive. # -# Since: 10.0 -# # .. qmp-example:: # # -> { "execute": "blockdev-set-active", @@ -5113,6 +5113,8 @@ # } # } # <- { "return": {} } +# +# Since: 10.0 ## { 'command': 'blockdev-set-active', 'data': { '*node-name': 'str', 'active': 'bool' }, @@ -5796,8 +5798,6 @@ # # .. note:: This event is rate-limited, except if action is "stop". # -# Since: 0.13 -# # .. qmp-example:: # # <- { "event": "BLOCK_IO_ERROR", @@ -5808,6 +5808,8 @@ # "action": "stop", # "reason": "No space left on device" }, # "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } +# +# Since: 0.13 ## { 'event': 'BLOCK_IO_ERROR', 'data': { 'qom-path': 'str', 'device': 'str', '*node-name': 'str', @@ -5837,8 +5839,6 @@ # other than that streaming has failed and clients should not try # to interpret the error string # -# Since: 1.1 -# # .. qmp-example:: # # <- { "event": "BLOCK_JOB_COMPLETED", @@ -5846,6 +5846,8 @@ # "len": 10737418240, "offset": 10737418240, # "speed": 0 }, # "timestamp": { "seconds": 1267061043, "microseconds": 959568 } } +# +# Since: 1.1 ## { 'event': 'BLOCK_JOB_COMPLETED', 'data': { 'type' : 'JobType', @@ -5872,8 +5874,6 @@ # # @speed: rate limit, bytes per second # -# Since: 1.1 -# # .. qmp-example:: # # <- { "event": "BLOCK_JOB_CANCELLED", @@ -5881,6 +5881,8 @@ # "len": 10737418240, "offset": 134217728, # "speed": 0 }, # "timestamp": { "seconds": 1267061043, "microseconds": 959568 } } +# +# Since: 1.1 ## { 'event': 'BLOCK_JOB_CANCELLED', 'data': { 'type' : 'JobType', @@ -5901,8 +5903,6 @@ # # @action: action that has been taken # -# Since: 1.3 -# # .. qmp-example:: # # <- { "event": "BLOCK_JOB_ERROR", @@ -5910,6 +5910,8 @@ # "operation": "write", # "action": "stop" }, # "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } +# +# Since: 1.3 ## { 'event': 'BLOCK_JOB_ERROR', 'data': { 'device' : 'str', @@ -5936,14 +5938,14 @@ # .. note:: The "ready to complete" status is always reset by a # `BLOCK_JOB_ERROR` event. # -# Since: 1.3 -# # .. qmp-example:: # # <- { "event": "BLOCK_JOB_READY", # "data": { "device": "drive0", "type": "mirror", "speed": 0, # "len": 2097152, "offset": 2097152 }, # "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } +# +# Since: 1.3 ## { 'event': 'BLOCK_JOB_READY', 'data': { 'type' : 'JobType', @@ -5964,13 +5966,13 @@ # # @id: The job identifier. # -# Since: 2.12 -# # .. qmp-example:: # # <- { "event": "BLOCK_JOB_PENDING", # "data": { "type": "mirror", "id": "backup_1" }, # "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } +# +# Since: 2.12 ## { 'event': 'BLOCK_JOB_PENDING', 'data': { 'type' : 'JobType', @@ -6038,14 +6040,14 @@ # @write-threshold: configured threshold for the block device, bytes. # Use 0 to disable the threshold. # -# Since: 2.3 -# # .. qmp-example:: # # -> { "execute": "block-set-write-threshold", # "arguments": { "node-name": "mydev", # "write-threshold": 17179869184 } } # <- { "return": {} } +# +# Since: 2.3 ## { 'command': 'block-set-write-threshold', 'data': { 'node-name': 'str', 'write-threshold': 'uint64' }, @@ -6079,8 +6081,6 @@ # 'children' list of `BlockdevOptionsQuorum`, as returned by # .bdrv_refresh_filename(). # -# Since: 2.7 -# # .. qmp-example:: # :title: Add a new node to a quorum # @@ -6103,6 +6103,8 @@ # "arguments": { "parent": "disk1", # "child": "children.1" } } # <- { "return": {} } +# +# Since: 2.7 ## { 'command': 'x-blockdev-change', 'data' : { 'parent': 'str', @@ -6131,8 +6133,6 @@ # @unstable: This command is experimental and intended for test cases # that need control over IOThreads only. # -# Since: 2.12 -# # .. qmp-example:: # :title: Move a node into an IOThread # @@ -6148,6 +6148,8 @@ # "arguments": { "node-name": "disk1", # "iothread": null } } # <- { "return": {} } +# +# Since: 2.12 ## { 'command': 'x-blockdev-set-iothread', 'data' : { 'node-name': 'str', @@ -6185,13 +6187,13 @@ # # .. note:: This event is rate-limited. # -# Since: 2.0 -# # .. qmp-example:: # # <- { "event": "QUORUM_FAILURE", # "data": { "reference": "usr1", "sector-num": 345435, "sectors-count": 5 }, # "timestamp": { "seconds": 1344522075, "microseconds": 745528 } } +# +# Since: 2.0 ## { 'event': 'QUORUM_FAILURE', 'data': { 'reference': 'str', 'sector-num': 'int', 'sectors-count': 'int' } } @@ -6216,8 +6218,6 @@ # # .. note:: This event is rate-limited. # -# Since: 2.0 -# # .. qmp-example:: # :title: Read operation # @@ -6233,6 +6233,8 @@ # "data": { "node-name": "node0", "sector-num": 0, "sectors-count": 2097120, # "type": "flush", "error": "Broken pipe" }, # "timestamp": { "seconds": 1456406829, "microseconds": 291763 } } +# +# Since: 2.0 ## { 'event': 'QUORUM_REPORT_BAD', 'data': { 'type': 'QuorumOpType', '*error': 'str', 'node-name': 'str', @@ -6269,8 +6271,6 @@ # .. note:: Only some image formats such as qcow2 and rbd support # internal snapshots. # -# Since: 1.7 -# # .. qmp-example:: # # -> { "execute": "blockdev-snapshot-internal-sync", @@ -6278,6 +6278,8 @@ # "name": "snapshot0" } # } # <- { "return": {} } +# +# Since: 1.7 ## { 'command': 'blockdev-snapshot-internal-sync', 'data': 'BlockdevSnapshotInternal', @@ -6305,8 +6307,6 @@ # GenericError # - If @id and @name are both not specified, GenericError # -# Since: 1.7 -# # .. qmp-example:: # # -> { "execute": "blockdev-snapshot-delete-internal-sync", @@ -6324,6 +6324,8 @@ # "icount": 220414 # } # } +# +# Since: 1.7 ## { 'command': 'blockdev-snapshot-delete-internal-sync', 'data': { 'device': 'str', '*id': 'str', '*name': 'str'}, diff --git a/qapi/block.json b/qapi/block.json index 54bc0056318..a29907e0be1 100644 --- a/qapi/block.json +++ b/qapi/block.json @@ -118,12 +118,12 @@ # # .. note:: Ejecting a device with no media results in success. # -# Since: 0.14 -# # .. qmp-example:: # # -> { "execute": "eject", "arguments": { "id": "ide1-0-1" } } # <- { "return": {} } +# +# Since: 0.14 ## { 'command': 'eject', 'data': { '*device': { 'type': 'str', 'features': [ 'deprecated' ] }, @@ -162,8 +162,6 @@ # # @deprecated: Member @device is deprecated. Use @id instead. # -# Since: 2.5 -# # .. qmp-example:: # # -> { "execute": "blockdev-open-tray", @@ -177,6 +175,8 @@ # "tray-open": true } } # # <- { "return": {} } +# +# Since: 2.5 ## { 'command': 'blockdev-open-tray', 'data': { '*device': { 'type': 'str', 'features': [ 'deprecated' ] }, @@ -200,8 +200,6 @@ # # @deprecated: Member @device is deprecated. Use @id instead. # -# Since: 2.5 -# # .. qmp-example:: # # -> { "execute": "blockdev-close-tray", @@ -215,6 +213,8 @@ # "tray-open": false } } # # <- { "return": {} } +# +# Since: 2.5 ## { 'command': 'blockdev-close-tray', 'data': { '*device': { 'type': 'str', 'features': [ 'deprecated' ] }, @@ -232,8 +232,6 @@ # # @id: The name or QOM path of the guest device # -# Since: 2.12 -# # .. qmp-example:: # # -> { "execute": "blockdev-remove-medium", @@ -258,6 +256,8 @@ # "arguments": { "id": "ide0-1-0" } } # # <- { "return": {} } +# +# Since: 2.12 ## { 'command': 'blockdev-remove-medium', 'data': { 'id': 'str' } } @@ -273,8 +273,6 @@ # # @node-name: name of a node in the block driver state graph # -# Since: 2.12 -# # .. qmp-example:: # # -> { "execute": "blockdev-add", @@ -290,6 +288,8 @@ # "node-name": "node0" } } # # <- { "return": {} } +# +# Since: 2.12 ## { 'command': 'blockdev-insert-medium', 'data': { 'id': 'str', @@ -343,8 +343,6 @@ # # @deprecated: Member @device is deprecated. Use @id instead. # -# Since: 2.5 -# # .. qmp-example:: # :title: Change a removable medium # @@ -374,6 +372,8 @@ # "read-only-mode": "read-only" } } # # <- { "return": {} } +# +# Since: 2.5 ## { 'command': 'blockdev-change-medium', 'data': { '*device': { 'type': 'str', 'features': [ 'deprecated' ] }, @@ -398,8 +398,6 @@ # @tray-open: true if the tray has been opened or false if it has been # closed # -# Since: 1.1 -# # .. qmp-example:: # # <- { "event": "DEVICE_TRAY_MOVED", @@ -408,6 +406,8 @@ # "tray-open": true # }, # "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } +# +# Since: 1.1 ## { 'event': 'DEVICE_TRAY_MOVED', 'data': { 'device': 'str', 'id': 'str', 'tray-open': 'bool' } } @@ -422,8 +422,6 @@ # # @connected: true if the PR manager is connected to a backend # -# Since: 3.0 -# # .. qmp-example:: # # <- { "event": "PR_MANAGER_STATUS_CHANGED", @@ -431,6 +429,8 @@ # "connected": true # }, # "timestamp": { "seconds": 1519840375, "microseconds": 450486 } } +# +# Since: 3.0 ## { 'event': 'PR_MANAGER_STATUS_CHANGED', 'data': { 'id': 'str', 'connected': 'bool' } } @@ -464,8 +464,6 @@ # Errors: # - If @device is not a valid block device, DeviceNotFound # -# Since: 1.1 -# # .. qmp-example:: # # -> { "execute": "block_set_io_throttle", @@ -505,6 +503,8 @@ # "bps_max_length": 60, # "iops_size": 0 } } # <- { "return": {} } +# +# Since: 1.1 ## { 'command': 'block_set_io_throttle', 'boxed': true, 'data': 'BlockIOThrottle', @@ -546,8 +546,6 @@ # Errors: # - if device is not found or any boundary arrays are invalid. # -# Since: 4.0 -# # .. qmp-example:: # :annotated: # @@ -594,6 +592,8 @@ # -> { "execute": "block-latency-histogram-set", # "arguments": { "id": "drive0" } } # <- { "return": {} } +# +# Since: 4.0 ## { 'command': 'block-latency-histogram-set', 'data': {'id': 'str', diff --git a/qapi/char.json b/qapi/char.json index a4abafa6803..74408cc6d39 100644 --- a/qapi/char.json +++ b/qapi/char.json @@ -38,8 +38,6 @@ # # Return information about current character devices. # -# Since: 0.14 -# # .. qmp-example:: # # -> { "execute": "query-chardev" } @@ -62,6 +60,8 @@ # } # ] # } +# +# Since: 0.14 ## { 'command': 'query-chardev', 'returns': ['ChardevInfo'], 'allow-preconfig': true } @@ -82,8 +82,6 @@ # # Return information about character device backends. # -# Since: 2.0 -# # .. qmp-example:: # # -> { "execute": "query-chardev-backends" } @@ -103,6 +101,8 @@ # } # ] # } +# +# Since: 2.0 ## { 'command': 'query-chardev-backends', 'returns': ['ChardevBackendInfo'] } @@ -137,8 +137,6 @@ # - data itself is always Unicode regardless of format, like any # other string. # -# Since: 1.4 -# # .. qmp-example:: # # -> { "execute": "ringbuf-write", @@ -146,6 +144,8 @@ # "data": "abcdefgh", # "format": "utf8" } } # <- { "return": {} } +# +# Since: 1.4 ## { 'command': 'ringbuf-write', 'data': { 'device': 'str', @@ -173,8 +173,6 @@ # # Returns: data read from the device # -# Since: 1.4 -# # .. qmp-example:: # # -> { "execute": "ringbuf-read", @@ -182,6 +180,8 @@ # "size": 1000, # "format": "utf8" } } # <- { "return": "abcdefgh" } +# +# Since: 1.4 ## { 'command': 'ringbuf-read', 'data': {'device': 'str', 'size': 'int', '*format': 'DataFormat'}, @@ -761,8 +761,6 @@ # # @backend: backend type and parameters # -# Since: 1.4 -# # .. qmp-example:: # # -> { "execute" : "chardev-add", @@ -784,6 +782,8 @@ # "arguments" : { "id" : "baz", # "backend" : { "type" : "pty", "data" : {} } } } # <- { "return": { "pty" : "/dev/pty/42" } } +# +# Since: 1.4 ## { 'command': 'chardev-add', 'data': { 'id': 'str', @@ -799,8 +799,6 @@ # # @backend: new backend type and parameters # -# Since: 2.10 -# # .. qmp-example:: # # -> { "execute" : "chardev-change", @@ -825,6 +823,8 @@ # "server" : true, # "wait" : false }}}} # <- {"return": {}} +# +# Since: 2.10 ## { 'command': 'chardev-change', 'data': { 'id': 'str', @@ -838,12 +838,12 @@ # # @id: the chardev's ID, must exist and not be in use # -# Since: 1.4 -# # .. qmp-example:: # # -> { "execute": "chardev-remove", "arguments": { "id" : "foo" } } # <- { "return": {} } +# +# Since: 1.4 ## { 'command': 'chardev-remove', 'data': { 'id': 'str' } } @@ -855,12 +855,12 @@ # # @id: the chardev's ID, must exist # -# Since: 2.10 -# # .. qmp-example:: # # -> { "execute": "chardev-send-break", "arguments": { "id" : "foo" } } # <- { "return": {} } +# +# Since: 2.10 ## { 'command': 'chardev-send-break', 'data': { 'id': 'str' } } @@ -876,13 +876,13 @@ # # .. note:: This event is rate-limited. # -# Since: 2.1 -# # .. qmp-example:: # # <- { "event": "VSERPORT_CHANGE", # "data": { "id": "channel0", "open": true }, # "timestamp": { "seconds": 1401385907, "microseconds": 422329 } } +# +# Since: 2.1 ## { 'event': 'VSERPORT_CHANGE', 'data': { 'id': 'str', diff --git a/qapi/control.json b/qapi/control.json index 9a5302193d6..758b176de72 100644 --- a/qapi/control.json +++ b/qapi/control.json @@ -97,8 +97,6 @@ # # Returns: An object describing the current version of QEMU. # -# Since: 0.14 -# # .. qmp-example:: # # -> { "execute": "query-version" } @@ -112,6 +110,8 @@ # "package":"" # } # } +# +# Since: 0.14 ## { 'command': 'query-version', 'returns': 'VersionInfo', 'allow-preconfig': true } @@ -134,8 +134,6 @@ # # Returns: A list of all supported commands # -# Since: 0.14 -# # .. qmp-example:: # # -> { "execute": "query-commands" } @@ -152,6 +150,8 @@ # } # # This example has been shortened as the real response is too long. +# +# Since: 0.14 ## { 'command': 'query-commands', 'returns': ['CommandInfo'], 'allow-preconfig': true } @@ -161,16 +161,18 @@ # # Request graceful QEMU process termination. # +# Details: +# # While every attempt is made to send the QMP response before # terminating, this is not guaranteed. When using this interface, a # premature EOF would not be unexpected. # -# Since: 0.14 -# # .. qmp-example:: # # -> { "execute": "quit" } # <- { "return": {} } +# +# Since: 0.14 ## { 'command': 'quit', 'allow-preconfig': true } diff --git a/qapi/dump.json b/qapi/dump.json index 726b5208703..bda1c731544 100644 --- a/qapi/dump.json +++ b/qapi/dump.json @@ -94,13 +94,13 @@ # # .. note:: All boolean arguments default to false. # -# Since: 1.2 -# # .. qmp-example:: # # -> { "execute": "dump-guest-memory", # "arguments": { "paging": false, "protocol": "fd:dump" } } # <- { "return": {} } +# +# Since: 1.2 ## { 'command': 'dump-guest-memory', 'data': { 'paging': 'bool', 'protocol': 'str', '*detach': 'bool', @@ -150,13 +150,13 @@ # # Returns: An object showing the dump status. # -# Since: 2.6 -# # .. qmp-example:: # # -> { "execute": "query-dump" } # <- { "return": { "status": "active", "completed": 1024000, # "total": 2048000 } } +# +# Since: 2.6 ## { 'command': 'query-dump', 'returns': 'DumpQueryResult' } @@ -171,14 +171,14 @@ # failed. Only presents on failure. The user should not try to # interpret the error string. # -# Since: 2.6 -# # .. qmp-example:: # # <- { "event": "DUMP_COMPLETED", # "data": { "result": { "total": 1090650112, "status": "completed", # "completed": 1090650112 } }, # "timestamp": { "seconds": 1648244171, "microseconds": 950316 } } +# +# Since: 2.6 ## { 'event': 'DUMP_COMPLETED' , 'data': { 'result': 'DumpQueryResult', '*error': 'str' } } @@ -201,13 +201,13 @@ # # Returns: An object listing available formats for `dump-guest-memory` # -# Since: 2.0 -# # .. qmp-example:: # # -> { "execute": "query-dump-guest-memory-capability" } # <- { "return": { "formats": # ["elf", "kdump-zlib", "kdump-lzo", "kdump-snappy"] } } +# +# Since: 2.0 ## { 'command': 'query-dump-guest-memory-capability', 'returns': 'DumpGuestMemoryCapability' } diff --git a/qapi/machine-s390x.json b/qapi/machine-s390x.json index e67f180a272..adc986418d7 100644 --- a/qapi/machine-s390x.json +++ b/qapi/machine-s390x.json @@ -79,13 +79,13 @@ # # @unstable: This event is experimental. # -# Since: 8.2 -# # .. qmp-example:: # # <- { "event": "CPU_POLARIZATION_CHANGE", # "data": { "polarization": "horizontal" }, # "timestamp": { "seconds": 1401385907, "microseconds": 422329 } } +# +# Since: 8.2 ## { 'event': 'CPU_POLARIZATION_CHANGE', 'data': { 'polarization': 'S390CpuPolarization' }, @@ -130,12 +130,12 @@ # # @unstable: This event is experimental. # -# Since: 10.2 -# # .. qmp-example:: # # <- { "event": "SCLP_CPI_INFO_AVAILABLE", # "timestamp": { "seconds": 1401385907, "microseconds": 422329 } } +# +# Since: 10.2 ## { 'event': 'SCLP_CPI_INFO_AVAILABLE', 'features': [ 'unstable' ] diff --git a/qapi/machine.json b/qapi/machine.json index 2052ebbbb5b..54d5ade610d 100644 --- a/qapi/machine.json +++ b/qapi/machine.json @@ -108,8 +108,6 @@ # # Return information about all virtual CPUs. # -# Since: 2.12 -# # .. qmp-example:: # # -> { "execute": "query-cpus-fast" } @@ -138,6 +136,8 @@ # } # ] # } +# +# Since: 2.12 ## { 'command': 'query-cpus-fast', 'returns': [ 'CpuInfoFast' ] } @@ -223,8 +223,6 @@ # # @unstable: Argument @compat-props is experimental. # -# Since: 1.2 -# # .. qmp-example:: # # -> { "execute": "query-machines", "arguments": { "compat-props": true } } @@ -247,6 +245,8 @@ # }, # ... # } +# +# Since: 1.2 ## { 'command': 'query-machines', 'data': { '*compat-props': { 'type': 'bool', @@ -303,10 +303,10 @@ # # @UUID: the UUID of the guest # -# Since: 0.14 -# # .. note:: If no UUID was specified for the guest, the nil UUID (all # zeroes) is returned. +# +# Since: 0.14 ## { 'struct': 'UuidInfo', 'data': {'UUID': 'str'} } @@ -315,12 +315,12 @@ # # Query the guest UUID information. # -# Since: 0.14 -# # .. qmp-example:: # # -> { "execute": "query-uuid" } # <- { "return": { "UUID": "550e8400-e29b-41d4-a716-446655440000" } } +# +# Since: 0.14 ## { 'command': 'query-uuid', 'returns': 'UuidInfo', 'allow-preconfig': true } @@ -349,12 +349,14 @@ # # Performs a hard reset of a guest. # -# Since: 0.14 +# Details: # # .. qmp-example:: # # -> { "execute": "system_reset" } # <- { "return": {} } +# +# Since: 0.14 ## { 'command': 'system_reset' } @@ -363,7 +365,7 @@ # # Requests that a guest perform a powerdown operation. # -# Since: 0.14 +# Details: # # .. note:: A guest may or may not respond to this command. This # command returning does not indicate that a guest has accepted the @@ -374,6 +376,8 @@ # # -> { "execute": "system_powerdown" } # <- { "return": {} } +# +# Since: 0.14 ## { 'command': 'system_powerdown' } @@ -385,7 +389,7 @@ # `query-current-machine`), wake-up guest from suspend if the guest is # in SUSPENDED state. Return an error otherwise. # -# Since: 1.1 +# Details: # # .. note:: Prior to 4.0, this command does nothing in case the guest # isn't suspended. @@ -394,6 +398,8 @@ # # -> { "execute": "system_wakeup" } # <- { "return": {} } +# +# Since: 1.1 ## { 'command': 'system_wakeup' } @@ -436,7 +442,7 @@ # all CPUs (ppc64). The command fails when the guest doesn't support # injecting. # -# Since: 0.14 +# Details: # # .. note:: Prior to 2.1, this command was only supported for x86 and # s390 VMs. @@ -445,6 +451,8 @@ # # -> { "execute": "inject-nmi" } # <- { "return": {} } +# +# Since: 0.14 ## { 'command': 'inject-nmi' } @@ -806,8 +814,6 @@ # @cpu-index: the index of the virtual CPU to use for translating the # virtual address (defaults to CPU 0) # -# Since: 0.14 -# # .. caution:: Errors were not reliably returned until 1.1. # # .. qmp-example:: @@ -817,6 +823,8 @@ # "size": 100, # "filename": "/tmp/virtual-mem-dump" } } # <- { "return": {} } +# +# Since: 0.14 ## { 'command': 'memsave', 'data': { @@ -836,8 +844,6 @@ # # @filename: the file to save the memory to as binary data # -# Since: 0.14 -# # .. caution:: Errors were not reliably returned until 1.1. # # .. qmp-example:: @@ -847,6 +853,8 @@ # "size": 100, # "filename": "/tmp/physical-mem-dump" } } # <- { "return": {} } +# +# Since: 0.14 ## { 'command': 'pmemsave', 'data': { @@ -900,7 +908,7 @@ # # Return information for all memory backends. # -# Since: 2.1 +# Details: # # .. qmp-example:: # @@ -927,6 +935,8 @@ # } # ] # } +# +# Since: 2.1 ## { 'command': 'query-memdev', 'returns': ['Memdev'], 'allow-preconfig': true } @@ -1015,8 +1025,6 @@ # # TODO: Better documentation; currently there is none. # -# Since: 2.7 -# # .. qmp-example:: # :annotated: # @@ -1067,6 +1075,8 @@ # "props": { "core-id": 0 } # } # ]} +# +# Since: 2.7 ## { 'command': 'query-hotpluggable-cpus', 'returns': ['HotpluggableCPU'], 'allow-preconfig': true } @@ -1105,8 +1115,6 @@ # returns, the balloon size may not have changed. A guest can # change the balloon size independent of this command. # -# Since: 0.14 -# # .. qmp-example:: # :annotated: # @@ -1116,6 +1124,8 @@ # <- { "return": {} } # # With a 2.5GiB guest this command inflated the ballon to 3GiB. +# +# Since: 0.14 ## { 'command': 'balloon', 'data': {'value': 'int'} } @@ -1141,8 +1151,6 @@ # the KVM kernel module cannot support it, KVMMissingCap # - If no balloon device is present, DeviceNotActive # -# Since: 0.14 -# # .. qmp-example:: # # -> { "execute": "query-balloon" } @@ -1150,6 +1158,8 @@ # "actual": 1073741824 # } # } +# +# Since: 0.14 ## { 'command': 'query-balloon', 'returns': 'BalloonInfo' } @@ -1165,13 +1175,13 @@ # # .. note:: This event is rate-limited. # -# Since: 1.2 -# # .. qmp-example:: # # <- { "event": "BALLOON_CHANGE", # "data": { "actual": 944766976 }, # "timestamp": { "seconds": 1267020223, "microseconds": 435656 } } +# +# Since: 1.2 ## { 'event': 'BALLOON_CHANGE', 'data': { 'actual': 'int' } } @@ -1204,8 +1214,6 @@ # reporting is not enabled or no guest memory status report # received yet, GenericError # -# Since: 8.2 -# # .. qmp-example:: # # -> { "execute": "query-hv-balloon-status-report" } @@ -1214,6 +1222,8 @@ # "available": 3333054464 # } # } +# +# Since: 8.2 ## { 'command': 'query-hv-balloon-status-report', 'returns': 'HvBalloonInfo' } @@ -1223,15 +1233,17 @@ # Emitted when the hv-balloon driver receives a "STATUS" message from # the guest. # -# .. note:: This event is rate-limited. +# Details: # -# Since: 8.2 +# .. note:: This event is rate-limited. # # .. qmp-example:: # # <- { "event": "HV_BALLOON_STATUS_REPORT", # "data": { "committed": 816640000, "available": 3333054464 }, # "timestamp": { "seconds": 1600295492, "microseconds": 661044 } } +# +# Since: 8.2 ## { 'event': 'HV_BALLOON_STATUS_REPORT', 'data': 'HvBalloonInfo' } @@ -1538,7 +1550,7 @@ # # Lists available memory devices and their state # -# Since: 2.1 +# Details: # # .. qmp-example:: # @@ -1554,6 +1566,8 @@ # "slot": 0}, # "type": "dimm" # } ] } +# +# Since: 2.1 ## { 'command': 'query-memory-devices', 'returns': ['MemoryDeviceInfo'] } @@ -1572,14 +1586,14 @@ # # .. note:: This event is rate-limited. # -# Since: 5.1 -# # .. qmp-example:: # # <- { "event": "MEMORY_DEVICE_SIZE_CHANGE", # "data": { "id": "vm0", "size": 1073741824, # "qom-path": "/machine/unattached/device[2]" }, # "timestamp": { "seconds": 1588168529, "microseconds": 201316 } } +# +# Since: 5.1 ## { 'event': 'MEMORY_DEVICE_SIZE_CHANGE', 'data': { '*id': 'str', 'size': 'size', 'qom-path' : 'str'} } @@ -1812,13 +1826,13 @@ # # @filename: name of the dtb file to be created # -# Since: 7.2 -# # .. qmp-example:: # # -> { "execute": "dumpdtb" } # "arguments": { "filename": "fdt.dtb" } } # <- { "return": {} } +# +# Since: 7.2 ## { 'command': 'dumpdtb', 'data': { 'filename': 'str' }, @@ -1877,13 +1891,13 @@ # # @filename: the path to the file to dump to # -# Since: 2.5 -# # .. qmp-example:: # # -> { "execute": "dump-skeys", # "arguments": { "filename": "/tmp/skeys" } } # <- { "return": {} } +# +# Since: 2.5 ## { 'command': 'dump-skeys', 'data': { 'filename': 'str' } } diff --git a/qapi/migration.json b/qapi/migration.json index 558b4f145ed..b88473aa2dd 100644 --- a/qapi/migration.json +++ b/qapi/migration.json @@ -339,8 +339,6 @@ # Return information about current migration process. If migration is # active there will be another json-object with RAM migration status. # -# Since: 0.14 -# # .. qmp-example:: # :title: Before the first migration # @@ -426,6 +424,8 @@ # } # } # } +# +# Since: 0.14 ## { 'command': 'query-migrate', 'returns': 'MigrationInfo' } @@ -562,13 +562,13 @@ # # @capabilities: json array of capability modifications to make # -# Since: 1.2 -# # .. qmp-example:: # # -> { "execute": "migrate-set-capabilities" , "arguments": # { "capabilities": [ { "capability": "xbzrle", "state": true } ] } } # <- { "return": {} } +# +# Since: 1.2 ## { 'command': 'migrate-set-capabilities', 'data': { 'capabilities': ['MigrationCapabilityStatus'] } } @@ -578,8 +578,6 @@ # # Return information about the current migration capabilities status # -# Since: 1.2 -# # .. qmp-example:: # # -> { "execute": "query-migrate-capabilities" } @@ -591,6 +589,8 @@ # {"state": false, "capability": "postcopy-ram"}, # {"state": false, "capability": "x-colo"} # ]} +# +# Since: 1.2 ## { 'command': 'query-migrate-capabilities', 'returns': ['MigrationCapabilityStatus']} @@ -838,13 +838,15 @@ # # Set migration parameters. All arguments are optional. # -# Since: 2.4 +# Details: # # .. qmp-example:: # # -> { "execute": "migrate-set-parameters" , # "arguments": { "multifd-channels": 5 } } # <- { "return": {} } +# +# Since: 2.4 ## { 'command': 'migrate-set-parameters', 'boxed': true, 'data': 'MigrationParameters' } @@ -1056,8 +1058,6 @@ # @block-bitmap-mapping, which is only present if it has been # previously set. # -# Since: 2.4 -# # .. qmp-example:: # # -> { "execute": "query-migrate-parameters" } @@ -1069,6 +1069,8 @@ # "downtime-limit": 300 # } # } +# +# Since: 2.4 ## { 'command': 'query-migrate-parameters', 'returns': 'MigrationParameters' } @@ -1080,12 +1082,14 @@ # mode. The postcopy-ram capability must be set on both source and # destination before the original migration command. # -# Since: 2.5 +# Details: # # .. qmp-example:: # # -> { "execute": "migrate-start-postcopy" } # <- { "return": {} } +# +# Since: 2.5 ## { 'command': 'migrate-start-postcopy' } @@ -1096,13 +1100,13 @@ # # @status: `MigrationStatus` describing the current migration status. # -# Since: 2.4 -# # .. qmp-example:: # # <- {"timestamp": {"seconds": 1432121972, "microseconds": 744001}, # "event": "MIGRATION", # "data": {"status": "completed"} } +# +# Since: 2.4 ## { 'event': 'MIGRATION', 'data': {'status': 'MigrationStatus'}} @@ -1115,12 +1119,12 @@ # # @pass: An incrementing count (starting at 1 on the first pass) # -# Since: 2.6 -# # .. qmp-example:: # # <- { "timestamp": {"seconds": 1449669631, "microseconds": 239225}, # "event": "MIGRATION_PASS", "data": {"pass": 2} } +# +# Since: 2.6 ## { 'event': 'MIGRATION_PASS', 'data': { 'pass': 'int' } } @@ -1199,12 +1203,12 @@ # # @reason: describes the reason for the COLO exit. # -# Since: 3.1 -# # .. qmp-example:: # # <- { "timestamp": {"seconds": 2032141960, "microseconds": 417172}, # "event": "COLO_EXIT", "data": {"mode": "primary", "reason": "request" } } +# +# Since: 3.1 ## { 'event': 'COLO_EXIT', 'data': {'mode': 'COLOMode', 'reason': 'COLOExitReason' } } @@ -1242,12 +1246,12 @@ # # @unstable: This command is experimental. # -# Since: 2.8 -# # .. qmp-example:: # # -> { "execute": "x-colo-lost-heartbeat" } # <- { "return": {} } +# +# Since: 2.8 ## { 'command': 'x-colo-lost-heartbeat', 'features': [ 'unstable' ], @@ -1260,15 +1264,17 @@ # migration to be started right after. When postcopy-ram is in use, # cancelling is not allowed after the postcopy phase has started. # +# Details: +# # .. note:: This command succeeds even if there is no migration # process running. # -# Since: 0.14 -# # .. qmp-example:: # # -> { "execute": "migrate_cancel" } # <- { "return": {} } +# +# Since: 0.14 ## { 'command': 'migrate_cancel' } @@ -1279,13 +1285,13 @@ # # @state: The state the migration is currently expected to be in # -# Since: 2.11 -# # .. qmp-example:: # # -> { "execute": "migrate-continue" , "arguments": # { "state": "pre-switchover" } } # <- { "return": {} } +# +# Since: 2.11 ## { 'command': 'migrate-continue', 'data': {'state': 'MigrationStatus'} } @@ -1394,8 +1400,6 @@ # will fail unless migration is in "postcopy-paused" state. # (default: false, since 3.0) # -# Since: 0.14 -# # .. admonition:: Notes # # 1. The `query-migrate` command should be used to check @@ -1449,6 +1453,8 @@ # "filename": "/tmp/migfile", # "offset": "0x1000" } } ] } } # <- { "return": {} } +# +# Since: 0.14 ## { 'command': 'migrate', 'data': {'*uri': 'str', @@ -1472,8 +1478,6 @@ # :qapi:event:`MIGRATION` event, and error details could be # retrieved with `query-migrate`. (since 9.1) # -# Since: 2.3 -# # .. admonition:: Notes # # 1. It's a bad idea to use a string for the uri, but it needs to @@ -1521,6 +1525,8 @@ # "host": "10.12.34.9", # "port": "1050" } } ] } } # <- { "return": {} } +# +# Since: 2.3 ## { 'command': 'migrate-incoming', 'data': {'*uri': 'str', @@ -1540,13 +1546,13 @@ # @live: Optional argument to ask QEMU to treat this command as part # of a live migration. Default to true. (since 2.11) # -# Since: 1.1 -# # .. qmp-example:: # # -> { "execute": "xen-save-devices-state", # "arguments": { "filename": "/tmp/save" } } # <- { "return": {} } +# +# Since: 1.1 ## { 'command': 'xen-save-devices-state', 'data': {'filename': 'str', '*live':'bool' } } @@ -1558,13 +1564,13 @@ # # @enable: true to enable, false to disable. # -# Since: 1.3 -# # .. qmp-example:: # # -> { "execute": "xen-set-global-dirty-log", # "arguments": { "enable": true } } # <- { "return": {} } +# +# Since: 1.3 ## { 'command': 'xen-set-global-dirty-log', 'data': { 'enable': 'bool' } } @@ -1578,13 +1584,13 @@ # data. See `xen-save-devices-state`.txt for a description of the # binary format. # -# Since: 2.7 -# # .. qmp-example:: # # -> { "execute": "xen-load-devices-state", # "arguments": { "filename": "/tmp/resume" } } # <- { "return": {} } +# +# Since: 2.7 ## { 'command': 'xen-load-devices-state', 'data': {'filename': 'str'} } @@ -1747,13 +1753,13 @@ # # @device-id: QEMU device id of the unplugged device # -# Since: 4.2 -# # .. qmp-example:: # # <- { "event": "UNPLUG_PRIMARY", # "data": { "device-id": "hostdev0" }, # "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } +# +# Since: 4.2 ## { 'event': 'UNPLUG_PRIMARY', 'data': { 'device-id': 'str' } } @@ -1907,8 +1913,6 @@ # 'page-sampling'. Others are 'dirty-bitmap' and 'dirty-ring'. # (Since 6.1) # -# Since: 5.2 -# # .. qmp-example:: # # -> {"execute": "calc-dirty-rate", "arguments": {"calc-time": 1, @@ -1924,6 +1928,8 @@ # "calc-time-unit": "millisecond", "mode": "dirty-bitmap"} } # # <- { "return": {} } +# +# Since: 5.2 ## { 'command': 'calc-dirty-rate', 'data': {'calc-time': 'int64', '*calc-time-unit': 'TimeUnit', @@ -1938,8 +1944,6 @@ # @calc-time-unit: time unit in which to report calculation time. # By default it is reported in seconds. (Since 8.2) # -# Since: 5.2 -# # .. qmp-example:: # :title: Measurement is in progress # @@ -1953,6 +1957,8 @@ # <- {"status": "measured", "sample-pages": 512, "dirty-rate": 108, # "mode": "page-sampling", "start-time": 1693900454, "calc-time": 10, # "calc-time-unit": "second"} +# +# Since: 5.2 ## { 'command': 'query-dirty-rate', 'data': {'*calc-time-unit': 'TimeUnit' }, 'returns': 'DirtyRateInfo' } @@ -1989,14 +1995,14 @@ # # @dirty-rate: upper limit of dirty page rate (MB/s) for virtual CPUs. # -# Since: 7.1 -# # .. qmp-example:: # # -> {"execute": "set-vcpu-dirty-limit"} # "arguments": { "dirty-rate": 200, # "cpu-index": 1 } } # <- { "return": {} } +# +# Since: 7.1 ## { 'command': 'set-vcpu-dirty-limit', 'data': { '*cpu-index': 'int', @@ -2013,13 +2019,13 @@ # # @cpu-index: index of a virtual CPU, default is all. # -# Since: 7.1 -# # .. qmp-example:: # # -> {"execute": "cancel-vcpu-dirty-limit"}, # "arguments": { "cpu-index": 1 } } # <- { "return": {} } +# +# Since: 7.1 ## { 'command': 'cancel-vcpu-dirty-limit', 'data': { '*cpu-index': 'int'} } @@ -2029,14 +2035,14 @@ # # Return information about virtual CPU dirty page rate limits, if any. # -# Since: 7.1 -# # .. qmp-example:: # # -> {"execute": "query-vcpu-dirty-limit"} # <- {"return": [ # { "limit-rate": 60, "current-rate": 3, "cpu-index": 0}, # { "limit-rate": 60, "current-rate": 3, "cpu-index": 1}]} +# +# Since: 7.1 ## { 'command': 'query-vcpu-dirty-limit', 'returns': [ 'DirtyLimitInfo' ] } diff --git a/qapi/misc-arm.json b/qapi/misc-arm.json index f921d740f15..31a44c52a04 100644 --- a/qapi/misc-arm.json +++ b/qapi/misc-arm.json @@ -33,15 +33,17 @@ # It will return a list of `GICCapability` objects that describe its # capability bits. # +# Details: +# # On non-ARM targets this command will report an error as the GIC # technology is not applicable. # -# Since: 2.6 -# # .. qmp-example:: # # -> { "execute": "query-gic-capabilities" } # <- { "return": [{ "version": 2, "emulated": true, "kernel": false }, # { "version": 3, "emulated": false, "kernel": true } ] } +# +# Since: 2.6 ## { 'command': 'query-gic-capabilities', 'returns': ['GICCapability'] } diff --git a/qapi/misc-i386.json b/qapi/misc-i386.json index 05a94d6c416..01cdf8d706e 100644 --- a/qapi/misc-i386.json +++ b/qapi/misc-i386.json @@ -10,16 +10,18 @@ # mechanism to synchronize guest time is in effect, for example QEMU # guest agent's `guest-set-time` command. # +# Details: +# # Use of this command is only applicable for x86 machines with an RTC, # and on other machines will silently return without performing any # action. # -# Since: 2.1 -# # .. qmp-example:: # # -> { "execute": "rtc-reset-reinjection" } # <- { "return": {} } +# +# Since: 2.1 ## { 'command': 'rtc-reset-reinjection' } @@ -127,18 +129,20 @@ # # Return information about SEV/SEV-ES/SEV-SNP. # +# Details: +# # If unavailable due to an incompatible configuration the returned # @enabled field is set to 'false' and the state of all other fields # is unspecified. # -# Since: 2.12 -# # .. qmp-example:: # # -> { "execute": "query-sev" } # <- { "return": { "enabled": true, "api-major" : 0, "api-minor" : 0, # "build-id" : 0, "policy" : 0, "state" : "running", # "handle" : 1 } } +# +# Since: 2.12 ## { 'command': 'query-sev', 'returns': 'SevInfo' } @@ -169,12 +173,12 @@ # invalid guest configuration or if the guest has not reached # the required SEV state, GenericError # -# Since: 2.12 -# # .. qmp-example:: # # -> { "execute": "query-sev-launch-measure" } # <- { "return": { "data": "4l8LXeNlSPUDlXPJG5966/8%YZ" } } +# +# Since: 2.12 ## { 'command': 'query-sev-launch-measure', 'returns': 'SevLaunchMeasureInfo' } @@ -214,14 +218,14 @@ # Errors: # - If SEV is not available on the platform, GenericError # -# Since: 2.12 -# # .. qmp-example:: # # -> { "execute": "query-sev-capabilities" } # <- { "return": { "pdh": "8CCDD8DDD", "cert-chain": "888CCCDDDEE", # "cpu0-id": "2lvmGwo+...61iEinw==", # "cbitpos": 47, "reduced-phys-bits": 1}} +# +# Since: 2.12 ## { 'command': 'query-sev-capabilities', 'returns': 'SevCapability' } @@ -280,13 +284,13 @@ # invalid guest configuration or because the guest has not # reached the required SEV state, GenericError # -# Since: 6.1 -# # .. qmp-example:: # # -> { "execute" : "query-sev-attestation-report", # "arguments": { "mnonce": "aaaaaaa" } } # <- { "return" : { "data": "aaaaaaaabbbddddd"} } +# +# Since: 6.1 ## { 'command': 'query-sev-attestation-report', 'data': { 'mnonce': 'str' }, @@ -336,7 +340,7 @@ # # Return information about configured SGX capabilities of guest # -# Since: 6.2 +# Details: # # .. qmp-example:: # @@ -345,6 +349,8 @@ # "flc": true, # "sections": [{"node": 0, "size": 67108864}, # {"node": 1, "size": 29360128}]} } +# +# Since: 6.2 ## { 'command': 'query-sgx', 'returns': 'SgxInfo' } @@ -353,7 +359,7 @@ # # Return information about SGX capabilities of host # -# Since: 6.2 +# Details: # # .. qmp-example:: # @@ -362,6 +368,8 @@ # "flc": true, # "section" : [{"node": 0, "size": 67108864}, # {"node": 1, "size": 29360128}]} } +# +# Since: 6.2 ## { 'command': 'query-sgx-capabilities', 'returns': 'SgxInfo' } @@ -424,8 +432,6 @@ # # Returns: list of open event channel ports. # -# Since: 8.0 -# # .. qmp-example:: # # -> { "execute": "xen-event-list" } @@ -450,6 +456,8 @@ # } # ] # } +# +# Since: 8.0 ## { 'command': 'xen-event-list', 'returns': ['EvtchnInfo'] } @@ -461,12 +469,12 @@ # # @port: The port number # -# Since: 8.0 -# # .. qmp-example:: # # -> { "execute": "xen-event-inject", "arguments": { "port": 1 } } # <- { "return": { } } +# +# Since: 8.0 ## { 'command': 'xen-event-inject', 'data': { 'port': 'uint32' } } diff --git a/qapi/misc.json b/qapi/misc.json index 05866837f09..abb14bbd397 100644 --- a/qapi/misc.json +++ b/qapi/misc.json @@ -30,13 +30,13 @@ # # @tls: whether to perform TLS. Only applies to the "spice" protocol # -# Since: 0.14 -# # .. qmp-example:: # # -> { "execute": "add_client", "arguments": { "protocol": "vnc", # "fdname": "myclient" } } # <- { "return": {} } +# +# Since: 0.14 ## { 'command': 'add_client', 'data': { 'protocol': 'str', 'fdname': 'str', '*skipauth': 'bool', @@ -58,12 +58,12 @@ # # Return the name information of a guest. # -# Since: 0.14 -# # .. qmp-example:: # # -> { "execute": "query-name" } # <- { "return": { "name": "qemu-name" } } +# +# Since: 0.14 ## { 'command': 'query-name', 'returns': 'NameInfo', 'allow-preconfig': true } @@ -109,8 +109,6 @@ # # Returns: a list of info for each iothread # -# Since: 2.0 -# # .. qmp-example:: # # -> { "execute": "query-iothreads" } @@ -125,6 +123,8 @@ # } # ] # } +# +# Since: 2.0 ## { 'command': 'query-iothreads', 'returns': ['IOThreadInfo'], 'allow-preconfig': true } @@ -134,7 +134,7 @@ # # Stop guest VM execution. # -# Since: 0.14 +# Details: # # .. note:: This function will succeed even if the guest is already in # the stopped state. In "inmigrate" state, it will ensure that the @@ -148,6 +148,8 @@ # # -> { "execute": "stop" } # <- { "return": {} } +# +# Since: 0.14 ## { 'command': 'stop' } @@ -156,7 +158,7 @@ # # Resume guest VM execution. # -# Since: 0.14 +# Details: # # .. note:: This command will succeed if the guest is currently # running. It will also succeed if the guest is in the "inmigrate" @@ -172,6 +174,8 @@ # # -> { "execute": "cont" } # <- { "return": {} } +# +# Since: 0.14 ## { 'command': 'cont' } @@ -190,12 +194,12 @@ # # @unstable: This command is experimental. # -# Since: 3.0 -# # .. qmp-example:: # # -> { "execute": "x-exit-preconfig" } # <- { "return": {} } +# +# Since: 3.0 ## { 'command': 'x-exit-preconfig', 'allow-preconfig': true, 'features': [ 'unstable' ] } @@ -217,8 +221,6 @@ # monitor-owned nodes if they have no parents. This allows the # use of 'savevm' with -blockdev. (since 4.2) # -# Since: 0.14 -# # .. 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 @@ -237,6 +239,8 @@ # -> { "execute": "human-monitor-command", # "arguments": { "command-line": "info kvm" } } # <- { "return": "kvm support: enabled\r\n" } +# +# Since: 0.14 ## { 'command': 'human-monitor-command', 'data': {'command-line': 'str', '*cpu-index': 'int'}, @@ -250,8 +254,6 @@ # # @fdname: file descriptor name # -# Since: 0.14 -# # .. note:: If @fdname already exists, the file descriptor assigned to # it will be closed and replaced by the received file descriptor. # @@ -262,6 +264,8 @@ # # -> { "execute": "getfd", "arguments": { "fdname": "fd1" } } # <- { "return": {} } +# +# Since: 0.14 ## { 'command': 'getfd', 'data': {'fdname': 'str'}, 'if': 'CONFIG_POSIX' } @@ -277,8 +281,6 @@ # # @fdname: file descriptor name # -# Since: 8.0 -# # .. note:: If @fdname already exists, the file descriptor assigned to # it will be closed and replaced by the received file descriptor. # @@ -290,6 +292,8 @@ # -> { "execute": "get-win32-socket", # "arguments": { "info": "abcd123..", "fdname": "skclient" } } # <- { "return": {} } +# +# Since: 8.0 ## { 'command': 'get-win32-socket', 'data': {'info': 'str', 'fdname': 'str'}, 'if': 'CONFIG_WIN32' } @@ -300,12 +304,12 @@ # # @fdname: file descriptor name # -# Since: 0.14 -# # .. qmp-example:: # # -> { "execute": "closefd", "arguments": { "fdname": "fd1" } } # <- { "return": {} } +# +# Since: 0.14 ## { 'command': 'closefd', 'data': {'fdname': 'str'} } @@ -341,12 +345,12 @@ # .. note:: If @fdset-id is not specified, a new fd set will be # created. # -# Since: 1.2 -# # .. qmp-example:: # # -> { "execute": "add-fd", "arguments": { "fdset-id": 1 } } # <- { "return": { "fdset-id": 1, "fd": 3 } } +# +# Since: 1.2 ## { 'command': 'add-fd', 'data': { '*fdset-id': 'int', @@ -365,8 +369,6 @@ # Errors: # - If @fdset-id or @fd is not found, GenericError # -# Since: 1.2 -# # .. note:: The list of fd sets is shared by all monitor connections. # # .. note:: If @fd is not specified, all file descriptors in @fdset-id @@ -376,6 +378,8 @@ # # -> { "execute": "remove-fd", "arguments": { "fdset-id": 1, "fd": 3 } } # <- { "return": {} } +# +# Since: 1.2 ## { 'command': 'remove-fd', 'data': {'fdset-id': 'int', '*fd': 'int'} } @@ -412,7 +416,7 @@ # # Return information describing all fd sets. # -# Since: 1.2 +# Details: # # .. note:: The list of fd sets is shared by all monitor connections. # @@ -446,6 +450,8 @@ # } # ] # } +# +# Since: 1.2 ## { 'command': 'query-fdsets', 'returns': ['FdsetInfo'] } @@ -516,8 +522,6 @@ # Errors: # - if the given @option doesn't exist # -# Since: 1.5 -# # .. qmp-example:: # # -> { "execute": "query-command-line-options", @@ -538,6 +542,8 @@ # } # ] # } +# +# Since: 1.5 ## {'command': 'query-command-line-options', 'data': {'*option': 'str'}, @@ -558,13 +564,13 @@ # RTC in the system implements this event, or even that the system # has an RTC at all. # -# Since: 0.13 -# # .. qmp-example:: # # <- { "event": "RTC_CHANGE", # "data": { "offset": 78 }, # "timestamp": { "seconds": 1267020223, "microseconds": 435656 } } +# +# Since: 0.13 ## { 'event': 'RTC_CHANGE', 'data': { 'offset': 'int', 'qom-path': 'str' } } @@ -585,8 +591,6 @@ # # @dev-qom-path: path to attached PCI device in the QOM tree # -# Since: 7.1 -# # .. qmp-example:: # # <- { "event": "VFU_CLIENT_HANGUP", @@ -595,6 +599,8 @@ # "dev-id": "sas1", # "dev-qom-path": "/machine/peripheral/sas1" }, # "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } +# +# Since: 7.1 ## { 'event': 'VFU_CLIENT_HANGUP', 'data': { 'vfu-id': 'str', 'vfu-qom-path': 'str', diff --git a/qapi/net.json b/qapi/net.json index c011d6dc1a9..2deb0b6dfdf 100644 --- a/qapi/net.json +++ b/qapi/net.json @@ -22,8 +22,6 @@ # Errors: # - If @name is not a valid network device, DeviceNotFound # -# Since: 0.14 -# # .. note:: Not all network adapters support setting link status. # This command will succeed even if the network adapter does not # support link status notification. @@ -33,6 +31,8 @@ # -> { "execute": "set_link", # "arguments": { "name": "e1000.0", "up": false } } # <- { "return": {} } +# +# Since: 0.14 ## { 'command': 'set_link', 'data': {'name': 'str', 'up': 'bool'} } @@ -43,8 +43,6 @@ # # Additional arguments depend on the type. # -# Since: 0.14 -# # Errors: # - If @type is not a valid network backend, DeviceNotFound # @@ -54,6 +52,8 @@ # "arguments": { "type": "user", "id": "netdev1", # "dnssearch": [ { "str": "example.org" } ] } } # <- { "return": {} } +# +# Since: 0.14 ## { 'command': 'netdev_add', 'data': 'Netdev', 'boxed': true, 'allow-preconfig': true } @@ -68,12 +68,12 @@ # Errors: # - If @id is not a valid network backend, DeviceNotFound # -# Since: 0.14 -# # .. qmp-example:: # # -> { "execute": "netdev_del", "arguments": { "id": "netdev1" } } # <- { "return": {} } +# +# Since: 0.14 ## { 'command': 'netdev_del', 'data': {'id': 'str'}, 'allow-preconfig': true } @@ -975,8 +975,6 @@ # - if the given NIC doesn't support rx-filter querying # - if the given net client isn't a NIC # -# Since: 1.6 -# # .. qmp-example:: # # -> { "execute": "query-rx-filter", "arguments": { "name": "vnet0" } } @@ -1005,6 +1003,8 @@ # } # ] # } +# +# Since: 1.6 ## { 'command': 'query-rx-filter', 'data': { '*name': 'str' }, @@ -1020,14 +1020,14 @@ # # @path: device path # -# Since: 1.6 -# # .. qmp-example:: # # <- { "event": "NIC_RX_FILTER_CHANGED", # "data": { "name": "vnet0", # "path": "/machine/peripheral/vnet0/virtio-backend" }, # "timestamp": { "seconds": 1368697518, "microseconds": 326866 } } +# +# Since: 1.6 ## { 'event': 'NIC_RX_FILTER_CHANGED', 'data': { '*name': 'str', 'path': 'str' } } @@ -1095,13 +1095,13 @@ # # @device-id: QEMU device id of the unplugged device # -# Since: 4.2 -# # .. qmp-example:: # # <- { "event": "FAILOVER_NEGOTIATED", # "data": { "device-id": "net1" }, # "timestamp": { "seconds": 1368697518, "microseconds": 326866 } } +# +# Since: 4.2 ## { 'event': 'FAILOVER_NEGOTIATED', 'data': {'device-id': 'str'} } @@ -1115,8 +1115,6 @@ # # @addr: The destination address # -# Since: 7.2 -# # .. qmp-example:: # # <- { "event": "NETDEV_STREAM_CONNECTED", @@ -1131,6 +1129,8 @@ # "data": { "netdev-id": "netdev0", # "addr": { "path": "/tmp/qemu0", "type": "unix" } }, # "timestamp": { "seconds": 1666269706, "microseconds": 413651 } } +# +# Since: 7.2 ## { 'event': 'NETDEV_STREAM_CONNECTED', 'data': { 'netdev-id': 'str', @@ -1143,13 +1143,13 @@ # # @netdev-id: QEMU netdev id that is disconnected # -# Since: 7.2 -# # .. qmp-example:: # # <- { "event": "NETDEV_STREAM_DISCONNECTED", # "data": {"netdev-id": "netdev0"}, # "timestamp": {"seconds": 1663330937, "microseconds": 526695} } +# +# Since: 7.2 ## { 'event': 'NETDEV_STREAM_DISCONNECTED', 'data': { 'netdev-id': 'str' } } @@ -1163,13 +1163,13 @@ # # @chardev-id: The character device id used by the QEMU netdev # -# Since: 10.0 -# # .. qmp-example:: # # <- { "timestamp": {"seconds": 1739538638, "microseconds": 354181 }, # "event": "NETDEV_VHOST_USER_CONNECTED", # "data": { "netdev-id": "netdev0", "chardev-id": "chr0" } } +# +# Since: 10.0 ## { 'event': 'NETDEV_VHOST_USER_CONNECTED', 'data': { 'netdev-id': 'str', 'chardev-id': 'str' } } @@ -1181,13 +1181,13 @@ # # @netdev-id: QEMU netdev id that is disconnected # -# Since: 10.0 -# # .. qmp-example:: # # <- { "timestamp": { "seconds": 1739538634, "microseconds": 920450 }, # "event": "NETDEV_VHOST_USER_DISCONNECTED", # "data": { "netdev-id": "netdev0" } } +# +# Since: 10.0 ## { 'event': 'NETDEV_VHOST_USER_DISCONNECTED', 'data': { 'netdev-id': 'str' } } diff --git a/qapi/pci.json b/qapi/pci.json index 694c741e420..c36af01a100 100644 --- a/qapi/pci.json +++ b/qapi/pci.json @@ -182,8 +182,6 @@ # of all PCI devices attached to it. Each device is represented # by a json-object. # -# Since: 0.14 -# # .. qmp-example:: # # -> { "execute": "query-pci" } @@ -314,5 +312,7 @@ # } # # This example has been shortened as the real response is too long. +# +# Since: 0.14 ## { 'command': 'query-pci', 'returns': ['PciInfo'] } diff --git a/qapi/qdev.json b/qapi/qdev.json index 974cf9c5830..483bc9eb9cd 100644 --- a/qapi/qdev.json +++ b/qapi/qdev.json @@ -103,8 +103,6 @@ # device will not be removed and a `DEVICE_UNPLUG_GUEST_ERROR` # event is sent. Some errors cannot be detected. # -# Since: 0.14 -# # .. qmp-example:: # # -> { "execute": "device_del", @@ -116,6 +114,8 @@ # -> { "execute": "device_del", # "arguments": { "id": "/machine/peripheral-anon/device[0]" } } # <- { "return": {} } +# +# Since: 0.14 ## { 'command': 'device_del', 'data': {'id': 'str'} } @@ -131,14 +131,14 @@ # # @path: the device's QOM path # -# Since: 1.5 -# # .. qmp-example:: # # <- { "event": "DEVICE_DELETED", # "data": { "device": "virtio-net-pci-0", # "path": "/machine/peripheral/virtio-net-pci-0" }, # "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } +# +# Since: 1.5 ## { 'event': 'DEVICE_DELETED', 'data': { '*device': 'str', 'path': 'str' } } @@ -153,14 +153,14 @@ # # @path: the device's QOM path # -# Since: 6.2 -# # .. qmp-example:: # # <- { "event": "DEVICE_UNPLUG_GUEST_ERROR", # "data": { "device": "core1", # "path": "/machine/peripheral/core1" }, # "timestamp": { "seconds": 1615570772, "microseconds": 202844 } } +# +# Since: 6.2 ## { 'event': 'DEVICE_UNPLUG_GUEST_ERROR', 'data': { '*device': 'str', 'path': 'str' } } diff --git a/qapi/qom.json b/qapi/qom.json index fd88be07e13..9733a815a9b 100644 --- a/qapi/qom.json +++ b/qapi/qom.json @@ -85,8 +85,6 @@ # # Returns: a list that describe the properties of the object. # -# Since: 1.2 -# # .. qmp-example:: # # -> { "execute": "qom-list", @@ -95,6 +93,8 @@ # { "name": "parallel0", "type": "child<chardev-vc>" }, # { "name": "serial0", "type": "child<chardev-vc>" }, # { "name": "mon0", "type": "child<chardev-stdio>" } ] } +# +# Since: 1.2 ## { 'command': 'qom-list', 'data': { 'path': 'str' }, @@ -129,8 +129,6 @@ # child<> and link<> properties are returned as #str pathnames. # All integer property types (u8, u16, etc) are returned as #int. # -# Since: 1.2 -# # .. qmp-example:: # :title: Use absolute path # @@ -146,6 +144,8 @@ # "arguments": { "path": "unattached/sysbus", # "property": "type" } } # <- { "return": "System" } +# +# Since: 1.2 ## { 'command': 'qom-get', 'data': { 'path': 'str', 'property': 'str' }, @@ -186,8 +186,6 @@ # @value: a value who's type is appropriate for the property type. # See `qom-get` for a description of type mapping. # -# Since: 1.2 -# # .. qmp-example:: # # -> { "execute": "qom-set", @@ -195,6 +193,8 @@ # "property": "graphics", # "value": false } } # <- { "return": {} } +# +# Since: 1.2 ## { 'command': 'qom-set', 'data': { 'path': 'str', 'property': 'str', 'value': 'any' }, @@ -1342,14 +1342,14 @@ # Errors: # - If @qom-type is not a valid class name # -# Since: 2.0 -# # .. qmp-example:: # # -> { "execute": "object-add", # "arguments": { "qom-type": "rng-random", "id": "rng1", # "filename": "/dev/hwrng" } } # <- { "return": {} } +# +# Since: 2.0 ## { 'command': 'object-add', 'data': 'ObjectOptions', 'boxed': true, 'allow-preconfig': true } @@ -1364,12 +1364,12 @@ # Errors: # - If @id is not a valid id for a QOM object # -# Since: 2.0 -# # .. qmp-example:: # # -> { "execute": "object-del", "arguments": { "id": "rng1" } } # <- { "return": {} } +# +# Since: 2.0 ## { 'command': 'object-del', 'data': {'id': 'str'}, 'allow-preconfig': true } diff --git a/qapi/replay.json b/qapi/replay.json index ccf84da68ef..bdee8e0ecfe 100644 --- a/qapi/replay.json +++ b/qapi/replay.json @@ -54,12 +54,12 @@ # # Returns: record/replay information. # -# Since: 5.2 -# # .. qmp-example:: # # -> { "execute": "query-replay" } # <- { "return": { "mode": "play", "filename": "log.rr", "icount": 220414 } } +# +# Since: 5.2 ## { 'command': 'query-replay', 'returns': 'ReplayInfo' } @@ -76,12 +76,12 @@ # # @icount: instruction count to stop at # -# Since: 5.2 -# # .. qmp-example:: # # -> { "execute": "replay-break", "arguments": { "icount": 220414 } } # <- { "return": {} } +# +# Since: 5.2 ## { 'command': 'replay-break', 'data': { 'icount': 'int' } } @@ -91,12 +91,14 @@ # Remove replay breakpoint which was set with `replay-break`. The # command is ignored when there are no replay breakpoints. # -# Since: 5.2 +# Details: # # .. qmp-example:: # # -> { "execute": "replay-delete-break" } # <- { "return": {} } +# +# Since: 5.2 ## { 'command': 'replay-delete-break' } @@ -112,11 +114,11 @@ # # @icount: target instruction count # -# Since: 5.2 -# # .. qmp-example:: # # -> { "execute": "replay-seek", "arguments": { "icount": 220414 } } # <- { "return": {} } +# +# Since: 5.2 ## { 'command': 'replay-seek', 'data': { 'icount': 'int' } } diff --git a/qapi/rocker.json b/qapi/rocker.json index 5d2dbd26034..e8efffc4c9f 100644 --- a/qapi/rocker.json +++ b/qapi/rocker.json @@ -30,12 +30,12 @@ # # @name: switch name # -# Since: 2.4 -# # .. qmp-example:: # # -> { "execute": "query-rocker", "arguments": { "name": "sw1" } } # <- { "return": {"name": "sw1", "ports": 2, "id": 1327446905938}} +# +# Since: 2.4 ## { 'command': 'query-rocker', 'data': { 'name': 'str' }, @@ -98,8 +98,6 @@ # # @name: port name # -# Since: 2.4 -# # .. qmp-example:: # # -> { "execute": "query-rocker-ports", "arguments": { "name": "sw1" } } @@ -108,6 +106,8 @@ # {"duplex": "full", "enabled": true, "name": "sw1.2", # "autoneg": "off", "link-up": true, "speed": 10000} # ]} +# +# Since: 2.4 ## { 'command': 'query-rocker-ports', 'data': { 'name': 'str' }, @@ -240,8 +240,6 @@ # # Returns: rocker OF-DPA flow information # -# Since: 2.4 -# # .. qmp-example:: # # -> { "execute": "query-rocker-of-dpa-flows", @@ -254,6 +252,8 @@ # }, # ... # ]} +# +# Since: 2.4 ## { 'command': 'query-rocker-of-dpa-flows', 'data': { 'name': 'str', '*tbl-id': 'uint32' }, @@ -315,8 +315,6 @@ # # Returns: rocker OF-DPA group information # -# Since: 2.4 -# # .. qmp-example:: # # -> { "execute": "query-rocker-of-dpa-groups", @@ -334,6 +332,8 @@ # "pport": 0, "vlan-id": 3840, # "pop-vlan": 1, "id": 251658240} # ]} +# +# Since: 2.4 ## { 'command': 'query-rocker-of-dpa-groups', 'data': { 'name': 'str', '*type': 'uint8' }, diff --git a/qapi/run-state.json b/qapi/run-state.json index a5771ad4681..1bc4e905f00 100644 --- a/qapi/run-state.json +++ b/qapi/run-state.json @@ -121,13 +121,15 @@ # # Query the run status of the VM # -# Since: 0.14 +# Details: # # .. qmp-example:: # # -> { "execute": "query-status" } # <- { "return": { "running": true, # "status": "running" } } +# +# Since: 0.14 ## { 'command': 'query-status', 'returns': 'StatusInfo', 'allow-preconfig': true } @@ -150,13 +152,13 @@ # specified, QEMU will not exit, and a `STOP` event will eventually # follow the `SHUTDOWN` event. # -# Since: 0.12 -# # .. qmp-example:: # # <- { "event": "SHUTDOWN", # "data": { "guest": true, "reason": "guest-shutdown" }, # "timestamp": { "seconds": 1267040730, "microseconds": 682951 } } +# +# Since: 0.12 ## { 'event': 'SHUTDOWN', 'data': { 'guest': 'bool', 'reason': 'ShutdownCause' } } @@ -166,12 +168,14 @@ # Emitted when the virtual machine is powered down through the power # control system, such as via ACPI. # -# Since: 0.12 +# Details: # # .. qmp-example:: # # <- { "event": "POWERDOWN", # "timestamp": { "seconds": 1267040730, "microseconds": 682951 } } +# +# Since: 0.12 ## { 'event': 'POWERDOWN' } @@ -187,13 +191,13 @@ # # @reason: The `ShutdownCause` of the `RESET`. (since 4.0) # -# Since: 0.12 -# # .. qmp-example:: # # <- { "event": "RESET", # "data": { "guest": false, "reason": "guest-reset" }, # "timestamp": { "seconds": 1267041653, "microseconds": 9518 } } +# +# Since: 0.12 ## { 'event': 'RESET', 'data': { 'guest': 'bool', 'reason': 'ShutdownCause' } } @@ -202,12 +206,14 @@ # # Emitted when the virtual machine is stopped # -# Since: 0.12 +# Details: # # .. qmp-example:: # # <- { "event": "STOP", # "timestamp": { "seconds": 1267041730, "microseconds": 281295 } } +# +# Since: 0.12 ## { 'event': 'STOP' } @@ -216,12 +222,14 @@ # # Emitted when the virtual machine resumes execution # -# Since: 0.12 +# Details: # # .. qmp-example:: # # <- { "event": "RESUME", # "timestamp": { "seconds": 1271770767, "microseconds": 582542 } } +# +# Since: 0.12 ## { 'event': 'RESUME' } @@ -231,12 +239,14 @@ # Emitted when guest enters a hardware suspension state, for example, # S3 state, which is sometimes called standby state # -# Since: 1.1 +# Details: # # .. qmp-example:: # # <- { "event": "SUSPEND", # "timestamp": { "seconds": 1344456160, "microseconds": 309119 } } +# +# Since: 1.1 ## { 'event': 'SUSPEND' } @@ -247,15 +257,17 @@ # saved on disk, for example, S4 state, which is sometimes called # hibernate state # +# Details: +# # .. note:: QEMU shuts down (similar to event `SHUTDOWN`) when # entering this state. # -# Since: 1.2 -# # .. qmp-example:: # # <- { "event": "SUSPEND_DISK", # "timestamp": { "seconds": 1344456160, "microseconds": 309119 } } +# +# Since: 1.2 ## { 'event': 'SUSPEND_DISK' } @@ -265,12 +277,14 @@ # Emitted when the guest has woken up from suspend state and is # running # -# Since: 1.1 +# Details: # # .. qmp-example:: # # <- { "event": "WAKEUP", # "timestamp": { "seconds": 1344522075, "microseconds": 745528 } } +# +# Since: 1.1 ## { 'event': 'WAKEUP' } @@ -287,13 +301,13 @@ # # .. note:: This event is rate-limited. # -# Since: 0.13 -# # .. qmp-example:: # # <- { "event": "WATCHDOG", # "data": { "action": "reset" }, # "timestamp": { "seconds": 1267061043, "microseconds": 959568 } } +# +# Since: 0.13 ## { 'event': 'WATCHDOG', 'data': { 'action': 'WatchdogAction' } } @@ -380,13 +394,13 @@ # # @action: `WatchdogAction` action taken when watchdog timer expires. # -# Since: 2.11 -# # .. qmp-example:: # # -> { "execute": "watchdog-set-action", # "arguments": { "action": "inject-nmi" } } # <- { "return": {} } +# +# Since: 2.11 ## { 'command': 'watchdog-set-action', 'data' : {'action': 'WatchdogAction'} } @@ -405,8 +419,6 @@ # @watchdog: `WatchdogAction` action taken when watchdog timer # expires. # -# Since: 6.0 -# # .. qmp-example:: # # -> { "execute": "set-action", @@ -415,6 +427,8 @@ # "panic": "pause", # "watchdog": "inject-nmi" } } # <- { "return": {} } +# +# Since: 6.0 ## { 'command': 'set-action', 'data': { '*reboot': 'RebootAction', @@ -432,13 +446,13 @@ # # @info: information about a panic (since 2.9) # -# Since: 1.5 -# # .. qmp-example:: # # <- { "event": "GUEST_PANICKED", # "data": { "action": "pause" }, # "timestamp": { "seconds": 1648245231, "microseconds": 900001 } } +# +# Since: 1.5 ## { 'event': 'GUEST_PANICKED', 'data': { 'action': 'GuestPanicAction', '*info': 'GuestPanicInformation' } } @@ -452,13 +466,13 @@ # # @info: information about a panic # -# Since: 5.0 -# # .. qmp-example:: # # <- { "event": "GUEST_CRASHLOADED", # "data": { "action": "run" }, # "timestamp": { "seconds": 1648245259, "microseconds": 893771 } } +# +# Since: 5.0 ## { 'event': 'GUEST_CRASHLOADED', 'data': { 'action': 'GuestPanicAction', '*info': 'GuestPanicInformation' } } @@ -468,12 +482,14 @@ # # Emitted when guest submits a shutdown request via pvpanic interface # -# Since: 9.1 +# Details: # # .. qmp-example:: # # <- { "event": "GUEST_PVSHUTDOWN", # "timestamp": { "seconds": 1648245259, "microseconds": 893771 } } +# +# Since: 9.1 ## { 'event': 'GUEST_PVSHUTDOWN' } @@ -655,8 +671,6 @@ # # @flags: flags for `MemoryFailureAction`. # -# Since: 5.2 -# # .. qmp-example:: # # <- { "event": "MEMORY_FAILURE", @@ -665,6 +679,8 @@ # "flags": { "action-required": false, # "recursive": false } }, # "timestamp": { "seconds": 1267061043, "microseconds": 959568 } } +# +# Since: 5.2 ## { 'event': 'MEMORY_FAILURE', 'data': { 'recipient': 'MemoryFailureRecipient', diff --git a/qapi/tpm.json b/qapi/tpm.json index 3f2850a5733..8b1be5fa4db 100644 --- a/qapi/tpm.json +++ b/qapi/tpm.json @@ -29,12 +29,12 @@ # # Return a list of supported TPM models # -# Since: 1.5 -# # .. qmp-example:: # # -> { "execute": "query-tpm-models" } # <- { "return": [ "tpm-tis", "tpm-crb", "tpm-spapr" ] } +# +# Since: 1.5 ## { 'command': 'query-tpm-models', 'returns': ['TpmModel'], 'if': 'CONFIG_TPM' } @@ -58,12 +58,12 @@ # # Return a list of supported TPM types # -# Since: 1.5 -# # .. qmp-example:: # # -> { "execute": "query-tpm-types" } # <- { "return": [ "passthrough", "emulator" ] } +# +# Since: 1.5 ## { 'command': 'query-tpm-types', 'returns': ['TpmType'], 'if': 'CONFIG_TPM' } @@ -164,8 +164,6 @@ # # Return information about the TPM device # -# Since: 1.5 -# # .. qmp-example:: # # -> { "execute": "query-tpm" } @@ -183,6 +181,8 @@ # } # ] # } +# +# Since: 1.5 ## { 'command': 'query-tpm', 'returns': ['TPMInfo'], 'if': 'CONFIG_TPM' } diff --git a/qapi/trace.json b/qapi/trace.json index de369dae6b5..63685b3d5ec 100644 --- a/qapi/trace.json +++ b/qapi/trace.json @@ -51,13 +51,13 @@ # # Returns: a list of info for the matching events # -# Since: 2.2 -# # .. qmp-example:: # # -> { "execute": "trace-event-get-state", # "arguments": { "name": "qemu_memalign" } } # <- { "return": [ { "name": "qemu_memalign", "state": "disabled", "vcpu": false } ] } +# +# Since: 2.2 ## { 'command': 'trace-event-get-state', 'data': {'name': 'str' }, @@ -74,13 +74,13 @@ # # @ignore-unavailable: Do not match unavailable events with @name. # -# Since: 2.2 -# # .. qmp-example:: # # -> { "execute": "trace-event-set-state", # "arguments": { "name": "qemu_memalign", "enable": true } } # <- { "return": {} } +# +# Since: 2.2 ## { 'command': 'trace-event-set-state', 'data': {'name': 'str', 'enable': 'bool', '*ignore-unavailable': 'bool' } } diff --git a/qapi/transaction.json b/qapi/transaction.json index 4b4eb09bf38..1e6b5d37980 100644 --- a/qapi/transaction.json +++ b/qapi/transaction.json @@ -244,8 +244,6 @@ # in an error condition, and subsequent actions will not have been # attempted. # -# Since: 1.1 -# # .. qmp-example:: # # -> { "execute": "transaction", @@ -266,6 +264,8 @@ # "device": "ide-hd2", # "name": "snapshot0" } } ] } } # <- { "return": {} } +# +# Since: 1.1 ## { 'command': 'transaction', 'data': { 'actions': [ 'TransactionAction' ], diff --git a/qapi/ui.json b/qapi/ui.json index e3da77632a8..0fd6b144394 100644 --- a/qapi/ui.json +++ b/qapi/ui.json @@ -83,13 +83,13 @@ # Errors: # - If Spice is not enabled, DeviceNotFound # -# Since: 0.14 -# # .. qmp-example:: # # -> { "execute": "set_password", "arguments": { "protocol": "vnc", # "password": "secret" } } # <- { "return": {} } +# +# Since: 0.14 ## { 'command': 'set_password', 'boxed': true, 'data': 'SetPasswordOptions' } @@ -145,13 +145,13 @@ # - If @protocol is 'spice' and Spice is not active, # DeviceNotFound # -# Since: 0.14 -# # .. qmp-example:: # # -> { "execute": "expire_password", "arguments": { "protocol": "vnc", # "time": "+60" } } # <- { "return": {} } +# +# Since: 0.14 ## { 'command': 'expire_password', 'boxed': true, 'data': 'ExpirePasswordOptions' } @@ -187,13 +187,13 @@ # # @format: image format for `screendump`. (default: ppm) (Since 7.1) # -# Since: 0.14 -# # .. qmp-example:: # # -> { "execute": "screendump", # "arguments": { "filename": "/tmp/image" } } # <- { "return": {} } +# +# Since: 0.14 ## { 'command': 'screendump', 'data': {'filename': 'str', '*device': 'str', '*head': 'int', @@ -328,8 +328,6 @@ # # Return information about the current SPICE server # -# Since: 0.14 -# # .. qmp-example:: # # -> { "execute": "query-spice" } @@ -364,6 +362,8 @@ # ] # } # } +# +# Since: 0.14 ## { 'command': 'query-spice', 'returns': 'SpiceInfo', 'if': 'CONFIG_SPICE' } @@ -377,8 +377,6 @@ # # @client: client information # -# Since: 0.14 -# # .. qmp-example:: # # <- { "timestamp": {"seconds": 1290688046, "microseconds": 388707}, @@ -387,6 +385,8 @@ # "server": { "port": "5920", "family": "ipv4", "host": "127.0.0.1"}, # "client": {"port": "52873", "family": "ipv4", "host": "127.0.0.1"} # }} +# +# Since: 0.14 ## { 'event': 'SPICE_CONNECTED', 'data': { 'server': 'SpiceBasicInfo', @@ -403,8 +403,6 @@ # # @client: client information # -# Since: 0.14 -# # .. qmp-example:: # # <- { "timestamp": {"seconds": 1290688046, "microseconds": 417172}, @@ -415,6 +413,8 @@ # "connection-id": 1804289383, "host": "127.0.0.1", # "channel-id": 0, "tls": true} # }} +# +# Since: 0.14 ## { 'event': 'SPICE_INITIALIZED', 'data': { 'server': 'SpiceServerInfo', @@ -430,8 +430,6 @@ # # @client: client information # -# Since: 0.14 -# # .. qmp-example:: # # <- { "timestamp": {"seconds": 1290688046, "microseconds": 388707}, @@ -440,6 +438,8 @@ # "server": { "port": "5920", "family": "ipv4", "host": "127.0.0.1"}, # "client": {"port": "52873", "family": "ipv4", "host": "127.0.0.1"} # }} +# +# Since: 0.14 ## { 'event': 'SPICE_DISCONNECTED', 'data': { 'server': 'SpiceBasicInfo', @@ -451,12 +451,14 @@ # # Emitted when SPICE migration has completed # -# Since: 1.3 +# Details: # # .. qmp-example:: # # <- { "timestamp": {"seconds": 1290688046, "microseconds": 417172}, # "event": "SPICE_MIGRATE_COMPLETED" } +# +# Since: 1.3 ## { 'event': 'SPICE_MIGRATE_COMPLETED', 'if': 'CONFIG_SPICE' } @@ -658,8 +660,6 @@ # # Return information about the current VNC server # -# Since: 0.14 -# # .. qmp-example:: # # -> { "execute": "query-vnc" } @@ -679,6 +679,8 @@ # ] # } # } +# +# Since: 0.14 ## { 'command': 'query-vnc', 'returns': 'VncInfo', 'if': 'CONFIG_VNC' } @@ -700,11 +702,11 @@ # # @password: the new password to use with VNC authentication # -# Since: 1.1 -# # .. note:: An empty password in this command will set the password to # the empty string. Existing clients are unaffected by executing # this command. +# +# Since: 1.1 ## { 'command': 'change-vnc-password', 'data': { 'password': 'str' }, @@ -722,8 +724,6 @@ # .. note:: This event is emitted before any authentication takes # place, thus the authentication ID is not provided. # -# Since: 0.13 -# # .. qmp-example:: # # <- { "event": "VNC_CONNECTED", @@ -733,6 +733,8 @@ # "client": { "family": "ipv4", "service": "58425", # "host": "127.0.0.1", "websocket": false } }, # "timestamp": { "seconds": 1262976601, "microseconds": 975795 } } +# +# Since: 0.13 ## { 'event': 'VNC_CONNECTED', 'data': { 'server': 'VncServerInfo', @@ -749,8 +751,6 @@ # # @client: client information # -# Since: 0.13 -# # .. qmp-example:: # # <- { "event": "VNC_INITIALIZED", @@ -760,6 +760,8 @@ # "client": { "family": "ipv4", "service": "46089", "websocket": false, # "host": "127.0.0.1", "sasl_username": "luiz" } }, # "timestamp": { "seconds": 1263475302, "microseconds": 150772 } } +# +# Since: 0.13 ## { 'event': 'VNC_INITIALIZED', 'data': { 'server': 'VncServerInfo', @@ -775,8 +777,6 @@ # # @client: client information # -# Since: 0.13 -# # .. qmp-example:: # # <- { "event": "VNC_DISCONNECTED", @@ -786,6 +786,8 @@ # "client": { "family": "ipv4", "service": "58425", "websocket": false, # "host": "127.0.0.1", "sasl_username": "luiz" } }, # "timestamp": { "seconds": 1262976601, "microseconds": 975795 } } +# +# Since: 0.13 ## { 'event': 'VNC_DISCONNECTED', 'data': { 'server': 'VncServerInfo', @@ -825,8 +827,6 @@ # # Returns: a list of info for each device # -# Since: 0.14 -# # .. qmp-example:: # # -> { "execute": "query-mice" } @@ -845,6 +845,8 @@ # } # ] # } +# +# Since: 0.14 ## { 'command': 'query-mice', 'returns': ['MouseInfo'] } @@ -1035,8 +1037,6 @@ # Errors: # - If key is unknown or redundant, GenericError # -# Since: 1.3 -# # .. qmp-example:: # # -> { "execute": "send-key", @@ -1044,6 +1044,8 @@ # { "type": "qcode", "data": "alt" }, # { "type": "qcode", "data": "delete" } ] } } # <- { "return": {} } +# +# Since: 1.3 ## { 'command': 'send-key', 'data': { 'keys': ['KeyValue'], '*hold-time': 'int' } } @@ -1265,8 +1267,6 @@ # # @events: List of `InputEvent` union. # -# 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 @@ -1308,6 +1308,8 @@ # { "type": "abs", "data" : { "axis": "x", "value" : 20000 } }, # { "type": "abs", "data" : { "axis": "y", "value" : 400 } } ] } } # <- { "return": {} } +# +# Since: 2.6 ## { 'command': 'input-send-event', 'data': { '*device': 'str', @@ -1620,13 +1622,15 @@ # # Reload display configuration. # -# Since: 6.0 +# Details: # # .. qmp-example:: # # -> { "execute": "display-reload", # "arguments": { "type": "vnc", "tls-certs": true } } # <- { "return": {} } +# +# Since: 6.0 ## { 'command': 'display-reload', 'data': 'DisplayReloadOptions', @@ -1677,7 +1681,7 @@ # # Update display configuration. # -# Since: 7.1 +# Details: # # .. qmp-example:: # @@ -1686,6 +1690,8 @@ # [ { "type": "inet", "host": "0.0.0.0", # "port": "5901" } ] } } # <- { "return": {} } +# +# Since: 7.1 ## { 'command': 'display-update', 'data': 'DisplayUpdateOptions', @@ -1708,8 +1714,6 @@ # # @cert-subject: server certificate subject # -# Since: 0.14 -# # .. qmp-example:: # # -> { "execute": "client_migrate_info", @@ -1717,6 +1721,8 @@ # "hostname": "virt42.lab.kraxel.org", # "port": 1234 } } # <- { "return": {} } +# +# Since: 0.14 ## { 'command': 'client_migrate_info', 'data': { 'protocol': 'str', 'hostname': 'str', '*port': 'int', diff --git a/qapi/vfio.json b/qapi/vfio.json index 17b60468712..630e2595c82 100644 --- a/qapi/vfio.json +++ b/qapi/vfio.json @@ -58,8 +58,6 @@ # # @device-state: The new changed device migration state. # -# Since: 9.1 -# # .. qmp-example:: # # <- { "timestamp": { "seconds": 1713771323, "microseconds": 212268 }, @@ -68,6 +66,8 @@ # "device-id": "vfio_dev1", # "qom-path": "/machine/peripheral/vfio_dev1", # "device-state": "stop" } } +# +# Since: 9.1 ## { 'event': 'VFIO_MIGRATION', 'data': { diff --git a/qapi/virtio.json b/qapi/virtio.json index 447fc182625..ae795e1e852 100644 --- a/qapi/virtio.json +++ b/qapi/virtio.json @@ -34,8 +34,6 @@ # # @unstable: This command is meant for debugging. # -# Since: 7.2 -# # .. qmp-example:: # # -> { "execute": "x-query-virtio" } @@ -62,6 +60,8 @@ # } # ] # } +# +# Since: 7.2 ## { 'command': 'x-query-virtio', 'returns': [ 'VirtioInfo' ], @@ -203,8 +203,6 @@ # # @unstable: This command is meant for debugging. # -# Since: 7.2 -# # .. qmp-example:: # :annotated: # @@ -437,6 +435,8 @@ # "use-started": true # } # } +# +# Since: 7.2 ## { 'command': 'x-query-virtio-status', 'data': { 'path': 'str' }, @@ -579,8 +579,6 @@ # shadow_avail_idx will not be displayed in the case where the # selected VirtIODevice has a running vhost device. # -# Since: 7.2 -# # .. qmp-example:: # :annotated: # @@ -635,6 +633,8 @@ # "vring-num": 128 # } # } +# +# Since: 7.2 ## { 'command': 'x-query-virtio-queue-status', 'data': { 'path': 'str', 'queue': 'uint16' }, @@ -707,8 +707,6 @@ # # @unstable: This command is meant for debugging. # -# Since: 7.2 -# # .. qmp-example:: # :title: Get vhost_virtqueue status for vhost-crypto # @@ -756,6 +754,8 @@ # "kick": 0 # } # } +# +# Since: 7.2 ## { 'command': 'x-query-virtio-vhost-queue-status', 'data': { 'path': 'str', 'queue': 'uint16' }, @@ -854,8 +854,6 @@ # # @unstable: This command is meant for debugging. # -# Since: 7.2 -# # .. qmp-example:: # :title: Introspect on virtio-net's VirtQueue 0 at index 5 # @@ -943,6 +941,8 @@ # } # } # } +# +# Since: 7.2 ## { 'command': 'x-query-virtio-queue-element', 'data': { 'path': 'str', 'queue': 'uint16', '*index': 'uint16' }, -- 2.53.0 ^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [PATCH 7/8] qapi: re-order 'since' sections to always be last 2026-03-16 18:26 ` [PATCH 7/8] qapi: re-order 'since' sections to always be last John Snow @ 2026-03-20 14:23 ` Markus Armbruster 2026-03-20 20:47 ` John Snow 0 siblings, 1 reply; 29+ messages in thread From: Markus Armbruster @ 2026-03-20 14:23 UTC (permalink / raw) To: John Snow Cc: qemu-devel, Pierrick Bouvier, Lukas Straub, Richard Henderson, Zhao Liu, Jason Wang, Mauro Carvalho Chehab, Alex Bennée, Peter Xu, Eric Blake, Daniel P. Berrangé, Fabiano Rosas, Philippe Mathieu-Daudé, Cédric Le Goater, qemu-block, Marc-André Lureau, Peter Maydell, Michael S. Tsirkin, Stefan Berger, Alex Williamson, Marcel Apfelbaum, Kevin Wolf, Michael Roth, Stefano Garzarella, Stefan Hajnoczi, Igor Mammedov, Jiri Pirko, Yanan Wang, Paolo Bonzini, Kashyap Chamarthy, Hanna Reitz, Ani Sinha John Snow <jsnow@redhat.com> writes: > Note that with "Since" being moved to the last position, we open up a > good many new cases of ambiguos intro-vs-details text which must be > corrected with "Details:" tags. > > This patch doesn't only add these markers where it would definitively > impact inlining - it adds them to *any* doc block that has more than one > paragraph of plaintext and no other distinguishing features (members, > features, errors, returns). > > It may well be the case that not every last one of these *needs* to be > amended in this way, but this is the broad coverage shotgun approach > that demonstrates which places in the code may cause footguns with > regards to automated stub insertions of members/arguments/etc, returns, > or inlining order ambiguities. > > Signed-off-by: John Snow <jsnow@redhat.com> [...] > diff --git a/qapi/accelerator.json b/qapi/accelerator.json > index d333a772384..5624b5d88b7 100644 > --- a/qapi/accelerator.json > +++ b/qapi/accelerator.json > @@ -29,12 +29,12 @@ > # > # Return information about KVM acceleration > # > -# Since: 0.14 > -# > # .. qmp-example:: > # > # -> { "execute": "query-kvm" } > # <- { "return": { "enabled": true, "present": true } } > +# > +# Since: 0.14 > ## > { 'command': 'query-kvm', 'returns': 'KvmInfo' } > Rendered output changes unexpectedly from Command query-kvm (Since: 0.14) Return information about KVM acceleration Return: KvmInfo Example:: -> { "execute": "query-kvm" } <- { "return": { "enabled": true, "present": true } } to Command query-kvm (Since: 0.14) Return information about KVM acceleration Example:: -> { "execute": "query-kvm" } <- { "return": { "enabled": true, "present": true } } Return: KvmInfo I guess the "Since:" quietly serves as separator between INTRO and DETAILS before the patch, and the patch is missing a DETAILS: line. Several more instances follow. [...] ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 7/8] qapi: re-order 'since' sections to always be last 2026-03-20 14:23 ` Markus Armbruster @ 2026-03-20 20:47 ` John Snow 0 siblings, 0 replies; 29+ messages in thread From: John Snow @ 2026-03-20 20:47 UTC (permalink / raw) To: Markus Armbruster Cc: qemu-devel, Pierrick Bouvier, Lukas Straub, Richard Henderson, Zhao Liu, Jason Wang, Mauro Carvalho Chehab, Alex Bennée, Peter Xu, Eric Blake, Daniel P. Berrangé, Fabiano Rosas, Philippe Mathieu-Daudé, Cédric Le Goater, Qemu-block, Marc-André Lureau, Peter Maydell, Michael S. Tsirkin, Stefan Berger, Alex Williamson, Marcel Apfelbaum, Kevin Wolf, Michael Roth, Stefano Garzarella, Stefan Hajnoczi, Igor Mammedov, Jiri Pirko, Yanan Wang, Paolo Bonzini, Kashyap Chamarthy, Hanna Reitz, Ani Sinha [-- Attachment #1: Type: text/plain, Size: 2523 bytes --] On Fri, Mar 20, 2026, 10:23 AM Markus Armbruster <armbru@redhat.com> wrote: > John Snow <jsnow@redhat.com> writes: > > > Note that with "Since" being moved to the last position, we open up a > > good many new cases of ambiguos intro-vs-details text which must be > > corrected with "Details:" tags. > > > > This patch doesn't only add these markers where it would definitively > > impact inlining - it adds them to *any* doc block that has more than one > > paragraph of plaintext and no other distinguishing features (members, > > features, errors, returns). > > > > It may well be the case that not every last one of these *needs* to be > > amended in this way, but this is the broad coverage shotgun approach > > that demonstrates which places in the code may cause footguns with > > regards to automated stub insertions of members/arguments/etc, returns, > > or inlining order ambiguities. > > > > Signed-off-by: John Snow <jsnow@redhat.com> > > [...] > > > diff --git a/qapi/accelerator.json b/qapi/accelerator.json > > index d333a772384..5624b5d88b7 100644 > > --- a/qapi/accelerator.json > > +++ b/qapi/accelerator.json > > @@ -29,12 +29,12 @@ > > # > > # Return information about KVM acceleration > > # > > -# Since: 0.14 > > -# > > # .. qmp-example:: > > # > > # -> { "execute": "query-kvm" } > > # <- { "return": { "enabled": true, "present": true } } > > +# > > +# Since: 0.14 > > ## > > { 'command': 'query-kvm', 'returns': 'KvmInfo' } > > > > Rendered output changes unexpectedly from > > Command query-kvm (Since: 0.14) > > Return information about KVM acceleration > > Return: > KvmInfo > > Example:: > > -> { "execute": "query-kvm" } > <- { "return": { "enabled": true, "present": true } } > > to > > Command query-kvm (Since: 0.14) > > Return information about KVM acceleration > > Example:: > > -> { "execute": "query-kvm" } > <- { "return": { "enabled": true, "present": true } } > > Return: > KvmInfo > > I guess the "Since:" quietly serves as separator between INTRO and > DETAILS before the patch, and the patch is missing a DETAILS: line. > > Several more instances follow. > > [...] > Oh, drats. I suppose my yelping tool doesn't notice this kind of change in particular. I suppose I'll compare before/after of my .ir files and use that to identify which cases change. Good spot. [-- Attachment #2: Type: text/html, Size: 3918 bytes --] ^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 8/8] qapi: enforce strict positioning for "Since:" section 2026-03-16 18:25 [PATCH 0/8] qapi: enforce section ordering John Snow ` (6 preceding siblings ...) 2026-03-16 18:26 ` [PATCH 7/8] qapi: re-order 'since' sections to always be last John Snow @ 2026-03-16 18:26 ` John Snow 7 siblings, 0 replies; 29+ messages in thread From: John Snow @ 2026-03-16 18:26 UTC (permalink / raw) To: qemu-devel Cc: Pierrick Bouvier, Lukas Straub, Richard Henderson, Zhao Liu, Jason Wang, Mauro Carvalho Chehab, Alex Bennée, Peter Xu, Eric Blake, Daniel P. Berrangé, Fabiano Rosas, Philippe Mathieu-Daudé, Cédric Le Goater, qemu-block, Marc-André Lureau, Peter Maydell, Michael S. Tsirkin, Stefan Berger, Alex Williamson, Marcel Apfelbaum, Kevin Wolf, John Snow, Michael Roth, Stefano Garzarella, Stefan Hajnoczi, Igor Mammedov, Jiri Pirko, Yanan Wang, Paolo Bonzini, Kashyap Chamarthy, Markus Armbruster, Hanna Reitz, Ani Sinha Signed-off-by: John Snow <jsnow@redhat.com> --- scripts/qapi/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py index 1a7856bf213..0bc7d622ec1 100644 --- a/scripts/qapi/parser.py +++ b/scripts/qapi/parser.py @@ -550,7 +550,7 @@ def get_doc(self) -> 'QAPIDoc': def _tag_check(what: str) -> None: nonlocal last_section - if what in ('TODO', 'Since'): + if what == 'TODO': return this_section = QAPIDoc.Kind.from_string(what) -- 2.53.0 ^ permalink raw reply related [flat|nested] 29+ messages in thread
end of thread, other threads:[~2026-03-23 9:07 UTC | newest] Thread overview: 29+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-03-16 18:25 [PATCH 0/8] qapi: enforce section ordering John Snow 2026-03-16 18:26 ` [PATCH 1/8] qapi: differentiate "intro" and "details" sections John Snow 2026-03-20 12:24 ` Markus Armbruster 2026-03-20 17:20 ` John Snow 2026-03-23 8:15 ` Markus Armbruster 2026-03-16 18:26 ` [PATCH 2/8] qapi: prohibit 'details' sections between tagged sections John Snow 2026-03-20 12:46 ` Markus Armbruster 2026-03-20 17:40 ` John Snow 2026-03-23 8:41 ` Markus Armbruster 2026-03-20 13:46 ` Markus Armbruster 2026-03-20 17:42 ` John Snow 2026-03-16 18:26 ` [PATCH 3/8] qapi: add "Details:" disambiguation marker John Snow 2026-03-20 13:45 ` Markus Armbruster 2026-03-20 18:25 ` John Snow 2026-03-23 8:55 ` Markus Armbruster 2026-03-16 18:26 ` [PATCH 4/8] qapi: detect potentially semantically ambiguous intro paragraphs John Snow 2026-03-20 13:51 ` Markus Armbruster 2026-03-20 18:26 ` John Snow 2026-03-16 18:26 ` [PATCH 5/8] qapi: re-order QAPI doc block sections John Snow 2026-03-20 14:11 ` Markus Armbruster 2026-03-20 18:27 ` John Snow 2026-03-16 18:26 ` [PATCH 6/8] qapi: enforce doc block section ordering John Snow 2026-03-20 14:13 ` Markus Armbruster 2026-03-20 18:28 ` John Snow 2026-03-23 8:56 ` Markus Armbruster 2026-03-16 18:26 ` [PATCH 7/8] qapi: re-order 'since' sections to always be last John Snow 2026-03-20 14:23 ` Markus Armbruster 2026-03-20 20:47 ` John Snow 2026-03-16 18:26 ` [PATCH 8/8] qapi: enforce strict positioning for "Since:" 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