From patchwork Fri Apr 19 04:37:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 13635662 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 608E0C04FF6 for ; Fri, 19 Apr 2024 04:40:01 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rxg1C-0007RB-4p; Fri, 19 Apr 2024 00:38:34 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg19-0007Ok-SP for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:31 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg17-00049j-Jk for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:31 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713501508; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=8n+UfeBL2CIYHwJZ2oAWjPHIDqW+hEsaFx7BYgalx9k=; b=MmSqLRCP6EyUIZlGJwVYZ9x06/o/X3UWeLaE8c5AZCIqRZ1w5biJgEQlauPC4MFnaNd3Q5 kTBRBZThkeiRwcJnMNnW+FE0dfEF6XLoblBUwewP0MEtC2J0mODg3DNssg+UqDytunqKoz Abbvdqt1l+EYLE/A8DmnzCPGtIbfgxE= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-1-T4PRfAqwORewWj-MK1Z8kw-1; Fri, 19 Apr 2024 00:38:22 -0400 X-MC-Unique: T4PRfAqwORewWj-MK1Z8kw-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 663CB80021A; Fri, 19 Apr 2024 04:38:22 +0000 (UTC) Received: from scv.redhat.com (unknown [10.22.8.7]) by smtp.corp.redhat.com (Postfix) with ESMTP id B423440357A7; Fri, 19 Apr 2024 04:38:21 +0000 (UTC) From: John Snow To: qemu-devel@nongnu.org Cc: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , Markus Armbruster , Victor Toso de Carvalho , Peter Maydell , Paolo Bonzini , John Snow Subject: [PATCH 01/27] docs/sphinx: create QAPI domain extension stub Date: Fri, 19 Apr 2024 00:37:49 -0400 Message-ID: <20240419043820.178731-2-jsnow@redhat.com> In-Reply-To: <20240419043820.178731-1-jsnow@redhat.com> References: <20240419043820.178731-1-jsnow@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 Received-SPF: pass client-ip=170.10.129.124; envelope-from=jsnow@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.067, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org It doesn't really do anything yet, we'll get to it brick-by-brick in the forthcoming commits to keep the series breezy and the git history informative. Signed-off-by: John Snow --- docs/conf.py | 3 ++- docs/sphinx/qapi-domain.py | 50 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 docs/sphinx/qapi-domain.py diff --git a/docs/conf.py b/docs/conf.py index aae0304ac6e..b15665d956d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -61,7 +61,8 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = ['kerneldoc', 'qmp_lexer', 'hxtool', 'depfile', 'qapidoc'] +extensions = ['kerneldoc', 'hxtool', 'depfile', + 'qapidoc', 'qapi-domain', 'qmp_lexer'] if sphinx.version_info[:3] > (4, 0, 0): tags.add('sphinx4') diff --git a/docs/sphinx/qapi-domain.py b/docs/sphinx/qapi-domain.py new file mode 100644 index 00000000000..163b9ff21c3 --- /dev/null +++ b/docs/sphinx/qapi-domain.py @@ -0,0 +1,50 @@ +""" +QAPI domain extension. +""" + +from __future__ import annotations + +from typing import ( + TYPE_CHECKING, + Any, + Dict, + List, + Tuple, +) + +from sphinx.domains import Domain, ObjType +from sphinx.util import logging + + +if TYPE_CHECKING: + from sphinx.application import Sphinx + +logger = logging.getLogger(__name__) + + +class QAPIDomain(Domain): + """QAPI language domain.""" + + name = "qapi" + label = "QAPI" + + object_types: Dict[str, ObjType] = {} + directives = {} + roles = {} + initial_data: Dict[str, Dict[str, Tuple[Any]]] = {} + indices = [] + + def merge_domaindata(self, docnames: List[str], otherdata: Dict[str, Any]) -> None: + pass + + +def setup(app: Sphinx) -> Dict[str, Any]: + app.setup_extension("sphinx.directives") + app.add_domain(QAPIDomain) + + return { + "version": "1.0", + "env_version": 1, + "parallel_read_safe": True, + "parallel_write_safe": True, + } From patchwork Fri Apr 19 04:37:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 13635674 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 7AAB5C4345F for ; Fri, 19 Apr 2024 04:41:05 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rxg1Q-0007WK-EA; Fri, 19 Apr 2024 00:38:48 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1C-0007SK-MJ for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:34 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg16-00049b-RX for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:34 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713501507; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=nj35h2WAXeTMyr3hnl2WAc6btn9ZnHTwGwLAP2BhYio=; b=RswWdNoDryF9Kw/DThevsWBNRlmd3hXvpONAlhJTcMyEeNWPObDQcapWjzkZndjjF+x9l4 yJBufLQKgS7E5JNATzhFOq4DX0uoMXdTiGqvu1uKyk0yryA8rBfxlKN64G3hFQNrPfNt1E /qz/dV9lZ8x1QUpen6P0LtK1C8dGXt8= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-400-wLCbpNe7NWaM-CKB29iYqA-1; Fri, 19 Apr 2024 00:38:23 -0400 X-MC-Unique: wLCbpNe7NWaM-CKB29iYqA-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 2559E3CBDF66; Fri, 19 Apr 2024 04:38:23 +0000 (UTC) Received: from scv.redhat.com (unknown [10.22.8.7]) by smtp.corp.redhat.com (Postfix) with ESMTP id 741F54011FF7; Fri, 19 Apr 2024 04:38:22 +0000 (UTC) From: John Snow To: qemu-devel@nongnu.org Cc: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , Markus Armbruster , Victor Toso de Carvalho , Peter Maydell , Paolo Bonzini , John Snow Subject: [PATCH 02/27] docs/qapi-domain: add qapi:module directive Date: Fri, 19 Apr 2024 00:37:50 -0400 Message-ID: <20240419043820.178731-3-jsnow@redhat.com> In-Reply-To: <20240419043820.178731-1-jsnow@redhat.com> References: <20240419043820.178731-1-jsnow@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 Received-SPF: pass client-ip=170.10.133.124; envelope-from=jsnow@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.067, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org This adds a qapi:module directive, which just notes the current module being documented and performs a nested parse of the content block, if present. This code is based pretty heavily on Sphinx's PyModule directive, but with the modindex functionality excised. This commit also adds the _nested_parse helper, which adds cross-version compatibility for nested parsing while preserving proper line context information. For example: .. qapi:module:: block-core Hello, and welcome to block-core! ================================= lorem ipsum, dolor sit amet ... (For RFC purposes, this commit also adds a test document that demonstrates the functionality-so-far to allow reviewers to easily test and experiment with each commit. The eventual submission for inclusion will remove this playground file.) Signed-off-by: John Snow --- docs/index.rst | 1 + docs/qapi/index.rst | 38 +++++++++++ docs/sphinx/qapi-domain.py | 128 ++++++++++++++++++++++++++++++++++++- 3 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 docs/qapi/index.rst diff --git a/docs/index.rst b/docs/index.rst index 0b9ee9901d9..11c18c598a8 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -18,3 +18,4 @@ Welcome to QEMU's documentation! interop/index specs/index devel/index + qapi/index diff --git a/docs/qapi/index.rst b/docs/qapi/index.rst new file mode 100644 index 00000000000..880fd17c709 --- /dev/null +++ b/docs/qapi/index.rst @@ -0,0 +1,38 @@ +---------------- +QAPI Domain Test +---------------- + +.. qapi:module:: foo-module + :no-index: + + This starts a hypothetical module named ``foo-module``, but it + doesn't create a cross-reference target and it isn't added to the + index. + + Check out the `genindex` for proof that foo-module is not present. + +.. qapi:module:: bar-module + :no-typesetting: + + This starts a hypothetical module named ``bar-module``, but the + contents of the body here will not be rendered in the + output. However, any link targets created here or in nested + directives will be preserved and functional. + + Check out the `genindex` for proof that bar-module is present in two + places! (under both "bar-module" and "QAPI module".) + +.. qapi:module:: block-core + + Block core (VM unrelated) + ========================= + + This starts the documentation section for the ``block-core`` module. + All documentation objects that follow belong to the block-core module + until another ``qapi:module:`` directive is encountered. + + This directive does not create an entry in the sidebar or the TOC + *unless* you create a nested section title within the directive. + + The ``block-core`` module will have two entries in the `genindex`, + under both "block-core" and "QAPI module". diff --git a/docs/sphinx/qapi-domain.py b/docs/sphinx/qapi-domain.py index 163b9ff21c3..7c5e4407bc1 100644 --- a/docs/sphinx/qapi-domain.py +++ b/docs/sphinx/qapi-domain.py @@ -7,21 +7,141 @@ from typing import ( TYPE_CHECKING, Any, + ClassVar, Dict, + Iterable, List, Tuple, + cast, ) +from docutils import nodes +from docutils.parsers.rst import directives + +from sphinx import addnodes from sphinx.domains import Domain, ObjType from sphinx.util import logging +from sphinx.util.docutils import SphinxDirective, switch_source_input +from sphinx.util.nodes import make_id, nested_parse_with_titles if TYPE_CHECKING: + from docutils.nodes import Element, Node + from sphinx.application import Sphinx + from sphinx.util.typing import OptionSpec logger = logging.getLogger(__name__) +def _nested_parse(directive: SphinxDirective, content_node: Element) -> None: + """ + This helper preserves error parsing context across sphinx versions. + """ + + # necessary so that the child nodes get the right source/line set + content_node.document = directive.state.document + + try: + # Modern sphinx (6.2.0+) supports proper offsetting for + # nested parse error context management + nested_parse_with_titles( + directive.state, + directive.content, + content_node, + content_offset=directive.content_offset, # type: ignore[call-arg] + ) + except TypeError: + # No content_offset argument. Fall back to SSI method. + with switch_source_input(directive.state, directive.content): + nested_parse_with_titles(directive.state, directive.content, content_node) + + +class QAPIModule(SphinxDirective): + """ + Directive to mark description of a new module. + + This directive doesn't generate any special formatting, and is just + a pass-through for the content body. Named section titles are + allowed in the content body. + + Use this directive to associate subsequent definitions with the + module they are defined in for purposes of search and QAPI index + organization. + + :arg: The name of the module. + :opt no-index: Don't add cross-reference targets or index entries. + :opt no-typesetting: Don't render the content body (but preserve any + cross-reference target IDs in the squelched output.) + + Example:: + + .. qapi:module:: block-core + :no-index: + :no-typesetting: + + Lorem ipsum, dolor sit amet ... + + """ + + has_content = True + required_arguments = 1 + optional_arguments = 0 + final_argument_whitespace = False + + option_spec: ClassVar[OptionSpec] = { + # These are universal "Basic" options; + # https://www.sphinx-doc.org/en/master/usage/domains/index.html#basic-markup + "no-index": directives.flag, + "no-typesetting": directives.flag, + "no-contents-entry": directives.flag, # NB: No effect + # Deprecated aliases; to be removed in Sphinx 9.0 + "noindex": directives.flag, + "nocontentsentry": directives.flag, # NB: No effect + } + + def run(self) -> List[Node]: + modname = self.arguments[0].strip() + no_index = "no-index" in self.options or "noindex" in self.options + + self.env.ref_context["qapi:module"] = modname + + content_node: Element = nodes.section() + _nested_parse(self, content_node) + + ret: List[Node] = [] + inode = addnodes.index(entries=[]) + + if not no_index: + node_id = make_id(self.env, self.state.document, "module", modname) + target = nodes.target("", "", ids=[node_id], ismod=True) + self.set_source_info(target) + self.state.document.note_explicit_target(target) + + indextext = f"QAPI module; {modname}" + inode = addnodes.index( + entries=[ + ("pair", indextext, node_id, "", None), + ] + ) + ret.append(inode) + content_node.insert(0, target) + + if "no-typesetting" in self.options: + if node_ids := [ + node_id + for el in content_node.findall(nodes.Element) + for node_id in cast(Iterable[str], el.get("ids", ())) + ]: + target = nodes.target(ids=node_ids) + self.set_source_info(target) + ret.append(target) + else: + ret.extend(content_node.children) + + return ret + + class QAPIDomain(Domain): """QAPI language domain.""" @@ -29,7 +149,13 @@ class QAPIDomain(Domain): label = "QAPI" object_types: Dict[str, ObjType] = {} - directives = {} + + # Each of these provides a ReST directive, + # e.g. .. qapi:module:: block-core + directives = { + "module": QAPIModule, + } + roles = {} initial_data: Dict[str, Dict[str, Tuple[Any]]] = {} indices = [] From patchwork Fri Apr 19 04:37:51 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 13635656 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id DD4C0C4345F for ; Fri, 19 Apr 2024 04:39:29 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rxg1A-0007PK-UO; Fri, 19 Apr 2024 00:38:33 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg18-0007NW-Mv for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:30 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg16-00049e-S2 for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:30 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713501507; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/AEQhBBM6eRMT5ZEFVa7wWZlrEMhJwKKNup8PtABSHw=; b=MaFjkz5/hsRmt5BzPb+T8LBXiIyxM8J4h7YEjenz++ykDItusd/R0XMjf2fqeV7PfEPSBE QweBET31F44SUg5cTIv8ktP522TVZSuoDABKGpqVxz2rTT2uGqUubeYV+bxXr0tJTkegX3 TmJhFDignb0c5bFH7064X/gkn8dLgQ0= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-253-BGK83vgJM4SGsq4-78L5OA-1; Fri, 19 Apr 2024 00:38:24 -0400 X-MC-Unique: BGK83vgJM4SGsq4-78L5OA-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id D9C76810602; Fri, 19 Apr 2024 04:38:23 +0000 (UTC) Received: from scv.redhat.com (unknown [10.22.8.7]) by smtp.corp.redhat.com (Postfix) with ESMTP id 33C8440357A7; Fri, 19 Apr 2024 04:38:23 +0000 (UTC) From: John Snow To: qemu-devel@nongnu.org Cc: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , Markus Armbruster , Victor Toso de Carvalho , Peter Maydell , Paolo Bonzini , John Snow Subject: [PATCH 03/27] docs/qapi-module: add QAPI domain object registry Date: Fri, 19 Apr 2024 00:37:51 -0400 Message-ID: <20240419043820.178731-4-jsnow@redhat.com> In-Reply-To: <20240419043820.178731-1-jsnow@redhat.com> References: <20240419043820.178731-1-jsnow@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 Received-SPF: pass client-ip=170.10.129.124; envelope-from=jsnow@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.067, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org This is the first step towards QAPI domain cross-references and a QAPI reference index. For now, just create the object registry and amend the qapi:module directive to use that registry. Update the merge_domaindata method now that we have actual data we may need to merge. RFC: Much of this code is adapted directly from sphinx.domains.python; it is unclear to me if there ever would be a collision on merge, hence the assertion. I haven't been able to trigger it or find better code to use as a template, so probably I'll just leave the assertion in there. Signed-off-by: John Snow --- docs/sphinx/qapi-domain.py | 76 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 73 insertions(+), 3 deletions(-) diff --git a/docs/sphinx/qapi-domain.py b/docs/sphinx/qapi-domain.py index 7c5e4407bc1..ab80fd5f634 100644 --- a/docs/sphinx/qapi-domain.py +++ b/docs/sphinx/qapi-domain.py @@ -11,6 +11,7 @@ Dict, Iterable, List, + NamedTuple, Tuple, cast, ) @@ -20,6 +21,7 @@ from sphinx import addnodes from sphinx.domains import Domain, ObjType +from sphinx.locale import _, __ from sphinx.util import logging from sphinx.util.docutils import SphinxDirective, switch_source_input from sphinx.util.nodes import make_id, nested_parse_with_titles @@ -34,6 +36,13 @@ logger = logging.getLogger(__name__) +class ObjectEntry(NamedTuple): + docname: str + node_id: str + objtype: str + aliased: bool + + def _nested_parse(directive: SphinxDirective, content_node: Element) -> None: """ This helper preserves error parsing context across sphinx versions. @@ -101,6 +110,7 @@ class QAPIModule(SphinxDirective): } def run(self) -> List[Node]: + domain = cast(QAPIDomain, self.env.get_domain("qapi")) modname = self.arguments[0].strip() no_index = "no-index" in self.options or "noindex" in self.options @@ -113,11 +123,14 @@ def run(self) -> List[Node]: inode = addnodes.index(entries=[]) if not no_index: + # note module to the domain node_id = make_id(self.env, self.state.document, "module", modname) target = nodes.target("", "", ids=[node_id], ismod=True) self.set_source_info(target) self.state.document.note_explicit_target(target) + domain.note_object(modname, "module", node_id, location=target) + indextext = f"QAPI module; {modname}" inode = addnodes.index( entries=[ @@ -148,7 +161,12 @@ class QAPIDomain(Domain): name = "qapi" label = "QAPI" - object_types: Dict[str, ObjType] = {} + # This table associates cross-reference object types (key) with an + # ObjType instance, which defines the valid cross-reference roles + # for each object type. + object_types: Dict[str, ObjType] = { + "module": ObjType(_("module"), "mod", "obj"), + } # Each of these provides a ReST directive, # e.g. .. qapi:module:: block-core @@ -157,11 +175,63 @@ class QAPIDomain(Domain): } roles = {} - initial_data: Dict[str, Dict[str, Tuple[Any]]] = {} + + # Moved into the data property at runtime; + # this is the internal index of reference-able objects. + initial_data: Dict[str, Dict[str, Tuple[Any]]] = { + "objects": {}, # fullname -> ObjectEntry + } + indices = [] + @property + def objects(self) -> Dict[str, ObjectEntry]: + return self.data.setdefault("objects", {}) # type: ignore[no-any-return] + + def note_object( + self, + name: str, + objtype: str, + node_id: str, + aliased: bool = False, + location: Any = None, + ) -> None: + """Note a QAPI object for cross reference.""" + if name in self.objects: + other = self.objects[name] + if other.aliased and aliased is False: + # The original definition found. Override it! + pass + elif other.aliased is False and aliased: + # The original definition is already registered. + return + else: + # duplicated + logger.warning( + __( + "duplicate object description of %s, " + "other instance in %s, use :no-index: for one of them" + ), + name, + other.docname, + location=location, + ) + self.objects[name] = ObjectEntry(self.env.docname, node_id, objtype, aliased) + + def clear_doc(self, docname: str) -> None: + for fullname, obj in list(self.objects.items()): + if obj.docname == docname: + del self.objects[fullname] + def merge_domaindata(self, docnames: List[str], otherdata: Dict[str, Any]) -> None: - pass + for fullname, obj in otherdata["objects"].items(): + if obj.docname in docnames: + # FIXME: Unsure of the implications of merge conflicts. + # Sphinx's own python domain doesn't appear to bother. + assert ( + fullname not in self.objects + ), f"!?!? collision on merge? {fullname=} {obj=} {self.objects[fullname]=}" + self.objects[fullname] = obj def setup(app: Sphinx) -> Dict[str, Any]: From patchwork Fri Apr 19 04:37:52 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 13635658 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 36A8EC04FF6 for ; Fri, 19 Apr 2024 04:39:36 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rxg1O-0007VV-Rf; Fri, 19 Apr 2024 00:38:46 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1B-0007QG-Ab for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:33 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg18-00049t-Gz for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:33 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713501508; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Yd3gqttPN7y/yTkQ3a8gByZcKPzL7SnUWn217oHpxJI=; b=XDudCDnn/pN6bgOCz64qBGFvnOhyja6q76/MTsUx6aM6CbEVmaChBb16pw2Iw+rEq1aXmo OYIHY5BrmBpFxk55FxPZlenr+zTuqwRHnctiHJc2dP1P95wOF6B/xXbRAr/X+d/Thtb3Bd xonVgqCP+zCti0ml5viDCRjkYwHV8mY= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-193-13vhTZKfMQqnhK7fAlMlrQ-1; Fri, 19 Apr 2024 00:38:25 -0400 X-MC-Unique: 13vhTZKfMQqnhK7fAlMlrQ-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 9992B811029; Fri, 19 Apr 2024 04:38:24 +0000 (UTC) Received: from scv.redhat.com (unknown [10.22.8.7]) by smtp.corp.redhat.com (Postfix) with ESMTP id E76984011FF7; Fri, 19 Apr 2024 04:38:23 +0000 (UTC) From: John Snow To: qemu-devel@nongnu.org Cc: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , Markus Armbruster , Victor Toso de Carvalho , Peter Maydell , Paolo Bonzini , John Snow Subject: [PATCH 04/27] docs/qapi-domain: add QAPI index Date: Fri, 19 Apr 2024 00:37:52 -0400 Message-ID: <20240419043820.178731-5-jsnow@redhat.com> In-Reply-To: <20240419043820.178731-1-jsnow@redhat.com> References: <20240419043820.178731-1-jsnow@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 Received-SPF: pass client-ip=170.10.129.124; envelope-from=jsnow@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.067, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Use the QAPI object registry to generate a special index just for QAPI definitions. The index can show entries both by definition type and alphabetically. The index can be linked from anywhere in the QEMU manual by using `qapi-index`. Signed-off-by: John Snow --- docs/qapi/index.rst | 6 +++- docs/sphinx/qapi-domain.py | 66 +++++++++++++++++++++++++++++++++++--- 2 files changed, 66 insertions(+), 6 deletions(-) diff --git a/docs/qapi/index.rst b/docs/qapi/index.rst index 880fd17c709..051dc6b3a37 100644 --- a/docs/qapi/index.rst +++ b/docs/qapi/index.rst @@ -9,7 +9,8 @@ QAPI Domain Test doesn't create a cross-reference target and it isn't added to the index. - Check out the `genindex` for proof that foo-module is not present. + Check out the `genindex` or the `qapi-index` for proof that + foo-module is not present. .. qapi:module:: bar-module :no-typesetting: @@ -36,3 +37,6 @@ QAPI Domain Test The ``block-core`` module will have two entries in the `genindex`, under both "block-core" and "QAPI module". + + Modules will also be reported in the `qapi-index`, under the Modules + category and in the alphabetical categories that follow. diff --git a/docs/sphinx/qapi-domain.py b/docs/sphinx/qapi-domain.py index ab80fd5f634..65409786119 100644 --- a/docs/sphinx/qapi-domain.py +++ b/docs/sphinx/qapi-domain.py @@ -12,6 +12,7 @@ Iterable, List, NamedTuple, + Optional, Tuple, cast, ) @@ -20,7 +21,12 @@ from docutils.parsers.rst import directives from sphinx import addnodes -from sphinx.domains import Domain, ObjType +from sphinx.domains import ( + Domain, + Index, + IndexEntry, + ObjType, +) from sphinx.locale import _, __ from sphinx.util import logging from sphinx.util.docutils import SphinxDirective, switch_source_input @@ -74,9 +80,10 @@ class QAPIModule(SphinxDirective): a pass-through for the content body. Named section titles are allowed in the content body. - Use this directive to associate subsequent definitions with the - module they are defined in for purposes of search and QAPI index - organization. + Use this directive to create entries for the QAPI module in the + global index and the qapi index; as well as to associate subsequent + definitions with the module they are defined in for purposes of + search and QAPI index organization. :arg: The name of the module. :opt no-index: Don't add cross-reference targets or index entries. @@ -155,6 +162,52 @@ def run(self) -> List[Node]: return ret +class QAPIIndex(Index): + """ + Index subclass to provide the QAPI definition index. + """ + + name = "index" + localname = _("QAPI Index") + shortname = _("QAPI Index") + + def generate( + self, + docnames: Optional[Iterable[str]] = None, + ) -> Tuple[List[Tuple[str, List[IndexEntry]]], bool]: + assert isinstance(self.domain, QAPIDomain) + content: Dict[str, List[IndexEntry]] = {} + collapse = False + + # list of all object (name, ObjectEntry) pairs, sorted by name + objects = sorted(self.domain.objects.items(), key=lambda x: x[0].lower()) + + for objname, obj in objects: + if docnames and obj.docname not in docnames: + continue + + # Strip the module name out: + objname = objname.split(".")[-1] + + # Add an alphabetical entry: + entries = content.setdefault(objname[0].upper(), []) + entries.append( + IndexEntry(objname, 0, obj.docname, obj.node_id, obj.objtype, "", "") + ) + + # Add a categorical entry: + category = obj.objtype.title() + "s" + entries = content.setdefault(category, []) + entries.append(IndexEntry(objname, 0, obj.docname, obj.node_id, "", "", "")) + + # alphabetically sort categories; type names first, ABC entries last. + sorted_content = sorted( + content.items(), + key=lambda x: (len(x[0]) == 1, x[0]), + ) + return sorted_content, collapse + + class QAPIDomain(Domain): """QAPI language domain.""" @@ -182,7 +235,10 @@ class QAPIDomain(Domain): "objects": {}, # fullname -> ObjectEntry } - indices = [] + # Index pages to generate; each entry is an Index class. + indices = [ + QAPIIndex, + ] @property def objects(self) -> Dict[str, ObjectEntry]: From patchwork Fri Apr 19 04:37:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 13635663 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 049C5C4345F for ; Fri, 19 Apr 2024 04:40:05 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rxg1C-0007SC-K4; Fri, 19 Apr 2024 00:38:34 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1A-0007PB-Df for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:32 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg17-00049u-SI for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:32 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713501509; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=eGh0Yo04442PQ/AzZ8ROlY8swRWkIkztCTSNUHGcCT0=; b=NtJCURMQ367FQplZwNy6/nOI+KMRkmIyKr1mMxTGGtP5v1RwkEeYYhBV8l2u0GmY1bJX34 2N4YiR9zR8Kst/NE88T82MsBlU9silipDZVI+go175QFZNZ546tbgyoiZPp54CeEoHFKhU l2HEGTtA9TrfYIxlWJVxx4OR1bCDzq8= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-6-nQvZ5gL6MMeY3PtFUAa08Q-1; Fri, 19 Apr 2024 00:38:25 -0400 X-MC-Unique: nQvZ5gL6MMeY3PtFUAa08Q-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 5C4251C0C66A; Fri, 19 Apr 2024 04:38:25 +0000 (UTC) Received: from scv.redhat.com (unknown [10.22.8.7]) by smtp.corp.redhat.com (Postfix) with ESMTP id A81EC40829C3; Fri, 19 Apr 2024 04:38:24 +0000 (UTC) From: John Snow To: qemu-devel@nongnu.org Cc: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , Markus Armbruster , Victor Toso de Carvalho , Peter Maydell , Paolo Bonzini , John Snow Subject: [PATCH 05/27] docs/qapi-domain: add resolve_any_xref() Date: Fri, 19 Apr 2024 00:37:53 -0400 Message-ID: <20240419043820.178731-6-jsnow@redhat.com> In-Reply-To: <20240419043820.178731-1-jsnow@redhat.com> References: <20240419043820.178731-1-jsnow@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 Received-SPF: pass client-ip=170.10.133.124; envelope-from=jsnow@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.067, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Add the ability to resolve cross-references using the `any` cross-reference syntax. Adding QAPI-specific cross-reference roles will be added in a forthcoming commit, and will share the same find_obj() helper. (There's less code needed for the generic cross-reference resolver, so it comes first in this series.) Once again, this code is based very heavily on sphinx.domains.python. Signed-off-by: John Snow --- docs/qapi/index.rst | 7 +++ docs/sphinx/qapi-domain.py | 95 +++++++++++++++++++++++++++++++++++++- 2 files changed, 101 insertions(+), 1 deletion(-) diff --git a/docs/qapi/index.rst b/docs/qapi/index.rst index 051dc6b3a37..39ad405fd93 100644 --- a/docs/qapi/index.rst +++ b/docs/qapi/index.rst @@ -40,3 +40,10 @@ QAPI Domain Test Modules will also be reported in the `qapi-index`, under the Modules category and in the alphabetical categories that follow. + + +QAPI modules can now be cross-referenced using the ```any``` +cross-referencing syntax. Here's a link to `bar-module`, even though +the actual output of that directive was suppressed. Here's a link to +`block-core`. A link to ```foo-module``` won't resolve because of the +``:no-index:`` option we used for that directive. diff --git a/docs/sphinx/qapi-domain.py b/docs/sphinx/qapi-domain.py index 65409786119..4758451ff0e 100644 --- a/docs/sphinx/qapi-domain.py +++ b/docs/sphinx/qapi-domain.py @@ -21,6 +21,7 @@ from docutils.parsers.rst import directives from sphinx import addnodes +from sphinx.addnodes import pending_xref from sphinx.domains import ( Domain, Index, @@ -30,13 +31,19 @@ from sphinx.locale import _, __ from sphinx.util import logging from sphinx.util.docutils import SphinxDirective, switch_source_input -from sphinx.util.nodes import make_id, nested_parse_with_titles +from sphinx.util.nodes import ( + make_id, + make_refnode, + nested_parse_with_titles, +) if TYPE_CHECKING: from docutils.nodes import Element, Node from sphinx.application import Sphinx + from sphinx.builders import Builder + from sphinx.environment import BuildEnvironment from sphinx.util.typing import OptionSpec logger = logging.getLogger(__name__) @@ -289,6 +296,92 @@ def merge_domaindata(self, docnames: List[str], otherdata: Dict[str, Any]) -> No ), f"!?!? collision on merge? {fullname=} {obj=} {self.objects[fullname]=}" self.objects[fullname] = obj + def find_obj( + self, modname: str, name: str, type: Optional[str] + ) -> list[tuple[str, ObjectEntry]]: + """ + Find a QAPI object for "name", perhaps using the given module. + + Returns a list of (name, object entry) tuples. + + :param modname: The current module context (if any!) + under which we are searching. + :param name: The name of the x-ref to resolve; + may or may not include a leading module. + :param type: The role name of the x-ref we're resolving, if provided. + (This is absent for "any" lookups.) + """ + if not name: + return [] + + names: list[str] = [] + matches: list[tuple[str, ObjectEntry]] = [] + + fullname = name + if "." in fullname: + # We're searching for a fully qualified reference; + # ignore the contextual module. + pass + elif modname: + # We're searching for something from somewhere; + # try searching the current module first. + # e.g. :qapi:cmd:`query-block` or `query-block` is being searched. + fullname = f"{modname}.{name}" + + if type is None: + # type isn't specified, this is a generic xref. + # search *all* qapi-specific object types. + objtypes: Optional[List[str]] = list(self.object_types) + else: + # type is specified and will be a role (e.g. obj, mod, cmd) + # convert this to eligible object types (e.g. command, module) + # using the QAPIDomain.object_types table. + objtypes = self.objtypes_for_role(type) + + # Either we should have been given no type, or the type we were + # given should correspond to at least one real actual object + # type. + assert objtypes + + if name in self.objects and self.objects[name].objtype in objtypes: + names = [name] + elif fullname in self.objects and self.objects[fullname].objtype in objtypes: + names = [fullname] + else: + # exact match wasn't found; e.g. we are searching for + # `query-block` from a different (or no) module. + searchname = "." + name + names = [ + oname + for oname in self.objects + if oname.endswith(searchname) + and self.objects[oname].objtype in objtypes + ] + + matches = [(oname, self.objects[oname]) for oname in names] + if len(matches) > 1: + matches = [m for m in matches if not m[1].aliased] + return matches + + def resolve_any_xref( + self, + env: BuildEnvironment, + fromdocname: str, + builder: Builder, + target: str, + node: pending_xref, + contnode: Element, + ) -> list[tuple[str, Element]]: + results: list[tuple[str, Element]] = [] + matches = self.find_obj(node.get("qapi:module"), target, None) + for name, obj in matches: + role = "qapi:" + self.role_for_objtype(obj.objtype) + refnode = make_refnode( + builder, fromdocname, obj.docname, obj.node_id, contnode, name + ) + results.append((role, refnode)) + return results + def setup(app: Sphinx) -> Dict[str, Any]: app.setup_extension("sphinx.directives") From patchwork Fri Apr 19 04:37:54 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 13635657 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A36ABC4345F for ; Fri, 19 Apr 2024 04:39:35 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rxg1F-0007Se-IW; Fri, 19 Apr 2024 00:38:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1A-0007P2-9P for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:32 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg17-00049g-UF for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:32 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713501508; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=tbx+fvhdbNSPrwljvaeH4rMdFjLjZX/GTuVJYLukLjo=; b=Ln8/pfuDGf/OgaCglUjAVuSwhWF9DZQbbyt8MjZH1p3V+P4mo5rl2vi26hpmZIEhxyN93i 9YCbvqAWlibTkAKWGm1j5KvTWzO9usH4BdR1O2jwOAn1CAnAb5AsXDJg4nw2di0vKrS8KD HSw7WSWbNc94s3ChLU7x3RYEvM8w/nc= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-74-FLHQZqTUPCie_RCVCD2E4g-1; Fri, 19 Apr 2024 00:38:26 -0400 X-MC-Unique: FLHQZqTUPCie_RCVCD2E4g-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 1ABD9811001; Fri, 19 Apr 2024 04:38:26 +0000 (UTC) Received: from scv.redhat.com (unknown [10.22.8.7]) by smtp.corp.redhat.com (Postfix) with ESMTP id 69CA140C1233; Fri, 19 Apr 2024 04:38:25 +0000 (UTC) From: John Snow To: qemu-devel@nongnu.org Cc: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , Markus Armbruster , Victor Toso de Carvalho , Peter Maydell , Paolo Bonzini , John Snow Subject: [PATCH 06/27] docs/qapi-domain: add QAPI xref roles Date: Fri, 19 Apr 2024 00:37:54 -0400 Message-ID: <20240419043820.178731-7-jsnow@redhat.com> In-Reply-To: <20240419043820.178731-1-jsnow@redhat.com> References: <20240419043820.178731-1-jsnow@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 Received-SPF: pass client-ip=170.10.133.124; envelope-from=jsnow@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.067, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Add domain-specific cross-reference syntax. As of this commit, that means new :qapi:mod:`block-core` and :qapi:obj:`block-core` referencing syntax. :mod: will only find modules, but :obj: will find anything registered to the QAPI domain. (In forthcoming commits, this means commands, events, enums, etc.) Creating the cross-references is powered by the QAPIXRefRole class; resolving them is handled by QAPIDomain.resolve_xref(). QAPIXrefRole is copied almost verbatim from Sphinx's own PyXrefRole. PyXrefRole (and QAPIXrefRole) adds two features over the base class: (1) Creating a cross-reference with e.g. :py:class:`~class.name` instructs sphinx to omit the fully qualified parts of the resolved name from the actual link text. This may be useful in the future if we add namespaces to QAPI documentation, e.g. :qapi:cmd:`~qsd.blockdev-backup` could link to the QSD-specific documentation for blockdev-backup while omitting that prefix from the link text. (2) Prefixing the link target with a "." changes the search behavior to prefer locally-scoped items first. I think both of these are worth keeping to help manage future namespace issues between QEMU, QSD and QGA; but it's possible it's extraneous. It may possibly be worth keeping just to keep feature parity with Sphinx's other domains; e.g. "principle of least surprise". Dunno. Signed-off-by: John Snow --- docs/qapi/index.rst | 4 +++ docs/sphinx/qapi-domain.py | 67 +++++++++++++++++++++++++++++++++++++- 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/docs/qapi/index.rst b/docs/qapi/index.rst index 39ad405fd93..e2223d5f363 100644 --- a/docs/qapi/index.rst +++ b/docs/qapi/index.rst @@ -47,3 +47,7 @@ cross-referencing syntax. Here's a link to `bar-module`, even though the actual output of that directive was suppressed. Here's a link to `block-core`. A link to ```foo-module``` won't resolve because of the ``:no-index:`` option we used for that directive. + +Explicit cross-referencing syntax for QAPI modules is available with +``:qapi:mod:`foo```, here's a link to :qapi:mod:`bar-module` and one to +:qapi:mod:`block-core`. diff --git a/docs/sphinx/qapi-domain.py b/docs/sphinx/qapi-domain.py index 4758451ff0e..d28ac1cb9d8 100644 --- a/docs/sphinx/qapi-domain.py +++ b/docs/sphinx/qapi-domain.py @@ -29,6 +29,7 @@ ObjType, ) from sphinx.locale import _, __ +from sphinx.roles import XRefRole from sphinx.util import logging from sphinx.util.docutils import SphinxDirective, switch_source_input from sphinx.util.nodes import ( @@ -56,6 +57,34 @@ class ObjectEntry(NamedTuple): aliased: bool +class QAPIXRefRole(XRefRole): + def process_link( + self, + env: BuildEnvironment, + refnode: Element, + has_explicit_title: bool, + title: str, + target: str, + ) -> tuple[str, str]: + refnode["qapi:module"] = env.ref_context.get("qapi:module") + if not has_explicit_title: + title = title.lstrip(".") # only has a meaning for the target + target = target.lstrip("~") # only has a meaning for the title + # if the first character is a tilde, don't display the module + # parts of the contents + if title[0:1] == "~": + title = title[1:] + dot = title.rfind(".") + if dot != -1: + title = title[dot + 1 :] + # if the first character is a dot, search more specific namespaces first + # else search builtins first + if target[0:1] == ".": + target = target[1:] + refnode["refspecific"] = True + return title, target + + def _nested_parse(directive: SphinxDirective, content_node: Element) -> None: """ This helper preserves error parsing context across sphinx versions. @@ -234,7 +263,13 @@ class QAPIDomain(Domain): "module": QAPIModule, } - roles = {} + # These are all cross-reference roles; e.g. + # :qapi:cmd:`query-block`. The keys correlate to the names used in + # the object_types table values above. + roles = { + "mod": QAPIXRefRole(), + "obj": QAPIXRefRole(), # reference *any* type of QAPI object. + } # Moved into the data property at runtime; # this is the internal index of reference-able objects. @@ -363,6 +398,36 @@ def find_obj( matches = [m for m in matches if not m[1].aliased] return matches + def resolve_xref( + self, + env: BuildEnvironment, + fromdocname: str, + builder: Builder, + type: str, + target: str, + node: pending_xref, + contnode: Element, + ) -> Element | None: + modname = node.get("qapi:module") + matches = self.find_obj(modname, target, type) + multiple_matches = len(matches) > 1 + + if not matches: + return None + elif multiple_matches: + logger.warning( + __("more than one target found for cross-reference %r: %s"), + target, + ", ".join(match[0] for match in matches), + type="ref", + subtype="qapi", + location=node, + ) + name, obj = matches[0] + return make_refnode( + builder, fromdocname, obj.docname, obj.node_id, contnode, name + ) + def resolve_any_xref( self, env: BuildEnvironment, From patchwork Fri Apr 19 04:37:55 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 13635665 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 80F16C4345F for ; Fri, 19 Apr 2024 04:40:34 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rxg1I-0007Tt-H8; Fri, 19 Apr 2024 00:38:43 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1A-0007PO-Ko for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:32 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg18-00049w-0V for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:32 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713501509; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=3l3KznzN5IC/sqY7udLFwiu1omnR5f9e149VssCm8M4=; b=JmWjrzpmFhYnSTyIligfZt0CudonvyYQejTacTfW7pmDwy+37PG4fBx1E1Ka7OOPX4zRil fUmNSz0bvzWwaeQNzEo8oMRlSHWZiBYBuE0YYMG0wXMCprfvjkLjRFA4gNj71tPD9WlD3x iGML9YHJlf9w0nOsrey3Mj697J41h4s= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-263-tUZYw9Z_MqylqBWHWXXE0A-1; Fri, 19 Apr 2024 00:38:27 -0400 X-MC-Unique: tUZYw9Z_MqylqBWHWXXE0A-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id CE9DE286A9D6; Fri, 19 Apr 2024 04:38:26 +0000 (UTC) Received: from scv.redhat.com (unknown [10.22.8.7]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2BC664011FF7; Fri, 19 Apr 2024 04:38:26 +0000 (UTC) From: John Snow To: qemu-devel@nongnu.org Cc: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , Markus Armbruster , Victor Toso de Carvalho , Peter Maydell , Paolo Bonzini , John Snow Subject: [PATCH 07/27] docs/qapi-domain: add qapi:command directive Date: Fri, 19 Apr 2024 00:37:55 -0400 Message-ID: <20240419043820.178731-8-jsnow@redhat.com> In-Reply-To: <20240419043820.178731-1-jsnow@redhat.com> References: <20240419043820.178731-1-jsnow@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 Received-SPF: pass client-ip=170.10.129.124; envelope-from=jsnow@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.067, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org This commit adds a generic QAPIObject class for use in documenting various QAPI entities in the Sphinx ecosystem. It also adds a stubbed version of QAPICommand that utilizes the QAPIObject class; along with the qapi:command directive, the :qapi:cmd: cross-reference role, and the "command" object type in the QAPI object registry. They don't do anything *particularly* interesting yet, but that will come in forthcoming commits. Note: some versions of mypy get a little confused over the difference between class and instance variables; because sphinx's ObjectDescription does not declare option_spec as a ClassVar (even though it's obvious that it is), mypy may produce this error: qapi-domain.py:125: error: Cannot override instance variable (previously declared on base class "ObjectDescription") with class variable [misc] I can't control that; so silence the error with a pragma. Signed-off-by: John Snow --- docs/qapi/index.rst | 34 ++++++++++ docs/sphinx/qapi-domain.py | 132 ++++++++++++++++++++++++++++++++++++- 2 files changed, 165 insertions(+), 1 deletion(-) diff --git a/docs/qapi/index.rst b/docs/qapi/index.rst index e2223d5f363..5516f762a24 100644 --- a/docs/qapi/index.rst +++ b/docs/qapi/index.rst @@ -51,3 +51,37 @@ the actual output of that directive was suppressed. Here's a link to Explicit cross-referencing syntax for QAPI modules is available with ``:qapi:mod:`foo```, here's a link to :qapi:mod:`bar-module` and one to :qapi:mod:`block-core`. + + +.. qapi:command:: example-command + + This directive creates a QAPI command named `example-command` that + appears in both the `genindex` and the `qapi-index`. As of this + commit, there aren't any special arguments or options you can give to + this directive, it merely parses its content block and handles the + TOC/index/xref book-keeping. + + Unlike the QAPI module directive, this directive *does* add a TOC + entry by default. + + This object can be referenced in *quite a few ways*: + + * ```example-command``` => `example-command` + * ```block-core.example-command``` => `block-core.example-command` + * ``:qapi:cmd:`example-command``` => :qapi:cmd:`example-command` + * ``:qapi:cmd:`block-core.example-command``` => :qapi:cmd:`block-core.example-command` + * ``:qapi:cmd:`~example-command``` => :qapi:cmd:`~example-command` + * ``:qapi:cmd:`~block-core.example-command``` => :qapi:cmd:`~block-core.example-command` + * ``:qapi:obj:`example-command``` => :qapi:obj:`example-command` + * ``:qapi:obj:`block-core.example-command``` => :qapi:obj:`block-core.example-command` + * ``:qapi:obj:`~example-command``` => :qapi:obj:`~example-command` + * ``:qapi:obj:`~block-core.example-command``` => :qapi:obj:`~block-core.example-command` + + As of Sphinx v7.2.6, there are a few sphinx-standard options this + directive has: + + * ``:no-index:`` or ``:noindex:`` Don't add to the `genindex` nor + the `qapi-index`; do not register for cross-references. + * ``:no-index-entry:`` or ``:noindexentry:`` + * ``:no-contents-entry:`` or ``:nocontentsentry:`` + * ``:no-typesetting:`` diff --git a/docs/sphinx/qapi-domain.py b/docs/sphinx/qapi-domain.py index d28ac1cb9d8..2c1e60290d9 100644 --- a/docs/sphinx/qapi-domain.py +++ b/docs/sphinx/qapi-domain.py @@ -21,7 +21,8 @@ from docutils.parsers.rst import directives from sphinx import addnodes -from sphinx.addnodes import pending_xref +from sphinx.addnodes import desc_signature, pending_xref +from sphinx.directives import ObjectDescription from sphinx.domains import ( Domain, Index, @@ -108,6 +109,132 @@ def _nested_parse(directive: SphinxDirective, content_node: Element) -> None: nested_parse_with_titles(directive.state, directive.content, content_node) +# Alias for the return of handle_signature(), which is used in several places. +# (In the Python domain, this is Tuple[str, str] instead.) +Signature = str + + +class QAPIObject(ObjectDescription[Signature]): + """ + Description of a generic QAPI object. + + It's not used directly, but is instead subclassed by specific directives. + """ + + # Inherit some standard options from Sphinx's ObjectDescription + option_spec: OptionSpec = ObjectDescription.option_spec.copy() # type:ignore[misc] + option_spec.update( + { + # Borrowed from the Python domain: + "module": directives.unchanged, # Override contextual module name + } + ) + + def get_signature_prefix(self, sig: str) -> List[nodes.Node]: + """Returns a prefix to put before the object name in the signature.""" + assert self.objtype + return [ + addnodes.desc_sig_keyword("", self.objtype.title()), + addnodes.desc_sig_space(), + ] + + def get_signature_suffix(self, sig: str) -> list[nodes.Node]: + """Returns a suffix to put after the object name in the signature.""" + return [] + + def handle_signature(self, sig: str, signode: desc_signature) -> Signature: + """ + Transform a QAPI definition name into RST nodes. + + This method was originally intended for handling function + signatures. In the QAPI domain, however, we only pass the + command name as the directive argument and handle everything + else in the content body with field lists. + + As such, the only argument here is "sig", which is just the QAPI + definition name. + """ + modname = self.options.get("module", self.env.ref_context.get("qapi:module")) + + signode["fullname"] = sig + signode["module"] = modname + sig_prefix = self.get_signature_prefix(sig) + if sig_prefix: + signode += addnodes.desc_annotation(str(sig_prefix), "", *sig_prefix) + signode += addnodes.desc_name(sig, sig) + signode += self.get_signature_suffix(sig) + + return sig + + def _object_hierarchy_parts(self, sig_node: desc_signature) -> Tuple[str, ...]: + if "fullname" not in sig_node: + return () + modname = sig_node.get("module") + fullname = sig_node["fullname"] + + if modname: + return (modname, *fullname.split(".")) + else: + return tuple(fullname.split(".")) + + def get_index_text(self, modname: str, name: Signature) -> str: + """Return the text for the index entry of the object.""" + # NB this is used for the global index, not the QAPI index. + return f"{name} (QMP {self.objtype})" + + def add_target_and_index( + self, name: Signature, sig: str, signode: desc_signature + ) -> None: + # Called by ObjectDescription.run with the result of + # handle_signature; name is the return value of handle_signature + # where sig is the original argument to handle_signature. In our + # case, they're the same for now. + assert self.objtype + + modname = self.options.get("module", self.env.ref_context.get("qapi:module")) + # Here, sphinx decides to prepend the module name. OK. + fullname = (modname + "." if modname else "") + name + node_id = make_id(self.env, self.state.document, "", fullname) + signode["ids"].append(node_id) + self.state.document.note_explicit_target(signode) + + domain = cast(QAPIDomain, self.env.get_domain("qapi")) + domain.note_object(fullname, self.objtype, node_id, location=signode) + + if "no-index-entry" not in self.options: + indextext = self.get_index_text(modname, name) + assert self.indexnode is not None + if indextext: + self.indexnode["entries"].append( + ("single", indextext, node_id, "", None) + ) + + def _toc_entry_name(self, sig_node: desc_signature) -> str: + # This controls the name in the TOC and on the sidebar. + + # This is the return type of _object_hierarchy_parts(). + toc_parts = cast(Tuple[str, ...], sig_node.get("_toc_parts", ())) + if not toc_parts: + return "" + + config = self.env.app.config + *parents, name = toc_parts + if config.toc_object_entries_show_parents == "domain": + return sig_node.get("fullname", name) + if config.toc_object_entries_show_parents == "hide": + return name + if config.toc_object_entries_show_parents == "all": + return ".".join(parents + [name]) + return "" + + +class QAPICommand(QAPIObject): + """Description of a QAPI Command.""" + + # Nothing unique for now! Changed in later commits O:-) + pass + + class QAPIModule(SphinxDirective): """ Directive to mark description of a new module. @@ -255,12 +382,14 @@ class QAPIDomain(Domain): # for each object type. object_types: Dict[str, ObjType] = { "module": ObjType(_("module"), "mod", "obj"), + "command": ObjType(_("command"), "cmd", "obj"), } # Each of these provides a ReST directive, # e.g. .. qapi:module:: block-core directives = { "module": QAPIModule, + "command": QAPICommand, } # These are all cross-reference roles; e.g. @@ -268,6 +397,7 @@ class QAPIDomain(Domain): # the object_types table values above. roles = { "mod": QAPIXRefRole(), + "cmd": QAPIXRefRole(), "obj": QAPIXRefRole(), # reference *any* type of QAPI object. } From patchwork Fri Apr 19 04:37:56 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 13635681 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 33327C4345F for ; Fri, 19 Apr 2024 04:42:28 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rxg1P-0007Vp-Jm; Fri, 19 Apr 2024 00:38:47 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1B-0007Qi-N4 for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:33 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg19-0004Bk-TC for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:33 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713501511; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=jeEOPzwkWscQq9TY4wDhSicoLO1pGuzMnN5NiFEv/iQ=; b=HjjeNFcSpImehL7mhi7CKmt/yhLMFs1HpYO60X+a2i+p+X7IYW1yMvVEmL9EWNlpCKYi6p Kc2fOvoVbh3u2NP2LF8dk41fSSLQHNH/J8vLhpW9gxl9wggQWHgZd2yQLEd3SCsiV93jSy n6i04x422dMWwy8n9AwUJDIGdZjCsqw= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-636-MID9YDE6MWGELDINiLZMew-1; Fri, 19 Apr 2024 00:38:27 -0400 X-MC-Unique: MID9YDE6MWGELDINiLZMew-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 8F9CC104B501; Fri, 19 Apr 2024 04:38:27 +0000 (UTC) Received: from scv.redhat.com (unknown [10.22.8.7]) by smtp.corp.redhat.com (Postfix) with ESMTP id DF95B407F3D4; Fri, 19 Apr 2024 04:38:26 +0000 (UTC) From: John Snow To: qemu-devel@nongnu.org Cc: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , Markus Armbruster , Victor Toso de Carvalho , Peter Maydell , Paolo Bonzini , John Snow Subject: [PATCH 08/27] docs/qapi-domain: add :since: directive option Date: Fri, 19 Apr 2024 00:37:56 -0400 Message-ID: <20240419043820.178731-9-jsnow@redhat.com> In-Reply-To: <20240419043820.178731-1-jsnow@redhat.com> References: <20240419043820.178731-1-jsnow@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 Received-SPF: pass client-ip=170.10.133.124; envelope-from=jsnow@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.067, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Add a little special markup for registering "Since:" information. Adding it as an option instead of generic content lets us hoist the information into the Signature bar, optionally put it in the index, etc. Signed-off-by: John Snow --- docs/qapi/index.rst | 1 + docs/sphinx/qapi-domain.py | 27 +++++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/docs/qapi/index.rst b/docs/qapi/index.rst index 5516f762a24..33b9349a3ee 100644 --- a/docs/qapi/index.rst +++ b/docs/qapi/index.rst @@ -54,6 +54,7 @@ Explicit cross-referencing syntax for QAPI modules is available with .. qapi:command:: example-command + :since: 42.0 This directive creates a QAPI command named `example-command` that appears in both the `genindex` and the `qapi-index`. As of this diff --git a/docs/sphinx/qapi-domain.py b/docs/sphinx/qapi-domain.py index 2c1e60290d9..38a50318d08 100644 --- a/docs/sphinx/qapi-domain.py +++ b/docs/sphinx/qapi-domain.py @@ -4,6 +4,7 @@ from __future__ import annotations +import re from typing import ( TYPE_CHECKING, Any, @@ -86,6 +87,18 @@ def process_link( return title, target +def since_validator(param: str) -> str: + """ + Validate the `:since: X.Y` option field. + """ + match = re.match(r"[0-9]+\.[0-9]+", param) + if not match: + raise ValueError( + f":since: requires a version number in X.Y format; not {param!r}" + ) + return param + + def _nested_parse(directive: SphinxDirective, content_node: Element) -> None: """ This helper preserves error parsing context across sphinx versions. @@ -127,6 +140,8 @@ class QAPIObject(ObjectDescription[Signature]): { # Borrowed from the Python domain: "module": directives.unchanged, # Override contextual module name + # These are QAPI originals: + "since": since_validator, } ) @@ -138,9 +153,17 @@ def get_signature_prefix(self, sig: str) -> List[nodes.Node]: addnodes.desc_sig_space(), ] - def get_signature_suffix(self, sig: str) -> list[nodes.Node]: + def get_signature_suffix(self, sig: str) -> List[nodes.Node]: """Returns a suffix to put after the object name in the signature.""" - return [] + ret: List[nodes.Node] = [] + + if "since" in self.options: + ret += [ + addnodes.desc_sig_space(), + addnodes.desc_sig_element("", f"(Since: {self.options['since']})"), + ] + + return ret def handle_signature(self, sig: str, signode: desc_signature) -> Signature: """ From patchwork Fri Apr 19 04:37:57 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 13635664 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 8D71EC4345F for ; Fri, 19 Apr 2024 04:40:13 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rxg1N-0007VQ-Nk; Fri, 19 Apr 2024 00:38:46 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1B-0007Qf-MX for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:33 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg19-0004BS-6r for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:33 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713501510; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=3rcUHy7QSQh4ohx4ayY+RA7M+aNEuZhNoIheLxzP2v0=; b=QAY60fQ/IYaZjFUWwXK+yI43Ack92HYqfFDqBxiXXPa4lXGv6gBsDLQWp90S9trB36JBzn 6EDJ0YjKNH16z6d2zecQdkYqAY/sOMg8qR2WwX5eH8J5MUYCI1xYDP7KFmLIFGZfoJGBPi j/fsys5z85Db/9bpvsE/vNIPD2ClZrM= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-481-5uEvj-fxOCOF0PM9TX1-6Q-1; Fri, 19 Apr 2024 00:38:28 -0400 X-MC-Unique: 5uEvj-fxOCOF0PM9TX1-6Q-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 4F5623811F28; Fri, 19 Apr 2024 04:38:28 +0000 (UTC) Received: from scv.redhat.com (unknown [10.22.8.7]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9F23640C1233; Fri, 19 Apr 2024 04:38:27 +0000 (UTC) From: John Snow To: qemu-devel@nongnu.org Cc: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , Markus Armbruster , Victor Toso de Carvalho , Peter Maydell , Paolo Bonzini , John Snow Subject: [PATCH 09/27] docs/qapi-domain: add "Arguments:" field lists Date: Fri, 19 Apr 2024 00:37:57 -0400 Message-ID: <20240419043820.178731-10-jsnow@redhat.com> In-Reply-To: <20240419043820.178731-1-jsnow@redhat.com> References: <20240419043820.178731-1-jsnow@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 Received-SPF: pass client-ip=170.10.129.124; envelope-from=jsnow@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.067, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org This adds special rendering for Sphinx's typed field lists. This patch does not add any QAPI-aware markup, rendering, or cross-referencing for the type names, yet. That feature requires a subclass to TypedField which will happen in its own commit quite a bit later in this series; after all the basic fields and objects have been established first. The syntax for this field is: :arg type name: description description cont'd You can omit the type or the description, but you cannot omit the name -- if you do so, it degenerates into a "normal field list" entry, and probably isn't what you want. Signed-off-by: John Snow --- docs/qapi/index.rst | 15 +++++++++++++++ docs/sphinx/qapi-domain.py | 14 ++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/docs/qapi/index.rst b/docs/qapi/index.rst index 33b9349a3ee..197587bbc81 100644 --- a/docs/qapi/index.rst +++ b/docs/qapi/index.rst @@ -86,3 +86,18 @@ Explicit cross-referencing syntax for QAPI modules is available with * ``:no-index-entry:`` or ``:noindexentry:`` * ``:no-contents-entry:`` or ``:nocontentsentry:`` * ``:no-typesetting:`` + +.. qapi:command:: fake-command + :since: 13.37 + + This is a fake command, it's not real. It can't hurt you. + + :arg int foo: normal parameter documentation. + :arg str bar: Another normal parameter description. + :arg baz: Missing a type. + :arg no-descr: + + Field lists can appear anywhere in the directive block, but any field + list entries in the same list block that are recognized as special + ("arg") will be reformatted and grouped accordingly for rendered + output. diff --git a/docs/sphinx/qapi-domain.py b/docs/sphinx/qapi-domain.py index 38a50318d08..853bd91b7a8 100644 --- a/docs/sphinx/qapi-domain.py +++ b/docs/sphinx/qapi-domain.py @@ -33,6 +33,7 @@ from sphinx.locale import _, __ from sphinx.roles import XRefRole from sphinx.util import logging +from sphinx.util.docfields import TypedField from sphinx.util.docutils import SphinxDirective, switch_source_input from sphinx.util.nodes import ( make_id, @@ -254,8 +255,17 @@ def _toc_entry_name(self, sig_node: desc_signature) -> str: class QAPICommand(QAPIObject): """Description of a QAPI Command.""" - # Nothing unique for now! Changed in later commits O:-) - pass + doc_field_types = QAPIObject.doc_field_types.copy() + doc_field_types.extend( + [ + TypedField( + "argument", + label=_("Arguments"), + names=("arg",), + can_collapse=True, + ), + ] + ) class QAPIModule(SphinxDirective): From patchwork Fri Apr 19 04:37:58 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 13635672 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6B18DC4345F for ; Fri, 19 Apr 2024 04:41:02 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rxg1N-0007Uy-6w; Fri, 19 Apr 2024 00:38:45 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1C-0007R7-0W for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:34 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg19-0004Bi-W7 for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:33 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713501511; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ZtfPOVc2sq5gvEb2kNhiQ+7sghfVmy34SoiYv6DOq5U=; b=ZEHmPehC4yr9WVeruMDn3iWIvyy0G8TxFWb+iby6vAGEhWJVw5HZU4iDYXwqV+5Btxz9TW Ydm73k2+h6OJs3IwyxGqCI8L9BXrZ3pWdpoemPTxr9k1G5TZP6auvhCX7Uzhavyy0gxNXF GvlmDMU+nC4RAtKH32VcDshcJ0vgfbI= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-209-_gerOnxrMACSfH8DytaZbQ-1; Fri, 19 Apr 2024 00:38:29 -0400 X-MC-Unique: _gerOnxrMACSfH8DytaZbQ-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 0D7CD834FB1; Fri, 19 Apr 2024 04:38:29 +0000 (UTC) Received: from scv.redhat.com (unknown [10.22.8.7]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5D1B140357A7; Fri, 19 Apr 2024 04:38:28 +0000 (UTC) From: John Snow To: qemu-devel@nongnu.org Cc: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , Markus Armbruster , Victor Toso de Carvalho , Peter Maydell , Paolo Bonzini , John Snow Subject: [PATCH 10/27] docs/qapi-domain: add "Features:" field lists Date: Fri, 19 Apr 2024 00:37:58 -0400 Message-ID: <20240419043820.178731-11-jsnow@redhat.com> In-Reply-To: <20240419043820.178731-1-jsnow@redhat.com> References: <20240419043820.178731-1-jsnow@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 Received-SPF: pass client-ip=170.10.129.124; envelope-from=jsnow@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.067, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Add support for Features field lists. There is no QAPI-specific functionality here, but this could be changed if desired (if we wanted the feature names to link somewhere, for instance.) This feature list doesn't have any restrictions, so it can be used to document object-wide features or per-member features as deemed appropriate. It's essentially free-form text. Signed-off-by: John Snow --- docs/qapi/index.rst | 6 ++++++ docs/sphinx/qapi-domain.py | 11 ++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/docs/qapi/index.rst b/docs/qapi/index.rst index 197587bbc81..a570c37abb2 100644 --- a/docs/qapi/index.rst +++ b/docs/qapi/index.rst @@ -95,9 +95,15 @@ Explicit cross-referencing syntax for QAPI modules is available with :arg int foo: normal parameter documentation. :arg str bar: Another normal parameter description. :arg baz: Missing a type. + :feat unstable: More than unstable, this command doesn't even exist! :arg no-descr: + :feat hallucination: This command is a figment of your imagination. Field lists can appear anywhere in the directive block, but any field list entries in the same list block that are recognized as special ("arg") will be reformatted and grouped accordingly for rendered output. + + At the moment, the order of grouped sections is based on the order in + which each group was encountered. This example will render Arguments + first, and then Features; but the order can be any that you choose. diff --git a/docs/sphinx/qapi-domain.py b/docs/sphinx/qapi-domain.py index 853bd91b7a8..c0dc6482204 100644 --- a/docs/sphinx/qapi-domain.py +++ b/docs/sphinx/qapi-domain.py @@ -33,7 +33,7 @@ from sphinx.locale import _, __ from sphinx.roles import XRefRole from sphinx.util import logging -from sphinx.util.docfields import TypedField +from sphinx.util.docfields import GroupedField, TypedField from sphinx.util.docutils import SphinxDirective, switch_source_input from sphinx.util.nodes import ( make_id, @@ -146,6 +146,15 @@ class QAPIObject(ObjectDescription[Signature]): } ) + doc_field_types = [ + GroupedField( + "feature", + label=_("Features"), + names=("feat",), + can_collapse=True, + ), + ] + def get_signature_prefix(self, sig: str) -> List[nodes.Node]: """Returns a prefix to put before the object name in the signature.""" assert self.objtype From patchwork Fri Apr 19 04:37:59 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 13635675 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A6634C05052 for ; Fri, 19 Apr 2024 04:41:05 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rxg1P-0007Vf-3q; Fri, 19 Apr 2024 00:38:47 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1C-0007SI-LZ for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:34 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1A-0004C4-O3 for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:34 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713501512; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Rtuow9SNA+OVjXTxvHwCUSUMwDlRyPh0+mhQGPz8ocQ=; b=VutQ0i6FwiaEiHxyqi9rlTvJN3rrwuDFxaKssvCM6m7jcLhp2whjKmk5NpqAW7mvXfzrf/ 8UzwIe8Yw0TOylhIgc34BYdbYeBi7QP5GgLTQXTA1OBS0nnvliNFqez+1ZIfO/ARGne2N2 Xg6GB4Z9gjXQn2ZCfhFeaaHqrtnno+o= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-664-2eb8cY2_Nti9Q0RrmW0RXw-1; Fri, 19 Apr 2024 00:38:30 -0400 X-MC-Unique: 2eb8cY2_Nti9Q0RrmW0RXw-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id C054D104B500; Fri, 19 Apr 2024 04:38:29 +0000 (UTC) Received: from scv.redhat.com (unknown [10.22.8.7]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1A6864011FF7; Fri, 19 Apr 2024 04:38:29 +0000 (UTC) From: John Snow To: qemu-devel@nongnu.org Cc: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , Markus Armbruster , Victor Toso de Carvalho , Peter Maydell , Paolo Bonzini , John Snow Subject: [PATCH 11/27] docs/qapi-domain: add "Errors:" field lists Date: Fri, 19 Apr 2024 00:37:59 -0400 Message-ID: <20240419043820.178731-12-jsnow@redhat.com> In-Reply-To: <20240419043820.178731-1-jsnow@redhat.com> References: <20240419043820.178731-1-jsnow@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 Received-SPF: pass client-ip=170.10.133.124; envelope-from=jsnow@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.067, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org ``:error type: descr`` can now be used to document error conditions, naming the type of error object and a description of when the error is surfaced. Like the previous Arguments patch, this patch does not apply any special QAPI syntax highlighting or cross-referencing for the types, but this can be adjusted in the future if desired. (At present, I have no commits that add such highlighting. Sphinx also does not appear to support Grouped fields with optional (or no) parameters, so the ability to exclude error types is currently not supported. If you omit the type, Sphinx treats it as a regular field list and doesn't apply the special Grouping postprocessing to it.) Signed-off-by: John Snow --- docs/qapi/index.rst | 4 ++++ docs/sphinx/qapi-domain.py | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/docs/qapi/index.rst b/docs/qapi/index.rst index a570c37abb2..004d02e0437 100644 --- a/docs/qapi/index.rst +++ b/docs/qapi/index.rst @@ -98,6 +98,10 @@ Explicit cross-referencing syntax for QAPI modules is available with :feat unstable: More than unstable, this command doesn't even exist! :arg no-descr: :feat hallucination: This command is a figment of your imagination. + :error CommandNotFound: When you try to use this command, because it + isn't real. + :error GenericError: If the system decides it doesn't like the + argument values. It's very temperamental. Field lists can appear anywhere in the directive block, but any field list entries in the same list block that are recognized as special diff --git a/docs/sphinx/qapi-domain.py b/docs/sphinx/qapi-domain.py index c0dc6482204..1f0b168fa2c 100644 --- a/docs/sphinx/qapi-domain.py +++ b/docs/sphinx/qapi-domain.py @@ -273,6 +273,12 @@ class QAPICommand(QAPIObject): names=("arg",), can_collapse=True, ), + GroupedField( + "error", + label=_("Errors"), + names=("error",), + can_collapse=True, + ), ] ) From patchwork Fri Apr 19 04:38:00 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 13635661 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 1A413C4345F for ; Fri, 19 Apr 2024 04:40:01 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rxg1R-0007WZ-2I; Fri, 19 Apr 2024 00:38:49 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1E-0007T3-Ss for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:37 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1D-0004Cq-AX for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:36 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713501514; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=yOsxkzvTq7IGxliGWm/dx2GKasAtz6w02bAJhwB0Zoc=; b=KJzcAJGOtipIy7wQCLVPqYHN3V8Ft0kaW2uJHfHIEojFyZhe1WLhHa5O7k+4GAX/0/KU+a MoqqcfJ2fF9h7qYKZ4Ct4tGD6BMOYZq/2mHLNgfw5EmOK47XVLx4uPcXn7RTbU4S7seiMh sz8v+Di0t9cJ2wKYxhkDg3HFQR2gN/k= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-387-wAVLQq9LMBqcTy1WmDHpcQ-1; Fri, 19 Apr 2024 00:38:30 -0400 X-MC-Unique: wAVLQq9LMBqcTy1WmDHpcQ-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 7F12C8948A1; Fri, 19 Apr 2024 04:38:30 +0000 (UTC) Received: from scv.redhat.com (unknown [10.22.8.7]) by smtp.corp.redhat.com (Postfix) with ESMTP id CDFC840829C3; Fri, 19 Apr 2024 04:38:29 +0000 (UTC) From: John Snow To: qemu-devel@nongnu.org Cc: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , Markus Armbruster , Victor Toso de Carvalho , Peter Maydell , Paolo Bonzini , John Snow Subject: [PATCH 12/27] docs/qapi-domain: add "Returns:" field lists Date: Fri, 19 Apr 2024 00:38:00 -0400 Message-ID: <20240419043820.178731-13-jsnow@redhat.com> In-Reply-To: <20240419043820.178731-1-jsnow@redhat.com> References: <20240419043820.178731-1-jsnow@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 Received-SPF: pass client-ip=170.10.129.124; envelope-from=jsnow@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.067, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Add "Returns:" field list syntax to QAPI Commands. Like "Arguments:" and "Errors:", the type name isn't currently processed for cross-referencing, but this will be addressed in a forthcoming commit. This patch adds "errors" as a GroupedField, which means that multiple return values can be annotated - this is only done because Sphinx does not seemingly (Maybe I missed it?) support mandatory type arguments to Ungrouped fields. Because we want to cross-reference this type information later, we want to make the type argument mandatory. As a result, you can technically add multiple :return: fields, though I'm not aware of any circumstance in which you'd need or want to. Recommendation: "Don't do that, then." Since this field describes an action/event instead of describing a list of nouns (arguments, features, errors), I added both the imperative and indicative forms (:return: and :returns:) to allow doc writers to use whichever mood "feels right" in the source document. The rendered output will always use the "Returns:" label, however. I'm sure you'll let me know how you feel about that. O:-) Signed-off-by: John Snow --- docs/qapi/index.rst | 2 ++ docs/sphinx/qapi-domain.py | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/docs/qapi/index.rst b/docs/qapi/index.rst index 004d02e0437..39fe4dd2dae 100644 --- a/docs/qapi/index.rst +++ b/docs/qapi/index.rst @@ -102,6 +102,8 @@ Explicit cross-referencing syntax for QAPI modules is available with isn't real. :error GenericError: If the system decides it doesn't like the argument values. It's very temperamental. + :return SomeTypeName: An esoteric collection of mystical nonsense to + both confound and delight. Field lists can appear anywhere in the directive block, but any field list entries in the same list block that are recognized as special diff --git a/docs/sphinx/qapi-domain.py b/docs/sphinx/qapi-domain.py index 1f0b168fa2c..5d44dba6cd3 100644 --- a/docs/sphinx/qapi-domain.py +++ b/docs/sphinx/qapi-domain.py @@ -279,6 +279,12 @@ class QAPICommand(QAPIObject): names=("error",), can_collapse=True, ), + GroupedField( + "returnvalue", + label=_("Returns"), + names=("return", "returns"), + can_collapse=True, + ), ] ) From patchwork Fri Apr 19 04:38:01 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 13635677 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C369CC41513 for ; Fri, 19 Apr 2024 04:41:18 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rxg1Q-0007WB-4q; Fri, 19 Apr 2024 00:38:48 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1D-0007Sz-Hi for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:36 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1B-0004CR-Nl for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:35 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713501513; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=xZb3TsU5dn/OiwuiJ8Lgb86sXV43UMJ+Lx/puhmv714=; b=RtI/GNvFODtGxKMqTEGXfboGlhEwv/kpZSPS1kNE81sawl1943vnJOPFIppJVBkwsmroiG 8bRcgJAT42OwlvsetJiMm/CVIbjFgEhvWoteSEqGO35HzfBwg4ag1sydeYKHaLKjgAuTks 3yKLkj07IvhHld76SrPU8KVkq3lI2/4= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-433-J7BqDJWKNNuBO3mjP7zT3w-1; Fri, 19 Apr 2024 00:38:31 -0400 X-MC-Unique: J7BqDJWKNNuBO3mjP7zT3w-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 3BF3280021A; Fri, 19 Apr 2024 04:38:31 +0000 (UTC) Received: from scv.redhat.com (unknown [10.22.8.7]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8BC03407F3D5; Fri, 19 Apr 2024 04:38:30 +0000 (UTC) From: John Snow To: qemu-devel@nongnu.org Cc: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , Markus Armbruster , Victor Toso de Carvalho , Peter Maydell , Paolo Bonzini , John Snow Subject: [PATCH 13/27] docs/qapi-domain: add qapi:enum directive Date: Fri, 19 Apr 2024 00:38:01 -0400 Message-ID: <20240419043820.178731-14-jsnow@redhat.com> In-Reply-To: <20240419043820.178731-1-jsnow@redhat.com> References: <20240419043820.178731-1-jsnow@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 Received-SPF: pass client-ip=170.10.129.124; envelope-from=jsnow@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.067, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Add the .. qapi:enum:: directive, object, and :qapi:enum:`name` cross-reference role. Add the :value name: field list for documenting Enum values. Of note, also introduce a new "type" role that is intended to be used by other QAPI object directives to cross-reference arbitrary QAPI type names, but will exclude commands, events, and modules from consideration. Signed-off-by: John Snow --- docs/qapi/index.rst | 14 ++++++++++++++ docs/sphinx/qapi-domain.py | 24 ++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/docs/qapi/index.rst b/docs/qapi/index.rst index 39fe4dd2dae..cf794e6e739 100644 --- a/docs/qapi/index.rst +++ b/docs/qapi/index.rst @@ -113,3 +113,17 @@ Explicit cross-referencing syntax for QAPI modules is available with At the moment, the order of grouped sections is based on the order in which each group was encountered. This example will render Arguments first, and then Features; but the order can be any that you choose. + +.. qapi:enum:: BitmapSyncMode + :since: 4.2 + + An enumeration of possible behaviors for the synchronization of a + bitmap when used for data copy operations. + + :value on-success: The bitmap is only synced when the operation is + successful. This is the behavior always used for + ``INCREMENTAL`` backups. + :value never: The bitmap is never synchronized with the operation, and + is treated solely as a read-only manifest of blocks to copy. + :value always: The bitmap is always synchronized with the operation, + regardless of whether or not the operation was successful. diff --git a/docs/sphinx/qapi-domain.py b/docs/sphinx/qapi-domain.py index 5d44dba6cd3..6759c39290d 100644 --- a/docs/sphinx/qapi-domain.py +++ b/docs/sphinx/qapi-domain.py @@ -289,6 +289,22 @@ class QAPICommand(QAPIObject): ) +class QAPIEnum(QAPIObject): + """Description of a QAPI Enum.""" + + doc_field_types = QAPIObject.doc_field_types.copy() + doc_field_types.extend( + [ + GroupedField( + "value", + label=_("Values"), + names=("value",), + can_collapse=True, + ) + ] + ) + + class QAPIModule(SphinxDirective): """ Directive to mark description of a new module. @@ -434,9 +450,14 @@ class QAPIDomain(Domain): # This table associates cross-reference object types (key) with an # ObjType instance, which defines the valid cross-reference roles # for each object type. + # + # e.g., the :qapi:type: cross-reference role can refer to enum, + # struct, union, or alternate objects; but :qapi:obj: can refer to + # anything. Each object also gets its own targeted cross-reference role. object_types: Dict[str, ObjType] = { "module": ObjType(_("module"), "mod", "obj"), "command": ObjType(_("command"), "cmd", "obj"), + "enum": ObjType(_("enum"), "enum", "obj", "type"), } # Each of these provides a ReST directive, @@ -444,6 +465,7 @@ class QAPIDomain(Domain): directives = { "module": QAPIModule, "command": QAPICommand, + "enum": QAPIEnum, } # These are all cross-reference roles; e.g. @@ -452,6 +474,8 @@ class QAPIDomain(Domain): roles = { "mod": QAPIXRefRole(), "cmd": QAPIXRefRole(), + "enum": QAPIXRefRole(), + "type": QAPIXRefRole(), # reference any data type (excludes modules, commands, events) "obj": QAPIXRefRole(), # reference *any* type of QAPI object. } From patchwork Fri Apr 19 04:38:02 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 13635671 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 4E13DC4345F for ; Fri, 19 Apr 2024 04:40:54 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rxg1Q-0007W7-2S; Fri, 19 Apr 2024 00:38:48 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1G-0007TO-MZ for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:38 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1E-0004DM-V7 for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:38 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713501516; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=aT7Zt+MnqDBeB3Aa1m9yjVj+44B/I2Lh5VoQCq7rSj8=; b=gmnTtJkNLUCOUBl5JdFTECCgtxW2hes5fceUHYbcIx20Et3P+1Qf/FcAcCuwxAYKIsfeQ2 jnpZhbrR2Q0NS9/ysRtfVjdMaFBqzMjLxXTm43TESwpobLJxvJ+g5dfUfj/fARR+shM1kW LNjQkQyj4b//snts9DjOTJMB+Ozxjos= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-260-mNEPjwTxN4-f2B3iwoVt8g-1; Fri, 19 Apr 2024 00:38:32 -0400 X-MC-Unique: mNEPjwTxN4-f2B3iwoVt8g-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id EF6A8810602; Fri, 19 Apr 2024 04:38:31 +0000 (UTC) Received: from scv.redhat.com (unknown [10.22.8.7]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4AC424011FF7; Fri, 19 Apr 2024 04:38:31 +0000 (UTC) From: John Snow To: qemu-devel@nongnu.org Cc: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , Markus Armbruster , Victor Toso de Carvalho , Peter Maydell , Paolo Bonzini , John Snow Subject: [PATCH 14/27] docs/qapi-domain: add qapi:alternate directive Date: Fri, 19 Apr 2024 00:38:02 -0400 Message-ID: <20240419043820.178731-15-jsnow@redhat.com> In-Reply-To: <20240419043820.178731-1-jsnow@redhat.com> References: <20240419043820.178731-1-jsnow@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 Received-SPF: pass client-ip=170.10.133.124; envelope-from=jsnow@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.067, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Add the .. qapi:alternate:: directive, object, and qapi:alt:`name` cross-reference role. Add the "Choices:" field list for describing alternate choices. Like other field lists that reference QAPI types, a forthcoming commit will add cross-referencing support to this field. RFC: In the future, it would be nice to directly inline Alternates as part of the type information in the containing object (i.e. directly in arguments/members) - but that's a task for another series. For now, the branch "names" are documented just like qapidoc.py does, even though this information is superfluous for user documentation. Room for future improvement, but not now. Signed-off-by: John Snow --- docs/qapi/index.rst | 7 +++++++ docs/sphinx/qapi-domain.py | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/docs/qapi/index.rst b/docs/qapi/index.rst index cf794e6e739..9bfe4d9f454 100644 --- a/docs/qapi/index.rst +++ b/docs/qapi/index.rst @@ -127,3 +127,10 @@ Explicit cross-referencing syntax for QAPI modules is available with is treated solely as a read-only manifest of blocks to copy. :value always: The bitmap is always synchronized with the operation, regardless of whether or not the operation was successful. + +.. qapi:alternate:: BlockDirtyBitmapOrStr + :since: 4.1 + + :choice str local: name of the bitmap, attached to the same node as + target bitmap. + :choice BlockDirtyBitmap external: bitmap with specified node diff --git a/docs/sphinx/qapi-domain.py b/docs/sphinx/qapi-domain.py index 6759c39290d..c6eb6324594 100644 --- a/docs/sphinx/qapi-domain.py +++ b/docs/sphinx/qapi-domain.py @@ -305,6 +305,22 @@ class QAPIEnum(QAPIObject): ) +class QAPIAlternate(QAPIObject): + """Description of a QAPI Alternate.""" + + doc_field_types = QAPIObject.doc_field_types.copy() + doc_field_types.extend( + [ + TypedField( + "choice", + label=_("Choices"), + names=("choice",), + can_collapse=True, + ), + ] + ) + + class QAPIModule(SphinxDirective): """ Directive to mark description of a new module. @@ -458,6 +474,7 @@ class QAPIDomain(Domain): "module": ObjType(_("module"), "mod", "obj"), "command": ObjType(_("command"), "cmd", "obj"), "enum": ObjType(_("enum"), "enum", "obj", "type"), + "alternate": ObjType(_("alternate"), "alt", "obj", "type"), } # Each of these provides a ReST directive, @@ -466,6 +483,7 @@ class QAPIDomain(Domain): "module": QAPIModule, "command": QAPICommand, "enum": QAPIEnum, + "alternate": QAPIAlternate, } # These are all cross-reference roles; e.g. @@ -475,6 +493,7 @@ class QAPIDomain(Domain): "mod": QAPIXRefRole(), "cmd": QAPIXRefRole(), "enum": QAPIXRefRole(), + "alt": QAPIXRefRole(), "type": QAPIXRefRole(), # reference any data type (excludes modules, commands, events) "obj": QAPIXRefRole(), # reference *any* type of QAPI object. } From patchwork Fri Apr 19 04:38:03 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 13635676 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id B56A4C4345F for ; Fri, 19 Apr 2024 04:41:17 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rxg1T-0007Xt-Sx; Fri, 19 Apr 2024 00:38:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1G-0007TM-At for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:38 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1E-0004DF-AF for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:38 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713501515; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=v8sVACIrRr62XXP78wsALvQJ+r6VO2WQThyIRVJL9Fw=; b=YIiqmS1g/xHOv3qNR0wy4TPWHt2RnPGMkPS9Ik9TYPxsjsBT8IUPLrJY3fdDnvvX44KbkY cMN9Ojm+6twhVWdMSk3ZkDF8zVGZjZoRkzUyfjoaPtTcy/L3Bsxv4XQl4eNRLkjm6epG9q gnihoXye9Jv49UF0X9vwYNSLhqoA2Q0= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-626-7G7w6msjNDCoqcoaiODsEQ-1; Fri, 19 Apr 2024 00:38:33 -0400 X-MC-Unique: 7G7w6msjNDCoqcoaiODsEQ-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id AD12280021A; Fri, 19 Apr 2024 04:38:32 +0000 (UTC) Received: from scv.redhat.com (unknown [10.22.8.7]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0729040357A7; Fri, 19 Apr 2024 04:38:32 +0000 (UTC) From: John Snow To: qemu-devel@nongnu.org Cc: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , Markus Armbruster , Victor Toso de Carvalho , Peter Maydell , Paolo Bonzini , John Snow Subject: [PATCH 15/27] docs/qapi-domain: add qapi:event directive Date: Fri, 19 Apr 2024 00:38:03 -0400 Message-ID: <20240419043820.178731-16-jsnow@redhat.com> In-Reply-To: <20240419043820.178731-1-jsnow@redhat.com> References: <20240419043820.178731-1-jsnow@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 Received-SPF: pass client-ip=170.10.133.124; envelope-from=jsnow@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.067, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Adds the .. qapi:event:: directive, object, and :qapi:event:`name` cross-referencing role. Adds the :memb type name: field list syntax for documenting event data members. As this syntax and phrasing will be shared with Structs and Unions as well, add the field list definition to a shared abstract class. As per usual, QAPI cross-referencing for types in the member field list will be added in a forthcoming commit. NOTE 1: The "str?" type annotation syntax sneaks into this commit in the demonstration doc. It isn't processed yet, so just ignore it for now. The non-RFC version of this series won't include the sandbox doc, so that inconsistency will sort itself out later. (Skip ahead to the commit that adds XRef support for TypedField and GroupedField lists to learn what the deal is there and leave feedback on that syntax.) NOTE 2: We already have a QMP lexer, turn it on for example blocks in this sample demo. Signed-off-by: John Snow --- docs/qapi/index.rst | 40 ++++++++++++++++++++++++++++++++++++++ docs/sphinx/qapi-domain.py | 25 ++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/docs/qapi/index.rst b/docs/qapi/index.rst index 9bfe4d9f454..d81bccfb06a 100644 --- a/docs/qapi/index.rst +++ b/docs/qapi/index.rst @@ -2,6 +2,12 @@ QAPI Domain Test ---------------- +.. this sets the code-highlighting language to QMP for this *document*. + I wonder if I can set a domain default...? + +.. highlight:: QMP + + .. qapi:module:: foo-module :no-index: @@ -134,3 +140,37 @@ Explicit cross-referencing syntax for QAPI modules is available with :choice str local: name of the bitmap, attached to the same node as target bitmap. :choice BlockDirtyBitmap external: bitmap with specified node + +.. qapi:event:: BLOCK_JOB_COMPLETED + :since: 1.1 + + Emitted when a block job has completed. + + :memb JobType type: job type + :memb str device: The job identifier. Originally the device name but + other values are allowed since QEMU 2.7 + :memb int len: maximum progress value + :memb int offset: current progress value. On success this is equal to + len. On failure this is less than len + :memb int speed: rate limit, bytes per second + :memb str? error: error message. Only present on failure. This field + contains a human-readable error message. There are no semantics + other than that streaming has failed and clients should not try to + interpret the error string + + Example:: + + <- { + "event": "BLOCK_JOB_COMPLETED", + "data": { + "type": "stream", + "device": "virtio-disk0", + "len": 10737418240, + "offset": 10737418240, + "speed": 0 + }, + "timestamp": { + "seconds": 1267061043, + "microseconds": 959568 + } + } diff --git a/docs/sphinx/qapi-domain.py b/docs/sphinx/qapi-domain.py index c6eb6324594..74dc578b3c7 100644 --- a/docs/sphinx/qapi-domain.py +++ b/docs/sphinx/qapi-domain.py @@ -321,6 +321,28 @@ class QAPIAlternate(QAPIObject): ) +class QAPIObjectWithMembers(QAPIObject): + """Base class for Events/Structs/Unions""" + + doc_field_types = QAPIObject.doc_field_types.copy() + doc_field_types.extend( + [ + TypedField( + "member", + label=_("Members"), + names=("memb",), + can_collapse=True, + ), + ] + ) + + +class QAPIEvent(QAPIObjectWithMembers): + """Description of a QAPI Event.""" + + pass + + class QAPIModule(SphinxDirective): """ Directive to mark description of a new module. @@ -473,6 +495,7 @@ class QAPIDomain(Domain): object_types: Dict[str, ObjType] = { "module": ObjType(_("module"), "mod", "obj"), "command": ObjType(_("command"), "cmd", "obj"), + "event": ObjType(_("event"), "event", "obj"), "enum": ObjType(_("enum"), "enum", "obj", "type"), "alternate": ObjType(_("alternate"), "alt", "obj", "type"), } @@ -482,6 +505,7 @@ class QAPIDomain(Domain): directives = { "module": QAPIModule, "command": QAPICommand, + "event": QAPIEvent, "enum": QAPIEnum, "alternate": QAPIAlternate, } @@ -492,6 +516,7 @@ class QAPIDomain(Domain): roles = { "mod": QAPIXRefRole(), "cmd": QAPIXRefRole(), + "event": QAPIXRefRole(), "enum": QAPIXRefRole(), "alt": QAPIXRefRole(), "type": QAPIXRefRole(), # reference any data type (excludes modules, commands, events) From patchwork Fri Apr 19 04:38:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 13635660 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C41EDC4345F for ; Fri, 19 Apr 2024 04:39:48 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rxg1R-0007Wg-8i; Fri, 19 Apr 2024 00:38:49 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1G-0007TL-7q for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:38 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1E-0004DD-5Q for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:37 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713501515; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=MF2waKTg6GHDYisWOktBmLflMpQrWVB3DdDEnaS+uUA=; b=YvOBUZ7N2u7UK22fqzM9UVoLdIpEFc5KBuTNuhjsVv2V+BWhJGF9hD4cV4u6Lz+R08YMWL 5VD8XfBuFMFkVJyLDuOeiUp+yX1hsbBo63RdG93uUcyZ3QpJ7iqGr7huKmzh9klJkTuLZk oBJqjg6xElKn7OkzbBSzC3AiqQgYPEs= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-437-Dz6E4P27OmOn9qr2uhvaRg-1; Fri, 19 Apr 2024 00:38:33 -0400 X-MC-Unique: Dz6E4P27OmOn9qr2uhvaRg-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 6E3981C0C651; Fri, 19 Apr 2024 04:38:33 +0000 (UTC) Received: from scv.redhat.com (unknown [10.22.8.7]) by smtp.corp.redhat.com (Postfix) with ESMTP id BB90C40829C3; Fri, 19 Apr 2024 04:38:32 +0000 (UTC) From: John Snow To: qemu-devel@nongnu.org Cc: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , Markus Armbruster , Victor Toso de Carvalho , Peter Maydell , Paolo Bonzini , John Snow Subject: [PATCH 16/27] docs/qapi-domain: add qapi:struct directive Date: Fri, 19 Apr 2024 00:38:04 -0400 Message-ID: <20240419043820.178731-17-jsnow@redhat.com> In-Reply-To: <20240419043820.178731-1-jsnow@redhat.com> References: <20240419043820.178731-1-jsnow@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 Received-SPF: pass client-ip=170.10.129.124; envelope-from=jsnow@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.067, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Adds the .. qapi:struct:: directive, object, and :qapi:struct:`name` cross-referencing role. As per usual, QAPI cross-referencing for types in the member field list will be added in a forthcoming commit. RFC Note: The "?" syntax sneaks into the example document again. Please ignore that for now. Signed-off-by: John Snow --- docs/qapi/index.rst | 16 ++++++++++++++++ docs/sphinx/qapi-domain.py | 9 +++++++++ 2 files changed, 25 insertions(+) diff --git a/docs/qapi/index.rst b/docs/qapi/index.rst index d81bccfb06a..b07e6e9e2e3 100644 --- a/docs/qapi/index.rst +++ b/docs/qapi/index.rst @@ -174,3 +174,19 @@ Explicit cross-referencing syntax for QAPI modules is available with "microseconds": 959568 } } + +.. qapi:struct:: BackupPerf + :since: 6.0 + + Optional parameters for backup. These parameters don't affect + functionality, but may significantly affect performance. + + :memb bool? use-copy-range: Use copy offloading. Default false. + :memb int? max-workers: Maximum number of parallel requests for the + sustained background copying process. Doesn't influence + copy-before-write operations. Default 64. + :memb int64? max-chunk: Maximum request length for the sustained + background copying process. Doesn't influence copy-before-write + operations. 0 means unlimited. If max-chunk is non-zero then it + should not be less than job cluster size which is calculated as + maximum of target image cluster size and 64k. Default 0. diff --git a/docs/sphinx/qapi-domain.py b/docs/sphinx/qapi-domain.py index 74dc578b3c7..b46faeaceef 100644 --- a/docs/sphinx/qapi-domain.py +++ b/docs/sphinx/qapi-domain.py @@ -343,6 +343,12 @@ class QAPIEvent(QAPIObjectWithMembers): pass +class QAPIStruct(QAPIObjectWithMembers): + """Description of a QAPI Struct.""" + + pass + + class QAPIModule(SphinxDirective): """ Directive to mark description of a new module. @@ -497,6 +503,7 @@ class QAPIDomain(Domain): "command": ObjType(_("command"), "cmd", "obj"), "event": ObjType(_("event"), "event", "obj"), "enum": ObjType(_("enum"), "enum", "obj", "type"), + "struct": ObjType(_("struct"), "struct", "obj", "type"), "alternate": ObjType(_("alternate"), "alt", "obj", "type"), } @@ -507,6 +514,7 @@ class QAPIDomain(Domain): "command": QAPICommand, "event": QAPIEvent, "enum": QAPIEnum, + "struct": QAPIStruct, "alternate": QAPIAlternate, } @@ -518,6 +526,7 @@ class QAPIDomain(Domain): "cmd": QAPIXRefRole(), "event": QAPIXRefRole(), "enum": QAPIXRefRole(), + "struct": QAPIXRefRole(), "alt": QAPIXRefRole(), "type": QAPIXRefRole(), # reference any data type (excludes modules, commands, events) "obj": QAPIXRefRole(), # reference *any* type of QAPI object. From patchwork Fri Apr 19 04:38:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 13635682 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A181BC4345F for ; Fri, 19 Apr 2024 04:42:30 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rxg1T-0007Xq-QS; Fri, 19 Apr 2024 00:38:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1I-0007UF-M0 for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:44 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1G-0004De-JM for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:40 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713501518; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=CoSqUgSzEsMb4xXZdgb8ytZiYXh2CE2Rj6nvlRqURIo=; b=IIs/4bkCql31VMRimLC2HW9XPsiFgpjQm90LF6+3odLf2gn264zr28bCjfONaURR2HWzaX cMMfNatjO3+b0T94YFzjm/6m19HIbQDZHVYBCGPEU7ojjU6HKZAKfECZV41n0jjVXJP9m+ qwPvV295QrXTk6WxbfMxFMpO6PQJwdc= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-584-Ycmgmc0nOHGfdZP06g2IUQ-1; Fri, 19 Apr 2024 00:38:34 -0400 X-MC-Unique: Ycmgmc0nOHGfdZP06g2IUQ-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 2C415286A9C8; Fri, 19 Apr 2024 04:38:34 +0000 (UTC) Received: from scv.redhat.com (unknown [10.22.8.7]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7BF0F40829C5; Fri, 19 Apr 2024 04:38:33 +0000 (UTC) From: John Snow To: qemu-devel@nongnu.org Cc: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , Markus Armbruster , Victor Toso de Carvalho , Peter Maydell , Paolo Bonzini , John Snow Subject: [PATCH 17/27] docs/qapi-domain: add qapi:union and qapi:branch directives Date: Fri, 19 Apr 2024 00:38:05 -0400 Message-ID: <20240419043820.178731-18-jsnow@redhat.com> In-Reply-To: <20240419043820.178731-1-jsnow@redhat.com> References: <20240419043820.178731-1-jsnow@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 Received-SPF: pass client-ip=170.10.133.124; envelope-from=jsnow@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.067, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Adds the .. qapi:union:: directive, object, and :qapi:union:`name` cross-referencing role. In order to support discriminated branches of unions, a new qapi:branch directive is created whose only purpose is to create a dynamically named field list section based on the name of the branch key and value. Because the label for these branch sections is dynamically generated, this patch allows the use of either :memb: or :arg: in branches; they are simply aliases and do not do anything different. (This is to allow the directive to be used for either Commands or Unions as needed; i.e. for commands whose argument type is a discriminated union.) For example: .. qapi:union:: foo-union :memb foo-enum key: Discriminator field :memb foo-type fieldname: Some base type field that is always present .. qapi:branch:: key value1 :memb type name: lorem ipsum ... .. qapi:branch:: key value2 :memb type2 name2: dolor sit amet ... In order to support this syntax, the root QAPIObject class needs to perform some post-processing on field lists to merge adjecent field lists. because each branch directive will return a separate field list, and we want to combine them into one unified list for proper rendering. NOTE: Technically, the branch directive will allow you to put arbitrary ReST besides field lists inside of it, but it almost certainly won't do anything you'd consider useful. I don't recommend it, but programmatically forbidding it is expensive. Recommendation: "Don't!" ... and now ... RFC: The branches abuse the field list system to create new categories of field list entries that are dynamically generated. At the moment, I do not have code to apply appropriate formatting to these headings, but would like to apply ``literal`` syntax at a minimum to the enum values. The other idea I have is to create a "blank" members value that doesn't add a "title" (field label) on the left column and instead adds a horizontal info bar into the arguments list in the right, but the problem with this approach is that I won't be able to get rid of the "* ..." list bullet syntax, so it may look odd. Otherwise, a benefit to this syntax is that it would allow us to write a longer explanation, e.g. "When ``{key}`` is ``{value}``". It's possible I could split the argument list into several nested lists, but I haven't experimented in that direction yet - it's also likely that Sphinx will want to append a ":" even to blank section titles, so this may prove tricky to do within the constraints of Sphinx's existing Field list system. (I believe the HTML formatter is responsible for appending the colons.) I'm open to suggestions, but wrestling with Sphinx, html and css is time consuming (for me, at least), so ultimately, I'm afraid I must say: ***PATCHES WELCOME***. Signed-off-by: John Snow --- docs/qapi/index.rst | 37 ++++++++++++++ docs/sphinx/qapi-domain.py | 98 +++++++++++++++++++++++++++++++++++++- 2 files changed, 134 insertions(+), 1 deletion(-) diff --git a/docs/qapi/index.rst b/docs/qapi/index.rst index b07e6e9e2e3..d37ceac497f 100644 --- a/docs/qapi/index.rst +++ b/docs/qapi/index.rst @@ -103,6 +103,18 @@ Explicit cross-referencing syntax for QAPI modules is available with :arg baz: Missing a type. :feat unstable: More than unstable, this command doesn't even exist! :arg no-descr: + :arg BitmapSyncMode discrim: How about branches in commands? + + .. qapi:branch:: discrim on-success + + :arg str foobar: This is an argument that belongs to a tagged union branch. + :arg int? foobaz: This is another argument belonging to the same branch. + + .. qapi:branch:: discrim never + + :arg str barfoo: This is an argument that belongs to a *different* tagged union branch. + :arg int64 zzxyz: And this is another argument belonging to that same branch. + :feat hallucination: This command is a figment of your imagination. :error CommandNotFound: When you try to use this command, because it isn't real. @@ -190,3 +202,28 @@ Explicit cross-referencing syntax for QAPI modules is available with operations. 0 means unlimited. If max-chunk is non-zero then it should not be less than job cluster size which is calculated as maximum of target image cluster size and 64k. Default 0. + +.. qapi:union:: RbdEncryptionOptions + :since: 6.1 + + :memb RbdImageEncryptionFormat format: Encryption format. + :memb RbdEncryptionOptions? parent: Parent image encryption options + (for cloned images). Can be left unspecified if this cloned image + is encrypted using the same format and secret as its parent image + (i.e. not explicitly formatted) or if its parent image is not + encrypted. (Since 8.0) + + .. qapi:branch:: format luks + + :memb str key-secret: ID of a QCryptoSecret object providing a + passphrase for unlocking the encryption + + .. qapi:branch:: format luks2 + + :memb str key-secret: ID of a QCryptoSecret object providing a + passphrase for unlocking the encryption + + .. qapi:branch:: format luks-any + + :memb str key-secret: ID of a QCryptoSecret object providing a + passphrase for unlocking the encryption diff --git a/docs/sphinx/qapi-domain.py b/docs/sphinx/qapi-domain.py index b46faeaceef..f0094300c03 100644 --- a/docs/sphinx/qapi-domain.py +++ b/docs/sphinx/qapi-domain.py @@ -33,7 +33,12 @@ from sphinx.locale import _, __ from sphinx.roles import XRefRole from sphinx.util import logging -from sphinx.util.docfields import GroupedField, TypedField +from sphinx.util.docfields import ( + DocFieldTransformer, + Field, + GroupedField, + TypedField, +) from sphinx.util.docutils import SphinxDirective, switch_source_input from sphinx.util.nodes import ( make_id, @@ -52,6 +57,8 @@ logger = logging.getLogger(__name__) +quack = cast # O:-) + class ObjectEntry(NamedTuple): docname: str @@ -242,6 +249,30 @@ def add_target_and_index( ("single", indextext, node_id, "", None) ) + def _merge_adjoining_field_lists(self, contentnode: addnodes.desc_content) -> None: + # Take any adjacent field lists and glue them together into + # one list for further processing by Sphinx. This is done so + # that field lists declared in nested directives can be + # flattened into non-nested field lists. + + first_list = None + delete_queue: List[nodes.field_list] = [] + for child in contentnode: + if isinstance(child, nodes.field_list): + if not first_list: + first_list = child + else: + first_list += child.children + delete_queue.append(child) + else: + first_list = None + + for child in delete_queue: + contentnode.remove(child) + + def transform_content(self, contentnode: addnodes.desc_content) -> None: + self._merge_adjoining_field_lists(contentnode) + def _toc_entry_name(self, sig_node: desc_signature) -> str: # This controls the name in the TOC and on the sidebar. @@ -349,6 +380,12 @@ class QAPIStruct(QAPIObjectWithMembers): pass +class QAPIUnion(QAPIObjectWithMembers): + """Description of a QAPI Union.""" + + pass + + class QAPIModule(SphinxDirective): """ Directive to mark description of a new module. @@ -439,6 +476,59 @@ def run(self) -> List[Node]: return ret +class Branch(SphinxDirective): + """ + Nested directive which only serves to introduce temporary + metadata but return its parsed content nodes unaltered otherwise. + + Technically, you can put whatever you want in here, but doing so may + prevent proper merging of adjacent field lists. + """ + + doc_field_types: List[Field] = [] + has_content = True + required_arguments = 2 + optional_arguments = 0 + domain = "qapi" + + def get_field_type_map(self) -> Dict[str, Tuple[Field, bool]]: + ret = {} + for field in self.doc_field_types: + for name in field.names: + ret[name] = (field, False) + + if field.is_typed: + typed_field = cast(TypedField, field) + for name in typed_field.typenames: + ret[name] = (field, True) + return ret + + def run(self) -> list[Node]: + discrim = self.arguments[0].strip() + value = self.arguments[1].strip() + + # The label name is dynamically generated per-instance instead + # of per-class to incorporate the branch conditions as a label + # name. + self.doc_field_types = [ + TypedField( + "branch-arg-or-memb", + label=f"[{discrim} = {value}]", + # In a branch, we don't actually use the name of the + # field name to generate the label; so allow either-or. + names=("arg", "memb"), + ), + ] + + content_node: addnodes.desc_content = addnodes.desc_content() + _nested_parse(self, content_node) + # DocFieldTransformer usually expects ObjectDescription, but... quack! + transformer = DocFieldTransformer(quack(ObjectDescription, self)) + transformer.transform_all(content_node) + + return content_node.children + + class QAPIIndex(Index): """ Index subclass to provide the QAPI definition index. @@ -505,6 +595,7 @@ class QAPIDomain(Domain): "enum": ObjType(_("enum"), "enum", "obj", "type"), "struct": ObjType(_("struct"), "struct", "obj", "type"), "alternate": ObjType(_("alternate"), "alt", "obj", "type"), + "union": ObjType(_("union"), "union", "obj", "type"), } # Each of these provides a ReST directive, @@ -516,6 +607,10 @@ class QAPIDomain(Domain): "enum": QAPIEnum, "struct": QAPIStruct, "alternate": QAPIAlternate, + "union": QAPIUnion, + # This is not an object in its own right; + # It's a directive for documenting branch members of Union types. + "branch": Branch, } # These are all cross-reference roles; e.g. @@ -528,6 +623,7 @@ class QAPIDomain(Domain): "enum": QAPIXRefRole(), "struct": QAPIXRefRole(), "alt": QAPIXRefRole(), + "union": QAPIXRefRole(), "type": QAPIXRefRole(), # reference any data type (excludes modules, commands, events) "obj": QAPIXRefRole(), # reference *any* type of QAPI object. } From patchwork Fri Apr 19 04:38:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 13635683 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 3FE8FC05023 for ; Fri, 19 Apr 2024 04:42:31 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rxg1V-0007ZX-Rq; Fri, 19 Apr 2024 00:38:53 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1H-0007TY-RN for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:40 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1G-0004DW-0u for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:39 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713501517; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=5IjAMj3TcxONzH6juApwTygBs9hbOUIr24XnNgh7nRc=; b=eM1Zq5v09q8OvCN6ulC/aKe2hvAXy/TIsXuOx6ExvNVA6mPltJvpNRvtN4tFFGTuKd5XaZ RJQnzJkRHiaFLAxGnNZPaTHcHV9+7lI9SToH+rQQ7uxVooKf4ju47YXSR+J3mHEGDeHjRE x8aQtjRn5hfzJSjTOnIzZb5apt07TBI= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-199-pDANlRLQNfuFMp5rcCVxRg-1; Fri, 19 Apr 2024 00:38:35 -0400 X-MC-Unique: pDANlRLQNfuFMp5rcCVxRg-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id E6E261C0C644; Fri, 19 Apr 2024 04:38:34 +0000 (UTC) Received: from scv.redhat.com (unknown [10.22.8.7]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3A1D84011FF7; Fri, 19 Apr 2024 04:38:34 +0000 (UTC) From: John Snow To: qemu-devel@nongnu.org Cc: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , Markus Armbruster , Victor Toso de Carvalho , Peter Maydell , Paolo Bonzini , John Snow , Harmonie Snow Subject: [PATCH 18/27] docs/qapi-domain: add :deprecated: directive option Date: Fri, 19 Apr 2024 00:38:06 -0400 Message-ID: <20240419043820.178731-19-jsnow@redhat.com> In-Reply-To: <20240419043820.178731-1-jsnow@redhat.com> References: <20240419043820.178731-1-jsnow@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 Received-SPF: pass client-ip=170.10.129.124; envelope-from=jsnow@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.067, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Although "deprecated" is a feature (and *will* appear in the features list), add a special :deprecated: option to generate an eye-catch that makes this information very hard to miss. (The intent is to modify qapidoc.py to add this option whenever it detects that the features list attached to a definition contains the "deprecated" entry.) - RFC: Technically, this object-level option is un-needed and could be replaced with a standard content-level directive that e.g. qapidoc.py could insert at the beginning of the content block. I've done it here as an option to demonstrate how it would be possible to do. It's a matter of taste for "where" we feel like implementing it. One benefit of doing it this way is that we can create a single containing box to set CSS style options controlling the flow of multiple infoboxes. The other way to achieve that would be to create a directive that allows us to set multiple options instead, e.g.: .. qapi:infoboxes:: deprecated unstable or possibly: .. qapi:infoboxes:: :deprecated: :unstable: For now, I've left these as top-level QAPI object options. "Hey, it works." P.S., I outsourced the CSS ;) Signed-off-by: Harmonie Snow Signed-off-by: John Snow --- docs/qapi/index.rst | 4 ++++ docs/sphinx-static/theme_overrides.css | 25 +++++++++++++++++++++++++ docs/sphinx/qapi-domain.py | 24 ++++++++++++++++++++++++ 3 files changed, 53 insertions(+) diff --git a/docs/qapi/index.rst b/docs/qapi/index.rst index d37ceac497f..b9a69f6bd17 100644 --- a/docs/qapi/index.rst +++ b/docs/qapi/index.rst @@ -95,6 +95,7 @@ Explicit cross-referencing syntax for QAPI modules is available with .. qapi:command:: fake-command :since: 13.37 + :deprecated: This is a fake command, it's not real. It can't hurt you. @@ -116,6 +117,9 @@ Explicit cross-referencing syntax for QAPI modules is available with :arg int64 zzxyz: And this is another argument belonging to that same branch. :feat hallucination: This command is a figment of your imagination. + :feat deprecated: Although this command is fake, you should know that + it's also deprecated. That's great news! Maybe it will go away and + stop haunting you someday. :error CommandNotFound: When you try to use this command, because it isn't real. :error GenericError: If the system decides it doesn't like the diff --git a/docs/sphinx-static/theme_overrides.css b/docs/sphinx-static/theme_overrides.css index c70ef951286..97b8c1c60e6 100644 --- a/docs/sphinx-static/theme_overrides.css +++ b/docs/sphinx-static/theme_overrides.css @@ -159,3 +159,28 @@ div[class^="highlight"] pre { color: inherit; } } + +/* QAPI domain theming */ + +.qapi-infopips { + margin-bottom: 1em; +} + +.qapi-infopip { + display: inline-block; + padding: 0em 0.5em 0em 0.5em; + margin: 0.25em; +} + +.qapi-deprecated { + background-color: #fffef5; + border: solid #fff176 6px; + font-weight: bold; + padding: 8px; + border-radius: 15px; + margin: 5px; +} + +.qapi-deprecated::before { + content: '⚠️ '; +} diff --git a/docs/sphinx/qapi-domain.py b/docs/sphinx/qapi-domain.py index f0094300c03..065ad501960 100644 --- a/docs/sphinx/qapi-domain.py +++ b/docs/sphinx/qapi-domain.py @@ -150,6 +150,7 @@ class QAPIObject(ObjectDescription[Signature]): "module": directives.unchanged, # Override contextual module name # These are QAPI originals: "since": since_validator, + "deprecated": directives.flag, } ) @@ -249,6 +250,28 @@ def add_target_and_index( ("single", indextext, node_id, "", None) ) + def _add_infopips(self, contentnode: addnodes.desc_content) -> None: + # Add various eye-catches and things that go below the signature + # bar, but precede the user-defined content. + infopips = nodes.container() + infopips.attributes["classes"].append("qapi-infopips") + + def _add_pip(source: str, content: str, classname: str) -> None: + node = nodes.container(source) + node.append(nodes.Text(content)) + node.attributes["classes"].extend(["qapi-infopip", classname]) + infopips.append(node) + + if "deprecated" in self.options: + _add_pip( + ":deprecated:", + f"This {self.objtype} is deprecated.", + "qapi-deprecated", + ) + + if infopips.children: + contentnode.insert(0, infopips) + def _merge_adjoining_field_lists(self, contentnode: addnodes.desc_content) -> None: # Take any adjacent field lists and glue them together into # one list for further processing by Sphinx. This is done so @@ -271,6 +294,7 @@ def _merge_adjoining_field_lists(self, contentnode: addnodes.desc_content) -> No contentnode.remove(child) def transform_content(self, contentnode: addnodes.desc_content) -> None: + self._add_infopips(contentnode) self._merge_adjoining_field_lists(contentnode) def _toc_entry_name(self, sig_node: desc_signature) -> str: From patchwork Fri Apr 19 04:38:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 13635666 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 26CFCC05023 for ; Fri, 19 Apr 2024 04:40:35 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rxg1V-0007ZU-L7; Fri, 19 Apr 2024 00:38:53 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1K-0007UJ-3M for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:44 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1I-0004E5-El for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:41 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713501519; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=fYQSZakUdyxax3fEvSg4ELSQbAzBJgzgMMYPGKLJpy4=; b=T1m/3L/tVpPx13TZpqCD0z2ADtlFPYCM01Dbx3CKfQgatzTkLE2lwXxThDRks0r4mqk8eR Pv6SXGJqyB2p3ROu4vcmXr8JqssaWyLnV9wVTUmWs3zNVhX6dk4AwPL/vhZ97BU3zP+OWq oMASlOHe5GlmkPjXe7NLeABM3k0xdEI= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-7-cai7qDqoMhuJfyVEgPBCjQ-1; Fri, 19 Apr 2024 00:38:36 -0400 X-MC-Unique: cai7qDqoMhuJfyVEgPBCjQ-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 0F4B21C0C652; Fri, 19 Apr 2024 04:38:36 +0000 (UTC) Received: from scv.redhat.com (unknown [10.22.8.7]) by smtp.corp.redhat.com (Postfix) with ESMTP id 01F8C40829C3; Fri, 19 Apr 2024 04:38:34 +0000 (UTC) From: John Snow To: qemu-devel@nongnu.org Cc: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , Markus Armbruster , Victor Toso de Carvalho , Peter Maydell , Paolo Bonzini , John Snow , Harmonie Snow Subject: [PATCH 19/27] docs/qapi-domain: add :unstable: directive option Date: Fri, 19 Apr 2024 00:38:07 -0400 Message-ID: <20240419043820.178731-20-jsnow@redhat.com> In-Reply-To: <20240419043820.178731-1-jsnow@redhat.com> References: <20240419043820.178731-1-jsnow@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 Received-SPF: pass client-ip=170.10.129.124; envelope-from=jsnow@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.067, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Although "unstable" is a feature (and *will* appear in the features list), add a special :unstable: option to generate an eye-catch that makes this information very hard to miss. (The intent is to modify qapidoc.py to add this option whenever it detects that the features list attached to a definition contains the "unstable" entry.) RFC: Same comments as last patch. Signed-off-by: Harmonie Snow Signed-off-by: John Snow --- docs/qapi/index.rst | 4 +++- docs/sphinx-static/theme_overrides.css | 6 +++++- docs/sphinx/qapi-domain.py | 8 ++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/docs/qapi/index.rst b/docs/qapi/index.rst index b9a69f6bd17..6350791a3ed 100644 --- a/docs/qapi/index.rst +++ b/docs/qapi/index.rst @@ -96,13 +96,13 @@ Explicit cross-referencing syntax for QAPI modules is available with .. qapi:command:: fake-command :since: 13.37 :deprecated: + :unstable: This is a fake command, it's not real. It can't hurt you. :arg int foo: normal parameter documentation. :arg str bar: Another normal parameter description. :arg baz: Missing a type. - :feat unstable: More than unstable, this command doesn't even exist! :arg no-descr: :arg BitmapSyncMode discrim: How about branches in commands? @@ -120,6 +120,8 @@ Explicit cross-referencing syntax for QAPI modules is available with :feat deprecated: Although this command is fake, you should know that it's also deprecated. That's great news! Maybe it will go away and stop haunting you someday. + :feat unstable: This command, as a figment of your imagination, is + highly unstable and should not be relied upon. :error CommandNotFound: When you try to use this command, because it isn't real. :error GenericError: If the system decides it doesn't like the diff --git a/docs/sphinx-static/theme_overrides.css b/docs/sphinx-static/theme_overrides.css index 97b8c1c60e6..acdf11675db 100644 --- a/docs/sphinx-static/theme_overrides.css +++ b/docs/sphinx-static/theme_overrides.css @@ -172,7 +172,7 @@ div[class^="highlight"] pre { margin: 0.25em; } -.qapi-deprecated { +.qapi-deprecated,.qapi-unstable { background-color: #fffef5; border: solid #fff176 6px; font-weight: bold; @@ -181,6 +181,10 @@ div[class^="highlight"] pre { margin: 5px; } +.qapi-unstable::before { + content: ' From patchwork Fri Apr 19 04:38:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 13635684 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 059A1C4345F for ; Fri, 19 Apr 2024 04:42:39 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rxg1V-0007Yv-1I; Fri, 19 Apr 2024 00:38:53 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1L-0007UQ-GO for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:44 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1J-0004EK-HT for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:43 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713501520; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=AF5xLvH/7kUiAUGkLwfvULf0scJbtE7oAdCJfc0wnYA=; b=b3qnFF05XfKh8cuvOc52Hi50D1knh/1BEl4WiIOZTYOPcdmEtIXxI54gQmt2KVEb2wtTc7 AZ1siT4uSHUxcQ6QdCTvrry7Tp4vNm953+2kwj4vHLEstLI2ViFMxNxQmNXgoZmASLNVcq mGy9D23NqiBuGl4a/6xPBSHUyfXiZqA= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-53-t2rsuqBpMReC0fC-FFKYmg-1; Fri, 19 Apr 2024 00:38:37 -0400 X-MC-Unique: t2rsuqBpMReC0fC-FFKYmg-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id CD240830E76; Fri, 19 Apr 2024 04:38:36 +0000 (UTC) Received: from scv.redhat.com (unknown [10.22.8.7]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1D2C14011FF7; Fri, 19 Apr 2024 04:38:36 +0000 (UTC) From: John Snow To: qemu-devel@nongnu.org Cc: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , Markus Armbruster , Victor Toso de Carvalho , Peter Maydell , Paolo Bonzini , John Snow , Harmonie Snow Subject: [PATCH 20/27] docs/qapi-domain: add :ifcond: directive option Date: Fri, 19 Apr 2024 00:38:08 -0400 Message-ID: <20240419043820.178731-21-jsnow@redhat.com> In-Reply-To: <20240419043820.178731-1-jsnow@redhat.com> References: <20240419043820.178731-1-jsnow@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 Received-SPF: pass client-ip=170.10.129.124; envelope-from=jsnow@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.067, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Add a special :ifcond: option that allows us to annotate the definition-level conditionals. RFC: This patch renders IFCOND information in two places, because I'm undecided about how to style this information. One option is in the signature bar, and another option is in an eye-catch, like :deprecated: or :unstable:. A benefit to having this be a directive option is that we can put it in the signature bar, the QAPI index, etc. However, if we merely want it in the content section, a directive would work just as well, e.g. ".. qapi:ifcond:: CONFIG_LINUX". (Though, having it be in the same containing box as the unstable/ifcond boxes might require some extra fiddling/post-processing to achieve. Generally, the less docutils tree muddling I have to do, the happier I am.) The syntax of the argument is currently undefined, but it is possible to parse it back down into constituent parts to avoid applying literal formatting to "AND" or "&&" or whichever syntax we formalize. (Or, in the future, applying cross-reference links to the config values for additional reading on some of those build options. Not for this series.) "Vote now on your phones!" Signed-off-by: Harmonie Snow Signed-off-by: John Snow --- docs/qapi/index.rst | 1 + docs/sphinx-static/theme_overrides.css | 13 +++++++++ docs/sphinx/qapi-domain.py | 37 ++++++++++++++++++++++++-- 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/docs/qapi/index.rst b/docs/qapi/index.rst index 6350791a3ed..c68e2044890 100644 --- a/docs/qapi/index.rst +++ b/docs/qapi/index.rst @@ -97,6 +97,7 @@ Explicit cross-referencing syntax for QAPI modules is available with :since: 13.37 :deprecated: :unstable: + :ifcond: CONFIG_LINUX This is a fake command, it's not real. It can't hurt you. diff --git a/docs/sphinx-static/theme_overrides.css b/docs/sphinx-static/theme_overrides.css index acdf11675db..b239a762a9e 100644 --- a/docs/sphinx-static/theme_overrides.css +++ b/docs/sphinx-static/theme_overrides.css @@ -188,3 +188,16 @@ div[class^="highlight"] pre { .qapi-deprecated::before { content: '⚠️ '; } + +.qapi-ifcond::before { + /* gaze ye into the crystal ball to determine feature availability */ + content: ' From patchwork Fri Apr 19 04:38:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 13635679 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id AAA96C4345F for ; Fri, 19 Apr 2024 04:41:44 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rxg1T-0007XM-Cg; Fri, 19 Apr 2024 00:38:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1L-0007UR-S5 for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:44 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1K-0004EU-BQ for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:43 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713501521; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=lgmQqAuYgu1dPNNMrsu0N1EFVraXVo1CGsaUaNPJUFU=; b=QceiGIaFfbm4bJ9/bEZWoMURW+2UtG8dgqKHDpwxyVkq/FSO403nXSn/gIQ5GYZ72f5q8/ t6jkzTBBAxoCAW8rprYggREaBUeEQECOfkBjqv8PM7Lqkk8QnMydgULvZ3+9eml+G3Cqpq vhWla73AxNYYBXOLBNtsZptqaT0/Uec= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-97-t_M2gGGUNQufvoPpb69O2g-1; Fri, 19 Apr 2024 00:38:37 -0400 X-MC-Unique: t_M2gGGUNQufvoPpb69O2g-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 95FBD80021A; Fri, 19 Apr 2024 04:38:37 +0000 (UTC) Received: from scv.redhat.com (unknown [10.22.8.7]) by smtp.corp.redhat.com (Postfix) with ESMTP id DC79A40357A7; Fri, 19 Apr 2024 04:38:36 +0000 (UTC) From: John Snow To: qemu-devel@nongnu.org Cc: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , Markus Armbruster , Victor Toso de Carvalho , Peter Maydell , Paolo Bonzini , John Snow Subject: [PATCH 21/27] docs/qapi-domain: RFC patch - add malformed field list entries Date: Fri, 19 Apr 2024 00:38:09 -0400 Message-ID: <20240419043820.178731-22-jsnow@redhat.com> In-Reply-To: <20240419043820.178731-1-jsnow@redhat.com> References: <20240419043820.178731-1-jsnow@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 Received-SPF: pass client-ip=170.10.129.124; envelope-from=jsnow@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.067, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org This patch demonstrates what happens when you mess up a field list entry. The next patch adds a safeguard against this. Signed-off-by: John Snow --- docs/qapi/index.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/qapi/index.rst b/docs/qapi/index.rst index c68e2044890..5bb1c37a5ed 100644 --- a/docs/qapi/index.rst +++ b/docs/qapi/index.rst @@ -129,6 +129,10 @@ Explicit cross-referencing syntax for QAPI modules is available with argument values. It's very temperamental. :return SomeTypeName: An esoteric collection of mystical nonsense to both confound and delight. + :arg: this is malformed. + :memb: this is malformed and unrecognized. + :choice type name: This is unrecognized. + :errors FooError: Also malformed. Field lists can appear anywhere in the directive block, but any field list entries in the same list block that are recognized as special From patchwork Fri Apr 19 04:38:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 13635673 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 86E9EC04FF6 for ; Fri, 19 Apr 2024 04:41:05 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rxg1U-0007Yu-W4; Fri, 19 Apr 2024 00:38:53 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1K-0007UL-W5 for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:44 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1J-0004EH-5z for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:42 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713501520; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=7jjLauuGCciQkrLfyUwiXsCrDWKAvSteSgJzJEAZUE8=; b=JYw/KNo4uWj9ZCw5Djqe7k6NyVXMFtSNa9OwWfU3ABZ0ZWl5+xTAkgDURhOWZfLaJfuVTK fjuzL42GYOVHaGmcRc0s7sRytNRnXGiG85Rx3JdyL0Q4kKzCqAGI+W/dF8Mh2LXu9drIck nnmDXA+siKV8CLPQJsh1Szn2vv5vVsc= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-259-3ztlf7YMP8C0syRqoqQUPw-1; Fri, 19 Apr 2024 00:38:38 -0400 X-MC-Unique: 3ztlf7YMP8C0syRqoqQUPw-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 5473D29AA38E; Fri, 19 Apr 2024 04:38:38 +0000 (UTC) Received: from scv.redhat.com (unknown [10.22.8.7]) by smtp.corp.redhat.com (Postfix) with ESMTP id A331C40C1233; Fri, 19 Apr 2024 04:38:37 +0000 (UTC) From: John Snow To: qemu-devel@nongnu.org Cc: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , Markus Armbruster , Victor Toso de Carvalho , Peter Maydell , Paolo Bonzini , John Snow Subject: [PATCH 22/27] docs/qapi-domain: add warnings for malformed field lists Date: Fri, 19 Apr 2024 00:38:10 -0400 Message-ID: <20240419043820.178731-23-jsnow@redhat.com> In-Reply-To: <20240419043820.178731-1-jsnow@redhat.com> References: <20240419043820.178731-1-jsnow@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 Received-SPF: pass client-ip=170.10.129.124; envelope-from=jsnow@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.067, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Normally, Sphinx will silently fall back to its standard field list processing if it doesn't match one of your defined fields. A lot of the time, that's not what we want - we want to be warned if we goof something up. For instance, the canonical argument field list form is: :arg type name: descr This form is captured by Sphinx and transformed so that the field label will become "Arguments:". It's possible to omit the type name and descr and still have it be processed correctly. However, if you omit the type name, Sphinx no longer recognizes it: :arg: this is not recognized. This will turn into an arbitrary field list entry whose label is "Arg:", and it otherwise silently fails. You may also see failures for doing things like using :values: instead of :value:, or :errors: instead of :error:, and so on. It's also case sensitive, and easy to trip up. Add a validator that guarantees all field list entries that are the direct child of an ObjectDescription use only recognized forms of field lists, and emit a warning (treated as error by default in most build configurations) whenever we detect one that is goofed up. However, there's still benefit to allowing arbitrary fields -- they are after all not a Sphinx invention, but perfectly normal docutils syntax. Create an allow list for known spellings we don't mind letting through, but warn against anything else. - RFC: Yes, this patch breaks the build! I thought it'd be helpful for you to see the error checking in action. The next commit drops the erroneous fields. Signed-off-by: John Snow --- docs/conf.py | 12 ++++++++ docs/qapi/index.rst | 27 +++++++++++++++++ docs/sphinx/qapi-domain.py | 59 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+) diff --git a/docs/conf.py b/docs/conf.py index b15665d956d..7a7d7005780 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -148,6 +148,18 @@ with open(os.path.join(qemu_docdir, 'defs.rst.inc')) as f: rst_epilog += f.read() + +# Normally, the QAPI domain is picky about what field lists you use to +# describe a QAPI entity. If you'd like to use arbitrary additional +# fields in source documentation, add them here. +qapi_allowed_fields = { + "example", + "note", + "see also", + "TODO", +} + + # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for diff --git a/docs/qapi/index.rst b/docs/qapi/index.rst index 5bb1c37a5ed..ef58dfc4bcd 100644 --- a/docs/qapi/index.rst +++ b/docs/qapi/index.rst @@ -133,6 +133,33 @@ Explicit cross-referencing syntax for QAPI modules is available with :memb: this is malformed and unrecognized. :choice type name: This is unrecognized. :errors FooError: Also malformed. + :example: This isn't a "semantic" field, but it's been added to the + allowed field names list. you can use whatever field names you'd + like; but to prevent accidental typos, there is an allow list of + "arbitrary" section names. + + You can nestle code-blocks in here, too, by using the ``::`` + syntax:: + + -> { [ "bidirectional QMP example" ] } + <- { [ "hello world!"] } + + Or use explicit ``.. code-block:: QMP`` syntax, but it must start + on its own line with a blank line both before and after the + directive to render correctly: + + .. code-block:: QMP + + -> "Hello friend!" + + Note that the QMP highlighter is merely garden-variety JSON, but + with the addition of ``->``, ``<-`` and ``...`` symbols to help + denote bidirectionality and elided segments. Eduardo Habkost and I + wrote this lexer many moons ago to support the + :doc:`/interop/bitmaps` documentation. + :see also: This is also not a "semantic" field. The only limit is + your imagination and what you can convince others to let you check + into conf.py. Field lists can appear anywhere in the directive block, but any field list entries in the same list block that are recognized as special diff --git a/docs/sphinx/qapi-domain.py b/docs/sphinx/qapi-domain.py index e44db10488f..bf8bb933345 100644 --- a/docs/sphinx/qapi-domain.py +++ b/docs/sphinx/qapi-domain.py @@ -334,10 +334,63 @@ def _merge_adjoining_field_lists(self, contentnode: addnodes.desc_content) -> No for child in delete_queue: contentnode.remove(child) + def _validate_field(self, field: nodes.field) -> None: + field_name = field.children[0] + assert isinstance(field_name, nodes.field_name) + allowed_fields = set(self.env.app.config.qapi_allowed_fields) + + field_label = field_name.astext() + if re.match(r"\[\S+ = \S+\]", field_label) or field_label in allowed_fields: + # okie-dokey. branch entry or known good allowed name. + return + + try: + # split into field type and argument + field_type, fieldarg = field_label.split(None, 1) + except ValueError: + # No arguments provided + field_type = field_label + fieldarg = "" + + typemap = self.get_field_type_map() + if field_type in typemap: + # This is a semantic field, yet-to-be-processed. Catch + # correct names, but incorrect arguments (which WILL fail to + # process correctly). + typedesc = typemap[field_type][0] + if typedesc.has_arg != bool(fieldarg): + msg = f"semantic field list type {field_type!r} " + if typedesc.has_arg: + msg += "requires an argument." + else: + msg += "takes no arguments." + logger.warning(msg, location=field) + else: + # This is unrecognized entirely. + valid = ", ".join(sorted(set(typemap) | allowed_fields)) + msg = ( + f"Unrecognized field list name {field_label!r}.\n" + f"Valid fields for qapi:{self.objtype} are: {valid}\n" + "\n" + "If this usage is intentional, please add it to " + "'qapi_allowed_fields' in docs/conf.py." + ) + logger.warning(msg, location=field) + def transform_content(self, contentnode: addnodes.desc_content) -> None: self._add_infopips(contentnode) self._merge_adjoining_field_lists(contentnode) + # Validate field lists. Note that this hook runs after any + # branch directives have processed and transformed their field + # lists, but before the main object directive has had a chance + # to do so. + for child in contentnode: + if isinstance(child, nodes.field_list): + for field in child.children: + assert isinstance(field, nodes.field) + self._validate_field(field) + def _toc_entry_name(self, sig_node: desc_signature) -> str: # This controls the name in the TOC and on the sidebar. @@ -872,6 +925,12 @@ def resolve_any_xref( def setup(app: Sphinx) -> Dict[str, Any]: app.setup_extension("sphinx.directives") + app.add_config_value( + "qapi_allowed_fields", + set(), + "env", # Setting impacts parsing phase + types=set, + ) app.add_domain(QAPIDomain) return { From patchwork Fri Apr 19 04:38:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 13635668 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 78A72C4345F for ; Fri, 19 Apr 2024 04:40:46 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rxg1W-0007aH-Il; Fri, 19 Apr 2024 00:38:54 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1L-0007UO-CO for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:44 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1J-0004EN-LH for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:43 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713501521; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=VGse/02Q0gYpHJXH+gJ0nNA2UseR1liYR+1bHBVp6ag=; b=JxSQUJJaZC8JxkXDDoX4rf3wcPdIczC5koFJpKgfhJ1I01nNHJLOhfqvlADewUnekN2BwN EAl6XX30ILOSQRHYeg5rFOj/+XyXHtWjyO49BYrhbX5lvNSpydhRCbVDEh0cv5hkWUC0pU NSc/8z1CuZB2nO/2NTE+XDKh6+9z0iM= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-295-ghUg9HZkPbySjCO8vzBQuw-1; Fri, 19 Apr 2024 00:38:39 -0400 X-MC-Unique: ghUg9HZkPbySjCO8vzBQuw-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 13B22811002; Fri, 19 Apr 2024 04:38:39 +0000 (UTC) Received: from scv.redhat.com (unknown [10.22.8.7]) by smtp.corp.redhat.com (Postfix) with ESMTP id 62E3740829C3; Fri, 19 Apr 2024 04:38:38 +0000 (UTC) From: John Snow To: qemu-devel@nongnu.org Cc: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , Markus Armbruster , Victor Toso de Carvalho , Peter Maydell , Paolo Bonzini , John Snow Subject: [PATCH 23/27] docs/qapi-domain: RFC patch - delete malformed field lists Date: Fri, 19 Apr 2024 00:38:11 -0400 Message-ID: <20240419043820.178731-24-jsnow@redhat.com> In-Reply-To: <20240419043820.178731-1-jsnow@redhat.com> References: <20240419043820.178731-1-jsnow@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 Received-SPF: pass client-ip=170.10.129.124; envelope-from=jsnow@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.067, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Cleanup of the last patch to fix the build before closing out this RFC series. Signed-off-by: John Snow --- docs/qapi/index.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/qapi/index.rst b/docs/qapi/index.rst index ef58dfc4bcd..8352a27d4a5 100644 --- a/docs/qapi/index.rst +++ b/docs/qapi/index.rst @@ -129,10 +129,6 @@ Explicit cross-referencing syntax for QAPI modules is available with argument values. It's very temperamental. :return SomeTypeName: An esoteric collection of mystical nonsense to both confound and delight. - :arg: this is malformed. - :memb: this is malformed and unrecognized. - :choice type name: This is unrecognized. - :errors FooError: Also malformed. :example: This isn't a "semantic" field, but it's been added to the allowed field names list. you can use whatever field names you'd like; but to prevent accidental typos, there is an allow list of From patchwork Fri Apr 19 04:38:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 13635678 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C362BC05023 for ; Fri, 19 Apr 2024 04:41:18 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rxg1c-0007fV-Fb; Fri, 19 Apr 2024 00:39:00 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1P-0007Vg-2t for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:47 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1N-0004F2-2a for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:46 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713501524; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=PULeYLsuR2VLx6UCPvozb8ITIbXW39pMMYzXoqDSqzc=; b=jRCzimrSgBd/YqaUjSubU6/5OBVHNj0VMu3SH2UU1oZ60SYBuyfNBjiumyLY/un8WBlF/c vS4dX9QPsgq5yix0Sere94M+8D/iOV/BYW1x8W5PcUf8MlkWQbS1tGJ6n6lCP9ggcS4nw/ zVU3mVGXScob0UFmJ+U976cltQXbPd4= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-231-vS7iFMpKNcu7TA9lo1khqQ-1; Fri, 19 Apr 2024 00:38:40 -0400 X-MC-Unique: vS7iFMpKNcu7TA9lo1khqQ-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id C59EF3CBDF64; Fri, 19 Apr 2024 04:38:39 +0000 (UTC) Received: from scv.redhat.com (unknown [10.22.8.7]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2187440357A7; Fri, 19 Apr 2024 04:38:39 +0000 (UTC) From: John Snow To: qemu-devel@nongnu.org Cc: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , Markus Armbruster , Victor Toso de Carvalho , Peter Maydell , Paolo Bonzini , John Snow Subject: [PATCH 24/27] docs/qapi-domain: add type cross-refs to field lists Date: Fri, 19 Apr 2024 00:38:12 -0400 Message-ID: <20240419043820.178731-25-jsnow@redhat.com> In-Reply-To: <20240419043820.178731-1-jsnow@redhat.com> References: <20240419043820.178731-1-jsnow@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 Received-SPF: pass client-ip=170.10.129.124; envelope-from=jsnow@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.067, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org This commit, finally, adds cross-referencing support to various field lists; modeled tightly after Sphinx's own Python domain code. Cross-referencing support is added to type names provided to :arg:, :memb:, :returns: and :choice:. :feat:, :error: and :value:, which do not take type names, do not support this syntax. The general syntax is simple: :arg TypeName ArgName: Lorem Ipsum ... The domain will transform TypeName into :qapi:type:`TypeName` in this basic case, and also apply the ``literal`` decoration to indicate that this is a type cross-reference. For Optional arguments, the special "?" suffix is used. Because "*" has special meaning in ReST that would cause parsing errors, we elect to use "?" instead. The special syntax processing in QAPIXrefMixin strips this character from the end of any type name argument and will append ", Optional" to the rendered output, applying the cross-reference only to the actual type name. The intent here is that the actual syntax in doc-blocks need not change; but e.g. qapidoc.py will need to process and transform "@arg foo lorem ipsum" into ":arg type? foo: lorem ipsum" based on the schema information. Therefore, nobody should ever actually witness this intermediate syntax unless they are writing manual documentation or the doc transmogrifier breaks. For array arguments, type names can similarly be surrounded by "[]", which are stripped off and then re-appended outside of the cross-reference. Note: The mixin pattern here (borrowed from Sphinx) confuses mypy because it cannot tell that it will be mixed into a descendent of Field. Doing that instead causes more errors, because many versions of Sphinx erroneously did not mark various arguments as Optional, so we're a bit hosed either way. Do the simpler thing. Signed-off-by: John Snow --- docs/qapi/index.rst | 34 ++++++++++++ docs/sphinx/qapi-domain.py | 110 +++++++++++++++++++++++++++++++++++-- 2 files changed, 138 insertions(+), 6 deletions(-) diff --git a/docs/qapi/index.rst b/docs/qapi/index.rst index 8352a27d4a5..6e85ea5280d 100644 --- a/docs/qapi/index.rst +++ b/docs/qapi/index.rst @@ -105,6 +105,11 @@ Explicit cross-referencing syntax for QAPI modules is available with :arg str bar: Another normal parameter description. :arg baz: Missing a type. :arg no-descr: + :arg int? oof: Testing optional argument parsing. + :arg [XDbgBlockGraphNode] rab: Testing array argument parsing. + :arg [BitmapSyncMode]? zab: Testing optional array argument parsing, + even though Markus said this should never happen. I believe him, + but I didn't *forbid* the syntax either. :arg BitmapSyncMode discrim: How about branches in commands? .. qapi:branch:: discrim on-success @@ -261,3 +266,32 @@ Explicit cross-referencing syntax for QAPI modules is available with :memb str key-secret: ID of a QCryptoSecret object providing a passphrase for unlocking the encryption + +.. qapi:command:: x-debug-query-block-graph + :since: 4.0 + :unstable: + + Get the block graph. + + :feat unstable: This command is meant for debugging. + :return XDbgBlockGraph: lorem ipsum ... + +.. qapi:struct:: XDbgBlockGraph + :since: 4.0 + + Block Graph - list of nodes and list of edges. + + :memb [XDbgBlockGraphNode] nodes: + :memb [XDbgBlockGraphEdge] edges: + +.. qapi:struct:: XDbgBlockGraphNode + :since: 4.0 + + :memb uint64 id: Block graph node identifier. This @id is generated only for + x-debug-query-block-graph and does not relate to any other + identifiers in Qemu. + :memb XDbgBlockGraphNodeType type: Type of graph node. Can be one of + block-backend, block-job or block-driver-state. + :memb str name: Human readable name of the node. Corresponds to + node-name for block-driver-state nodes; is not guaranteed to be + unique in the whole graph (with block-jobs and block-backends). diff --git a/docs/sphinx/qapi-domain.py b/docs/sphinx/qapi-domain.py index bf8bb933345..074453193ce 100644 --- a/docs/sphinx/qapi-domain.py +++ b/docs/sphinx/qapi-domain.py @@ -50,11 +50,12 @@ if TYPE_CHECKING: from docutils.nodes import Element, Node + from docutils.parsers.rst.states import Inliner from sphinx.application import Sphinx from sphinx.builders import Builder from sphinx.environment import BuildEnvironment - from sphinx.util.typing import OptionSpec + from sphinx.util.typing import OptionSpec, TextlikeNode logger = logging.getLogger(__name__) @@ -68,6 +69,90 @@ class ObjectEntry(NamedTuple): aliased: bool +class QAPIXrefMixin: + def make_xref( + self, + rolename: str, + domain: str, + target: str, + innernode: type[TextlikeNode] = nodes.literal, + contnode: Optional[Node] = None, + env: Optional[BuildEnvironment] = None, + inliner: Optional[Inliner] = None, + location: Optional[Node] = None, + ) -> Node: + result = super().make_xref( # type: ignore[misc] + rolename, + domain, + target, + innernode=innernode, + contnode=contnode, + env=env, + inliner=None, + location=None, + ) + if isinstance(result, pending_xref): + assert env is not None + result["refspecific"] = True + result["qapi:module"] = env.ref_context.get("qapi:module") + + assert isinstance(result, Node) + return result + + def make_xrefs( + self, + rolename: str, + domain: str, + target: str, + innernode: type[TextlikeNode] = nodes.literal, + contnode: Optional[Node] = None, + env: Optional[BuildEnvironment] = None, + inliner: Optional[Inliner] = None, + location: Optional[Node] = None, + ) -> list[Node]: + # Note: this function is called on up to three fields of text: + # (1) The field name argument (e.g. member/arg name) + # (2) The field name type (e.g. member/arg type) + # (3) The field *body* text, for Fields that do not take arguments. + + list_type = False + optional = False + + # If the rolename is qapi:type, we know we are processing a type + # and not an arg/memb name or field body text. + if rolename == "type": + # force the innernode class to be a literal. + innernode = nodes.literal + + # Type names that end with "?" are considered Optional + # arguments and should be documented as such, but it's not + # part of the xref itself. + if target.endswith("?"): + optional = True + target = target[:-1] + + # Type names wrapped in brackets denote lists. strip the + # brackets and remember to add them back later. + if target.startswith("[") and target.endswith("]"): + list_type = True + target = target[1:-1] + + results = [] + result = self.make_xref( + rolename, domain, target, innernode, contnode, env, inliner, location + ) + results.append(result) + + if list_type: + results.insert(0, nodes.literal("[", "[")) + results.append(nodes.literal("]", "]")) + if optional: + results.append(nodes.Text(", ")) + results.append(nodes.emphasis("?", "Optional")) + + return results + + class QAPIXRefRole(XRefRole): def process_link( self, @@ -96,6 +181,14 @@ def process_link( return title, target +class QAPIGroupedField(QAPIXrefMixin, GroupedField): + pass + + +class QAPITypedField(QAPIXrefMixin, TypedField): + pass + + def since_validator(param: str) -> str: """ Validate the `:since: X.Y` option field. @@ -416,10 +509,11 @@ class QAPICommand(QAPIObject): doc_field_types = QAPIObject.doc_field_types.copy() doc_field_types.extend( [ - TypedField( + QAPITypedField( "argument", label=_("Arguments"), names=("arg",), + typerolename="type", can_collapse=True, ), GroupedField( @@ -428,9 +522,10 @@ class QAPICommand(QAPIObject): names=("error",), can_collapse=True, ), - GroupedField( + QAPIGroupedField( "returnvalue", label=_("Returns"), + rolename="type", names=("return", "returns"), can_collapse=True, ), @@ -460,10 +555,11 @@ class QAPIAlternate(QAPIObject): doc_field_types = QAPIObject.doc_field_types.copy() doc_field_types.extend( [ - TypedField( + QAPITypedField( "choice", label=_("Choices"), names=("choice",), + typerolename="type", can_collapse=True, ), ] @@ -476,10 +572,11 @@ class QAPIObjectWithMembers(QAPIObject): doc_field_types = QAPIObject.doc_field_types.copy() doc_field_types.extend( [ - TypedField( + QAPITypedField( "member", label=_("Members"), names=("memb",), + typerolename="type", can_collapse=True, ), ] @@ -629,12 +726,13 @@ def run(self) -> list[Node]: # of per-class to incorporate the branch conditions as a label # name. self.doc_field_types = [ - TypedField( + QAPITypedField( "branch-arg-or-memb", label=f"[{discrim} = {value}]", # In a branch, we don't actually use the name of the # field name to generate the label; so allow either-or. names=("arg", "memb"), + typerolename="type", ), ] From patchwork Fri Apr 19 04:38:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 13635680 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 7094BC4345F for ; Fri, 19 Apr 2024 04:42:01 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rxg1Q-0007WV-Op; Fri, 19 Apr 2024 00:38:48 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1O-0007VX-Gr for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:46 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1M-0004Et-Jx for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:46 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713501523; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=UKNkbqrEhzyrsBVuLkNEGiD9G/ACMD1JU77CLaAjtAk=; b=YjMkSGrwN1LWF070oNnVL+I820iFzE7IsErj3K6r7BvoWNV6C3MtdhDB70a+M7qQMu9ydJ grsZcPLbuYLI/QM234qaesAxW8qpl5DMUtYzGbqBkPmKVhSKWVK7Jk/JU23lP1vEEwPgKS 51jwr4f9y/S49bxdYJwUCGIvv5QE+B8= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-527-fvgFM1IcMFSyO9LcjMBU8Q-1; Fri, 19 Apr 2024 00:38:40 -0400 X-MC-Unique: fvgFM1IcMFSyO9LcjMBU8Q-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 8316F3CBDF6A; Fri, 19 Apr 2024 04:38:40 +0000 (UTC) Received: from scv.redhat.com (unknown [10.22.8.7]) by smtp.corp.redhat.com (Postfix) with ESMTP id D201640829C3; Fri, 19 Apr 2024 04:38:39 +0000 (UTC) From: John Snow To: qemu-devel@nongnu.org Cc: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , Markus Armbruster , Victor Toso de Carvalho , Peter Maydell , Paolo Bonzini , John Snow Subject: [PATCH 25/27] docs/qapi-domain: implement error context reporting fix Date: Fri, 19 Apr 2024 00:38:13 -0400 Message-ID: <20240419043820.178731-26-jsnow@redhat.com> In-Reply-To: <20240419043820.178731-1-jsnow@redhat.com> References: <20240419043820.178731-1-jsnow@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 Received-SPF: pass client-ip=170.10.129.124; envelope-from=jsnow@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.067, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sphinx 5.3.0 to Sphinx 6.2.0 has a bug where nested content in an ObjectDescription content block has its error position reported incorrectly due to an oversight when they added nested section support to this directive. (This bug is present in Sphinx's own Python and C domains; test it yourself by creating a py:func directive and creating a syntax error in the directive's content block.) To avoid overriding and re-implementing the entirety of the run() method, a workaround is employed where we parse the content block ourselves in before_content(), then null the content block to make Sphinx's own parsing a no-op. Then, in transform_content (which occurs after Sphinx's nested parse), we simply swap our own parsed content tree back in for Sphinx's. It appears a little tricky, but it's the nicest solution I can find. Signed-off-by: John Snow --- docs/sphinx/qapi-domain.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/sphinx/qapi-domain.py b/docs/sphinx/qapi-domain.py index 074453193ce..7d8911c635f 100644 --- a/docs/sphinx/qapi-domain.py +++ b/docs/sphinx/qapi-domain.py @@ -21,7 +21,9 @@ from docutils import nodes from docutils.parsers.rst import directives +from docutils.statemachine import StringList +import sphinx from sphinx import addnodes from sphinx.addnodes import desc_signature, pending_xref from sphinx.directives import ObjectDescription @@ -470,7 +472,27 @@ def _validate_field(self, field: nodes.field) -> None: ) logger.warning(msg, location=field) + def before_content(self) -> None: + # Work around a sphinx bug and parse the content ourselves. + self._temp_content = self.content + self._temp_offset = self.content_offset + self._temp_node = None + + if sphinx.version_info[:3] >= (5, 3, 0) and sphinx.version_info[:3] < (6, 2, 0): + self._temp_node = addnodes.desc_content() + self.state.nested_parse(self.content, self.content_offset, self._temp_node) + # Sphinx will try to parse the content block itself, + # Give it nothingness to parse instead. + self.content = StringList() + self.content_offset = 0 + def transform_content(self, contentnode: addnodes.desc_content) -> None: + # Sphinx workaround: Inject our parsed content and restore state. + if self._temp_node: + contentnode += self._temp_node.children + self.content = self._temp_content + self.content_offset = self._temp_offset + self._add_infopips(contentnode) self._merge_adjoining_field_lists(contentnode) From patchwork Fri Apr 19 04:38:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 13635669 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 345ACC05023 for ; Fri, 19 Apr 2024 04:40:47 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rxg1Z-0007eZ-4c; Fri, 19 Apr 2024 00:38:57 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1P-0007W8-Vo for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:48 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1N-0004FC-C0 for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:47 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713501524; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=h9ivFynH+DrIyxyCrgkjda0tH5zkdVzYPlc+LqwrpBU=; b=YQJhgU9r0EVfzxFvVgDMx25Cb2sboJA/Xo4aElzHw0+2gsreFYWnOcqBB/prtYCHuSN2yO 9hOUx2XlFDW2rAAPKoUXYNN5y9Y5XmJ2UOf8ed63r4OiweOXPVjU0mS1R1QDn9HFViCzfE 1dbgKtF9Y/nDJ69K9JUa6TSXBmaMIpI= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-548-SWjDAIYJOgWopWUA_tmK-g-1; Fri, 19 Apr 2024 00:38:41 -0400 X-MC-Unique: SWjDAIYJOgWopWUA_tmK-g-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 3EBD63CBDF61; Fri, 19 Apr 2024 04:38:41 +0000 (UTC) Received: from scv.redhat.com (unknown [10.22.8.7]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8F8614011FF7; Fri, 19 Apr 2024 04:38:40 +0000 (UTC) From: John Snow To: qemu-devel@nongnu.org Cc: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , Markus Armbruster , Victor Toso de Carvalho , Peter Maydell , Paolo Bonzini , John Snow Subject: [PATCH 26/27] docs/qapi-domain: RFC patch - Add one last sample command Date: Fri, 19 Apr 2024 00:38:14 -0400 Message-ID: <20240419043820.178731-27-jsnow@redhat.com> In-Reply-To: <20240419043820.178731-1-jsnow@redhat.com> References: <20240419043820.178731-1-jsnow@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 Received-SPF: pass client-ip=170.10.133.124; envelope-from=jsnow@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.067, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Just to have a bit more to look at in the generated doc, here's a fairly complex command with a lot of bells and whistles. Signed-off-by: John Snow --- docs/qapi/index.rst | 67 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/docs/qapi/index.rst b/docs/qapi/index.rst index 6e85ea5280d..4562e755d21 100644 --- a/docs/qapi/index.rst +++ b/docs/qapi/index.rst @@ -267,6 +267,73 @@ Explicit cross-referencing syntax for QAPI modules is available with :memb str key-secret: ID of a QCryptoSecret object providing a passphrase for unlocking the encryption +.. qapi:command:: blockdev-backup + :since: 4.2 + + Start a point-in-time copy of a block device to a new + destination. The status of ongoing blockdev-backup operations can be + checked with query-block-jobs where the BlockJobInfo.type field has + the value ‘backup’. The operation can be stopped before it has + completed using the block-job-cancel command. + + :arg str target: + the device name or node-name of the backup target node. + :arg str? job-id: + identifier for the newly-created block job. If omitted, the device + name will be used. (Since 2.7) + :arg str device: + the device name or node-name of a root node which should be copied. + :arg MirrorSyncMode sync: + what parts of the disk image should be copied to the destination + (all the disk, only the sectors allocated in the topmost image, + from a dirty bitmap, or only new I/O). + :arg int? speed: + the maximum speed, in bytes per second. The default is 0, for unlimited. + :arg str? bitmap: + The name of a dirty bitmap to use. Must be present if sync is + ``bitmap`` or ``incremental``. Can be present if sync is ``full`` or + ``top``. Must not be present otherwise. (Since 2.4 (drive-backup), + 3.1 (blockdev-backup)) + :arg BitmapSyncMode? bitmap-mode: + Specifies the type of data the bitmap should contain after the + operation concludes. Must be present if a bitmap was provided, + Must NOT be present otherwise. (Since 4.2) + :arg bool? compress: + true to compress data, if the target format supports it. (default: + false) (since 2.8) + :arg BlockdevOnError? on-source-error: + the action to take on an error on the source, default + ``report``. ``stop`` and ``enospc`` can only be used if the block device + supports io-status (see BlockInfo). + :arg BlockdevOnError? on-target-error: + the action to take on an error on the target, default ``report`` (no + limitations, since this applies to a different block device than + device). + :arg bool? auto-finalize: + When false, this job will wait in a ``PENDING`` state after it has + finished its work, waiting for block-job-finalize before making + any block graph changes. When true, this job will automatically + perform its abort or commit actions. Defaults to true. (Since + 2.12) + :arg bool? auto-dismiss: + When false, this job will wait in a ``CONCLUDED`` state after it has + completely ceased all work, and awaits block-job-dismiss. When + true, this job will automatically disappear from the query list + without user intervention. Defaults to true. (Since 2.12) + :arg str? filter-node-name: + the node name that should be assigned to the filter driver that + the backup job inserts into the graph above node specified by + drive. If this option is not given, a node name is + autogenerated. (Since: 4.2) + :arg BackupPerf? x-perf: + Performance options. (Since 6.0) + :feat unstable: Member ``x-perf`` is experimental. + :error DeviceNotFound: if ``device`` is not a valid block device. + + .. note:: ``on-source-error`` and ``on-target-error only`` affect + background I/O. If an error occurs during a guest write + request, the device's rerror/werror actions will be used. + .. qapi:command:: x-debug-query-block-graph :since: 4.0 :unstable: From patchwork Fri Apr 19 04:38:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 13635667 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id B067CC04FF6 for ; Fri, 19 Apr 2024 04:40:36 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rxg1Z-0007ed-M7; Fri, 19 Apr 2024 00:38:57 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1Q-0007WL-Dg for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:48 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rxg1O-0004FH-NT for qemu-devel@nongnu.org; Fri, 19 Apr 2024 00:38:48 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713501526; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=5abJCU0h5aF3vdT6HE6N8xKGQV3SNeJnkpXl7YahGbw=; b=gd4g84OjNxJFhF15NkycTENp/9EnYtpATFBqnFRv0+FJ9Pib1IiH2M9MYM4UDUq3Y2dHpj Uj4O8MeArnSX37BmPcPfPfTE74jER9xmsnRIoHnHGuk7CJD0tob1/4KQgEjIRxH2wvbLhN Emes/eZjwpcbpjzmj5jpMWbPdZbZtiw= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-169-Qv6s_TVfNCiNXHLVTS8sbQ-1; Fri, 19 Apr 2024 00:38:42 -0400 X-MC-Unique: Qv6s_TVfNCiNXHLVTS8sbQ-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 035B918065AF; Fri, 19 Apr 2024 04:38:42 +0000 (UTC) Received: from scv.redhat.com (unknown [10.22.8.7]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4E8C540829C5; Fri, 19 Apr 2024 04:38:41 +0000 (UTC) From: John Snow To: qemu-devel@nongnu.org Cc: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , Markus Armbruster , Victor Toso de Carvalho , Peter Maydell , Paolo Bonzini , Harmonie Snow , John Snow Subject: [PATCH 27/27] docs/qapi-domain: add CSS styling Date: Fri, 19 Apr 2024 00:38:15 -0400 Message-ID: <20240419043820.178731-28-jsnow@redhat.com> In-Reply-To: <20240419043820.178731-1-jsnow@redhat.com> References: <20240419043820.178731-1-jsnow@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 Received-SPF: pass client-ip=170.10.129.124; envelope-from=jsnow@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.067, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Harmonie Snow Improve the general look and feel of generated QAPI docs. Attempt to limit line lengths to offer a more comfortable measure on maximized windows, and improve some margin and spacing for field lists. Signed-off-by: Harmonie Snow Signed-off-by: John Snow --- docs/sphinx-static/theme_overrides.css | 50 ++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/docs/sphinx-static/theme_overrides.css b/docs/sphinx-static/theme_overrides.css index b239a762a9e..9a58cf86b5c 100644 --- a/docs/sphinx-static/theme_overrides.css +++ b/docs/sphinx-static/theme_overrides.css @@ -18,8 +18,8 @@ h1, h2, .rst-content .toctree-wrapper p.caption, h3, h4, h5, h6, legend { .rst-content dl:not(.docutils) dt { border-top: none; - border-left: solid 3px #ccc; - background-color: #f0f0f0; + border-left: solid 5px #bcc6d2; + background-color: #eaedf1; color: black; } @@ -162,6 +162,18 @@ div[class^="highlight"] pre { /* QAPI domain theming */ +/* most content in a qapi object definition should not eclipse about + 80ch, but nested field lists are explicitly exempt due to their + two-column nature */ +.qapi dd *:not(dl) { + max-width: 80ch; +} + +/* but the content column itself should still be less than ~80ch. */ +.qapi .field-list dd { + max-width: 80ch; +} + .qapi-infopips { margin-bottom: 1em; } @@ -201,3 +213,37 @@ div[class^="highlight"] pre { border-radius: 15px; margin: 5px; } + +/* code blocks */ +.qapi div[class^="highlight"] { + width: fit-content; + background-color: #fffafd; + border: 2px solid #ffe1f3; +} + +/* note, warning, etc. */ +.qapi .admonition { + width: fit-content; +} + +/* pad the top of the field-list so the text doesn't start directly at + the top border; primarily for the field list labels, but adjust the + field bodies as well for parity. */ +dl.field-list > dt:first-of-type, dl.field-list > dd:first-of-type { + padding-top: 0.3em; +} + +dl.field-list > dt:last-of-type, dl.field-list > dd:last-of-type { + padding-bottom: 0.3em; +} + +/* pad the field list labels so they don't crash into the border */ +dl.field-list > dt { + padding-left: 0.5em; + padding-right: 0.5em; +} + +/* Add a little padding between field list sections */ +dl.field-list > dd:not(:last-child) { + padding-bottom: 1em; +}