From patchwork Tue Mar 11 11:30:37 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011615 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 1CF37C282EC for ; Tue, 11 Mar 2025 11:52:23 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxqI-00039P-QK; Tue, 11 Mar 2025 07:32:14 -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 1trxq0-00031F-Bk for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:31:58 -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 1trxpt-0006Pf-8c for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:31:56 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692705; 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=RtvWj4oPK+6yI7FNQpfBxeEqsivHdCTqY6DnAhxRVGE=; b=FV/s3be0IhiVuKg4Y406OFSwzSL7lUm7eAVHIwUC8rq5m2qk11y3gg937z8PU/I2O9Ung4 YiMJ+8BKBcn7s+OMGjT6mPpAz3sR81aTNbYQH4j12F12awQPpBA63fABcPL2dTQZx7Tyt4 8dRCodjf0/HoZcWsQYFKykQtnQdt/Ws= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-141-P4lCJPxAOz-_LUytw31YDw-1; Tue, 11 Mar 2025 07:31:44 -0400 X-MC-Unique: P4lCJPxAOz-_LUytw31YDw-1 X-Mimecast-MFC-AGG-ID: P4lCJPxAOz-_LUytw31YDw_1741692703 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (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 mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 78664180AB1C for ; Tue, 11 Mar 2025 11:31:43 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 1D360195608F for ; Tue, 11 Mar 2025 11:31:42 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id B534721E669B; Tue, 11 Mar 2025 12:31:37 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 01/61] docs/sphinx: create QAPI domain extension stub Date: Tue, 11 Mar 2025 12:30:37 +0100 Message-ID: <20250311113137.1277125-2-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow A Sphinx domain is a collection of directive and role extensions meant to facilitate the documentation of a specific language. For instance, Sphinx ships with "python" and "cpp" domains. This patch introduces a stub for the "qapi" language domain. Please see https://www.sphinx-doc.org/en/master/usage/domains/index.html for more information. This stub 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 Message-ID: <20250311034303.75779-4-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/conf.py | 9 +++++- docs/sphinx/qapi_domain.py | 56 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 docs/sphinx/qapi_domain.py diff --git a/docs/conf.py b/docs/conf.py index 31bb9a3789..49d9de894c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -60,7 +60,14 @@ # 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 = [ + 'depfile', + 'hxtool', + 'kerneldoc', + 'qapi_domain', + 'qapidoc', + '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 0000000000..a1983d9444 --- /dev/null +++ b/docs/sphinx/qapi_domain.py @@ -0,0 +1,56 @@ +""" +QAPI domain extension. +""" + +from __future__ import annotations + +from typing import ( + TYPE_CHECKING, + AbstractSet, + Any, + Dict, + 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: AbstractSet[str], otherdata: Dict[str, Any] + ) -> None: + pass + + def resolve_any_xref(self, *args: Any, **kwargs: Any) -> Any: + # pylint: disable=unused-argument + return [] + + +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 Tue Mar 11 11:30:38 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011535 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 8436EC28B2E for ; Tue, 11 Mar 2025 11:33:33 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxq2-0002zs-Em; Tue, 11 Mar 2025 07:32:02 -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 1trxpu-0002zV-6V for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:31:50 -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 1trxps-0006Pk-8x for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:31:49 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692705; 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=GvRqAYXngKFnsunoBIWJIZ3/px5KzUK18gI3qg38ap4=; b=MaIdAFphmqk9AplskFPG7eR4VYAcN6+14VSaBuFCYah8zWNuy0m85USSlSz83Uc3VFnO6O uIeFbPrYcIsq1fcPK6ygms/UrekRTNzzM2SuFGVNlSrRbWspe5jJejx0tpOEWGO/KohqYJ +HkY3lE7PD/NNHtrFwAKnr4JL1PTdCI= Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-637-m6Y1BEUoPmqJZtEWFUS9Pg-1; Tue, 11 Mar 2025 07:31:44 -0400 X-MC-Unique: m6Y1BEUoPmqJZtEWFUS9Pg-1 X-Mimecast-MFC-AGG-ID: m6Y1BEUoPmqJZtEWFUS9Pg_1741692703 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (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 mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 504671955D50 for ; Tue, 11 Mar 2025 11:31:43 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id BE9FC1955BCB for ; Tue, 11 Mar 2025 11:31:42 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id B926321E669D; Tue, 11 Mar 2025 12:31:37 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 02/61] docs/sphinx: add compat.py module and nested_parse helper Date: Tue, 11 Mar 2025 12:30:38 +0100 Message-ID: <20250311113137.1277125-3-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow Create a compat module that handles sphinx cross-version compatibility issues. For the inaugural function, add a nested_parse_with_titles() helper that handles differences in line number tracking for nested directive body parsing. Spoilers: there are more cross-version hacks to come throughout the series. Signed-off-by: John Snow Message-ID: <20250311034303.75779-5-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/compat.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 docs/sphinx/compat.py diff --git a/docs/sphinx/compat.py b/docs/sphinx/compat.py new file mode 100644 index 0000000000..39b859a25e --- /dev/null +++ b/docs/sphinx/compat.py @@ -0,0 +1,35 @@ +""" +Sphinx cross-version compatibility goop +""" + +from docutils.nodes import Element + +from sphinx.util import nodes +from sphinx.util.docutils import SphinxDirective, switch_source_input + + +def nested_parse_with_titles( + 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 + nodes.nested_parse_with_titles( + directive.state, + directive.content, + content_node, + content_offset=directive.content_offset, + ) + except TypeError: + # No content_offset argument. Fall back to SSI method. + with switch_source_input(directive.state, directive.content): + nodes.nested_parse_with_titles( + directive.state, directive.content, content_node + ) From patchwork Tue Mar 11 11:30:39 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011611 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 895BBC282EC for ; Tue, 11 Mar 2025 11:51:34 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxrs-0004iS-5v; Tue, 11 Mar 2025 07:33:52 -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 1trxpz-00030J-FP for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:31:58 -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 1trxps-0006Po-8g for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:31:54 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692705; 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=d7vRvWf9SmhRJpBK3qNPhaybcHPWaKYGOQw1EhRPmiA=; b=G6s0mvHzOgRNwwbpG/tZiLarl/o2NMg7++u1Bk1aNTfkqH2bU7C4o+7WKJUp3dZpsUPE8v zHEW8WA2E3qUz8/3JAWmEv57XAOXziINR0Qo4PoMPqBZvCmT0WfKzamRmRJtSYtBbY6Fu0 U2SMu5iVgQvkKI6mnfEaapNBqpyGNxo= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-141-Usi3BkozOZ-SU2-v5lc-hQ-1; Tue, 11 Mar 2025 07:31:44 -0400 X-MC-Unique: Usi3BkozOZ-SU2-v5lc-hQ-1 X-Mimecast-MFC-AGG-ID: Usi3BkozOZ-SU2-v5lc-hQ_1741692703 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (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 mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 780C21954B3A for ; Tue, 11 Mar 2025 11:31:43 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id EA6FE19560AB for ; Tue, 11 Mar 2025 11:31:42 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id BD8FA21E66A3; Tue, 11 Mar 2025 12:31:37 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 03/61] docs/qapi-domain: add QAPI domain object registry Date: Tue, 11 Mar 2025 12:30:39 +0100 Message-ID: <20250311113137.1277125-4-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow This is the first step towards QAPI domain cross-references and a QAPI reference index. This patch just creates the object registry, and updates the merge_domaindata stub method now that we have actual data we may need to merge. Note that how to handle merge conflict resolution is unhandled, as the Sphinx python domain itself does not handle it either. I do not know how to intentionally trigger it, so I've left an assertion instead if it should ever come up ... Signed-off-by: John Snow Message-ID: <20250311034303.75779-6-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapi_domain.py | 77 +++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py index a1983d9444..f3ece42bc2 100644 --- a/docs/sphinx/qapi_domain.py +++ b/docs/sphinx/qapi_domain.py @@ -9,10 +9,12 @@ AbstractSet, Any, Dict, + NamedTuple, Tuple, ) from sphinx.domains import Domain, ObjType +from sphinx.locale import __ from sphinx.util import logging @@ -22,22 +24,93 @@ logger = logging.getLogger(__name__) +class ObjectEntry(NamedTuple): + docname: str + node_id: str + objtype: str + aliased: bool + + class QAPIDomain(Domain): """QAPI language domain.""" name = "qapi" label = "QAPI" + # This table associates cross-reference object types (key) with an + # ObjType instance, which defines the valid cross-reference roles + # for each object type. + + # Actual table entries for module, command, event, etc will come in + # forthcoming commits. object_types: Dict[str, ObjType] = {} + directives = {} 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]: + ret = self.data.setdefault("objects", {}) + return ret # 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: AbstractSet[str], otherdata: Dict[str, Any] ) -> None: - pass + for fullname, obj in otherdata["objects"].items(): + if obj.docname in docnames: + # Sphinx's own python domain doesn't appear to bother to + # check for collisions. Assert they don't happen and + # we'll fix it if/when the case arises. + assert fullname not in self.objects, ( + "bug - collision on merge?" + f" {fullname=} {obj=} {self.objects[fullname]=}" + ) + self.objects[fullname] = obj def resolve_any_xref(self, *args: Any, **kwargs: Any) -> Any: # pylint: disable=unused-argument From patchwork Tue Mar 11 11:30:40 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011541 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 2AC98C28B2E for ; Tue, 11 Mar 2025 11:34:36 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxrU-000488-IJ; Tue, 11 Mar 2025 07:33:29 -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 1trxpx-00030D-EW for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:31:58 -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 1trxpt-0006QM-68 for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:31:51 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692706; 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=4fzVBga88f/OqmMbr+swR0bwGim42s2bhCCOndnrpmU=; b=HPOXADD0Db3dxIIXuVhkyDEuB+8myg4DyUZu3YY6KrEQEoJI7VwLHopxmjU77qWItA5suZ yGa1Lu1Tkl7MQEPAzCn3R4OlCYk4rTQkFnfdypXkfpGu2SeePh1QvlPLvdta2dEoTwMP6k Z+/siBISQahwMSpAQgtFLWJpXVtMNbw= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-590-tepSRSfENPSU0Qeosx15QA-1; Tue, 11 Mar 2025 07:31:45 -0400 X-MC-Unique: tepSRSfENPSU0Qeosx15QA-1 X-Mimecast-MFC-AGG-ID: tepSRSfENPSU0Qeosx15QA_1741692704 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (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 mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id F3425180034D for ; Tue, 11 Mar 2025 11:31:43 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 7788F1944F12 for ; Tue, 11 Mar 2025 11:31:42 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id C19A221E66A4; Tue, 11 Mar 2025 12:31:37 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 04/61] docs/qapi-domain: add QAPI index Date: Tue, 11 Mar 2025 12:30:40 +0100 Message-ID: <20250311113137.1277125-5-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Received-SPF: pass client-ip=170.10.133.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H2=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow Use the QAPI object registry to generate a special index just for QAPI definitions. The index can show entries both by definition type and all together, alphabetically. The index can be linked from anywhere in the QEMU manual by using the reference `qapi-index`. Signed-off-by: John Snow Message-ID: <20250311034303.75779-7-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapi_domain.py | 73 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 3 deletions(-) diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py index f3ece42bc2..3e7718d32d 100644 --- a/docs/sphinx/qapi_domain.py +++ b/docs/sphinx/qapi_domain.py @@ -9,12 +9,20 @@ AbstractSet, Any, Dict, + Iterable, + List, NamedTuple, + Optional, Tuple, ) -from sphinx.domains import Domain, ObjType -from sphinx.locale import __ +from sphinx.domains import ( + Domain, + Index, + IndexEntry, + ObjType, +) +from sphinx.locale import _, __ from sphinx.util import logging @@ -31,6 +39,62 @@ class ObjectEntry(NamedTuple): aliased: bool +class QAPIIndex(Index): + """ + Index subclass to provide the QAPI definition index. + """ + + # pylint: disable=too-few-public-methods + + 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 + # (ignoring the module) + objects = sorted( + self.domain.objects.items(), + key=lambda x: x[0].split(".")[-1].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.""" @@ -54,7 +118,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 Tue Mar 11 11:30:41 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011613 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 ABA01C282EC for ; Tue, 11 Mar 2025 11:51:43 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxqX-0003E3-J3; Tue, 11 Mar 2025 07:32:30 -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 1trxq9-00034y-Sj for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:07 -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 1trxpz-0006Sp-6F for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:03 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692711; 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=dqpBYp4PbrmJ7vPfHHWBAjHCBdNfG66HXq5ykYSxADY=; b=ZQS4E5r3tZi4Ew5hRMy/skPhveKPVY2DJ42sHJOFAUT8yC1ODgEo7Ia0fps6/BIYToQAnw 4Tx4rpD/6lVbmq/Ns/l0ucAUdiYmXKW5gt4JlOIT5ttGhqspTa1F4Rvrr+oCbPJxRPkBAQ 98FJX4rD/PpHsjNrf1blbfAqGkTdP4c= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-116-qrZ1C4tSMYSdgYDcaBdRvQ-1; Tue, 11 Mar 2025 07:31:49 -0400 X-MC-Unique: qrZ1C4tSMYSdgYDcaBdRvQ-1 X-Mimecast-MFC-AGG-ID: qrZ1C4tSMYSdgYDcaBdRvQ_1741692708 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C789D1801A12 for ; Tue, 11 Mar 2025 11:31:48 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 0F4231800268 for ; Tue, 11 Mar 2025 11:31:48 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id C579321E66A7; Tue, 11 Mar 2025 12:31:37 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 05/61] docs/qapi-domain: add resolve_any_xref() Date: Tue, 11 Mar 2025 12:30:41 +0100 Message-ID: <20250311113137.1277125-6-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass client-ip=170.10.133.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H2=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow 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 Message-ID: <20250311034303.75779-8-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapi_domain.py | 96 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 93 insertions(+), 3 deletions(-) diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py index 3e7718d32d..f05c2cadf0 100644 --- a/docs/sphinx/qapi_domain.py +++ b/docs/sphinx/qapi_domain.py @@ -16,6 +16,9 @@ Tuple, ) +from docutils import nodes + +from sphinx.addnodes import pending_xref from sphinx.domains import ( Domain, Index, @@ -24,10 +27,15 @@ ) from sphinx.locale import _, __ from sphinx.util import logging +from sphinx.util.nodes import make_refnode if TYPE_CHECKING: + from docutils.nodes import Element + from sphinx.application import Sphinx + from sphinx.builders import Builder + from sphinx.environment import BuildEnvironment logger = logging.getLogger(__name__) @@ -179,9 +187,91 @@ def merge_domaindata( ) self.objects[fullname] = obj - def resolve_any_xref(self, *args: Any, **kwargs: Any) -> Any: - # pylint: disable=unused-argument - return [] + def find_obj( + self, modname: str, name: str, typ: 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 typ is None: + # type isn't specified, this is a generic xref. + # search *all* qapi-specific object types. + objtypes: 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(typ, []) + + 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, nodes.reference]]: + results: List[Tuple[str, nodes.reference]] = [] + matches = self.find_obj(node.get("qapi:module"), target, None) + for name, obj in matches: + rolename = self.role_for_objtype(obj.objtype) + assert rolename is not None + role = f"qapi:{rolename}" + 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]: From patchwork Tue Mar 11 11:30:42 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011617 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 3A708C28B2E for ; Tue, 11 Mar 2025 11:52:48 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxqI-00039d-Sc; Tue, 11 Mar 2025 07:32:14 -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 1trxq6-00033H-R9 for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:07 -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 1trxpx-0006SJ-7R for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:31:59 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692710; 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=Is6a5N00uknZIelzF2+id8m4QFd+3awuhN/SWIJn9Y8=; b=M3crRN6GD+z/j5roukZhxCOIQ6nElePUqkcd0H3b69w5mF4TuorHZomTuMLs3wZKGMVDtk KT2/PfhG87pdPcWE+rv0bprsrnoQQJW2s4uk9+F5ogA0XAmzbzBcffEHmPrXIhzJlgLOzA QHABkUxj11gGSmjFI2FjRwApNeNy5t8= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-21-CdvwFVmGMNKwrOJnS-xWfQ-1; Tue, 11 Mar 2025 07:31:49 -0400 X-MC-Unique: CdvwFVmGMNKwrOJnS-xWfQ-1 X-Mimecast-MFC-AGG-ID: CdvwFVmGMNKwrOJnS-xWfQ_1741692708 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (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 mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C592818007E1 for ; Tue, 11 Mar 2025 11:31:48 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 0FA291828A92 for ; Tue, 11 Mar 2025 11:31:48 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id C953421E65DD; Tue, 11 Mar 2025 12:31:37 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 06/61] docs/qapi-domain: add QAPI xref roles Date: Tue, 11 Mar 2025 12:30:42 +0100 Message-ID: <20250311113137.1277125-7-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow Add domain-specific cross-reference syntax. As of this commit, that means new :qapi:any:`block-core` referencing syntax. The :any: role will find anything registered to the QAPI domain, including modules, commands, events, etc. Creating the cross-references is powered by the QAPIXRefRole class; resolving them is handled by QAPIDomain.resolve_xref(). QAPIXrefRole is based heavily on Sphinx's own PyXrefRole, with modifications necessary for QAPI features. Signed-off-by: John Snow Message-ID: <20250311034303.75779-9-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapi_domain.py | 88 +++++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-) diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py index f05c2cadf0..49d42c0921 100644 --- a/docs/sphinx/qapi_domain.py +++ b/docs/sphinx/qapi_domain.py @@ -26,6 +26,7 @@ ObjType, ) from sphinx.locale import _, __ +from sphinx.roles import XRefRole from sphinx.util import logging from sphinx.util.nodes import make_refnode @@ -47,6 +48,54 @@ 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") + + # Cross-references that begin with a tilde adjust the title to + # only show the reference without a leading module, even if one + # was provided. This is a Sphinx-standard syntax; give it + # priority over QAPI-specific type markup below. + hide_module = False + if target.startswith("~"): + hide_module = True + target = target[1:] + + # 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("?"): + refnode["qapi: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("]"): + refnode["qapi:array"] = True + target = target[1:-1] + + if has_explicit_title: + # Don't mess with the title at all if it was explicitly set. + # Explicit title syntax for references is e.g. + # :qapi:type:`target ` + # and this explicit title overrides everything else here. + return title, target + + title = target + if hide_module: + title = target.split(".")[-1] + + return title, target + + class QAPIIndex(Index): """ Index subclass to provide the QAPI definition index. @@ -118,7 +167,13 @@ class QAPIDomain(Domain): object_types: Dict[str, ObjType] = {} directives = {} - 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 = { + "any": QAPIXRefRole(), # reference *any* type of QAPI object. + } # Moved into the data property at runtime; # this is the internal index of reference-able objects. @@ -252,6 +307,37 @@ 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, + typ: str, + target: str, + node: pending_xref, + contnode: Element, + ) -> nodes.reference | None: + modname = node.get("qapi:module") + matches = self.find_obj(modname, target, typ) + + if not matches: + return None + + if len(matches) > 1: + 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 Tue Mar 11 11:30:43 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011587 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 AA8E7C282EC for ; Tue, 11 Mar 2025 11:44:59 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxqM-0003B2-VT; Tue, 11 Mar 2025 07:32:19 -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 1trxq9-00034t-RJ for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:07 -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 1trxpx-0006T8-92 for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:02 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692712; 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=SRWt7X/Z6Aeo0rDyoVOlOiqyvQY/dWNpmRHRtgGwmjc=; b=Lt8DmdkBYYOlPuSz9k5sXvxuPLQxfnv5HO+nOwr1zWRuOFfixvmfT9ZFJl2GXAxwqAUdZw tTFxYJJDLX8rQRnfSW1T4aQQvmZ8Ijr7bRtXyG1K2SXeyt5dBQ7mLcyGvrHZrqcQ15nr0y TVKP3N53cV8M082wBfuqLghQ6RDY2Pg= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-612-Edq6XNpgPA-VY-JeQHFNjw-1; Tue, 11 Mar 2025 07:31:49 -0400 X-MC-Unique: Edq6XNpgPA-VY-JeQHFNjw-1 X-Mimecast-MFC-AGG-ID: Edq6XNpgPA-VY-JeQHFNjw_1741692708 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (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 mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C89611954B38 for ; Tue, 11 Mar 2025 11:31:48 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 62074195608F for ; Tue, 11 Mar 2025 11:31:48 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id CDA0921E65FF; Tue, 11 Mar 2025 12:31:37 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 07/61] docs/qapi-domain: add compatibility node classes Date: Tue, 11 Mar 2025 12:30:43 +0100 Message-ID: <20250311113137.1277125-8-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Received-SPF: pass client-ip=170.10.133.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H2=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow Sphinx prior to v4.0 uses different classes for rendering elements of documentation objects; add some compatibility classes to use the right node classes conditionally. Signed-off-by: John Snow Message-ID: <20250311034303.75779-10-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/compat.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/docs/sphinx/compat.py b/docs/sphinx/compat.py index 39b859a25e..6bc698c5ad 100644 --- a/docs/sphinx/compat.py +++ b/docs/sphinx/compat.py @@ -2,12 +2,27 @@ Sphinx cross-version compatibility goop """ -from docutils.nodes import Element +from typing import Callable +from docutils.nodes import Element, Node, Text + +import sphinx +from sphinx import addnodes from sphinx.util import nodes from sphinx.util.docutils import SphinxDirective, switch_source_input +SpaceNode: Callable[[str], Node] +KeywordNode: Callable[[str, str], Node] + +if sphinx.version_info[:3] >= (4, 0, 0): + SpaceNode = addnodes.desc_sig_space + KeywordNode = addnodes.desc_sig_keyword +else: + SpaceNode = Text + KeywordNode = addnodes.desc_annotation + + def nested_parse_with_titles( directive: SphinxDirective, content_node: Element ) -> None: From patchwork Tue Mar 11 11:30:44 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011603 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 BDCF3C28B2E for ; Tue, 11 Mar 2025 11:48:57 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxs2-0005M7-TO; Tue, 11 Mar 2025 07:34:03 -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 1trxq9-000355-Uy for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:07 -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 1trxpy-0006TO-U9 for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:03 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692711; 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=w+MPXw/ViYW+BO5JYLzSFNIa+LpybWCpjcuBxciHrxs=; b=YigALLPXM5rT583ISey8uHz9whmpuxXGzv4c4TieiMuRxVB+hAfPh7MiKFuX0zV7kMRg7D XOrcVavMd/l8n+pgO2HO9dnL2qTAiBhjzNYDqmVOyHI3+Y51QjS4zpObooMZsKS6TKVpp5 Frt1zM4asjyKcRpI8FWvv0TmzpZu3Pc= Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-551-rMdTXRXRMhS0NJns1qPf0g-1; Tue, 11 Mar 2025 07:31:50 -0400 X-MC-Unique: rMdTXRXRMhS0NJns1qPf0g-1 X-Mimecast-MFC-AGG-ID: rMdTXRXRMhS0NJns1qPf0g_1741692709 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (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 mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id CAA9D1955DDF for ; Tue, 11 Mar 2025 11:31:49 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id DAD7B19560AB for ; Tue, 11 Mar 2025 11:31:48 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id D159E21E6560; Tue, 11 Mar 2025 12:31:37 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 08/61] docs/qapi-domain: Add QAPIDescription abstract class Date: Tue, 11 Mar 2025 12:30:44 +0100 Message-ID: <20250311113137.1277125-9-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow This class is a generic, top-level directive for documenting some kind of QAPI thingamajig that we expect to go into the Index. This class doesn't do much by itself, and it isn't yet associated with any particular directive. handle_signature(), _object_hierarchy_parts() and _toc_entry_name() are defined in the base class. get_index_text() and add_target_and_index() are new methods defined here; they are based heavily on the layout and format of the Python domain's general object class. Signed-off-by: John Snow Message-ID: <20250311034303.75779-11-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapi_domain.py | 101 ++++++++++++++++++++++++++++++++++++- 1 file changed, 99 insertions(+), 2 deletions(-) diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py index 49d42c0921..0ee36b4644 100644 --- a/docs/sphinx/qapi_domain.py +++ b/docs/sphinx/qapi_domain.py @@ -14,11 +14,13 @@ NamedTuple, Optional, Tuple, + cast, ) from docutils import nodes -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, @@ -28,7 +30,7 @@ from sphinx.locale import _, __ from sphinx.roles import XRefRole from sphinx.util import logging -from sphinx.util.nodes import make_refnode +from sphinx.util.nodes import make_id, make_refnode if TYPE_CHECKING: @@ -96,6 +98,101 @@ def process_link( return title, target +Signature = str + + +class QAPIDescription(ObjectDescription[Signature]): + """ + Generic QAPI description. + + This is meant to be an abstract class, not instantiated + directly. This class handles the abstract details of indexing, the + TOC, and reference targets for QAPI descriptions. + """ + + def handle_signature(self, sig: str, signode: desc_signature) -> Signature: + # Do nothing. The return value here is the "name" of the entity + # being documented; for QAPI, this is the same as the + # "signature", which is just a name. + + # Normally this method must also populate signode with nodes to + # render the signature; here we do nothing instead - the + # subclasses will handle this. + return sig + + def get_index_text(self, name: Signature) -> Tuple[str, str]: + """Return the text for the index entry of the object.""" + + # NB: this is used for the global index, not the QAPI index. + return ("single", f"{name} (QMP {self.objtype})") + + def add_target_and_index( + self, name: Signature, sig: str, signode: desc_signature + ) -> None: + # name is the return value of handle_signature. + # sig is the original, raw text argument to handle_signature. + # For QAPI, these are identical, currently. + + assert self.objtype + + # If we're documenting a module, don't include the module as + # part of the FQN. + modname = "" + if self.objtype != "module": + modname = self.options.get( + "module", self.env.ref_context.get("qapi:module") + ) + fullname = (modname + "." if modname else "") + name + + node_id = make_id( + self.env, self.state.document, self.objtype, 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: + arity, indextext = self.get_index_text(name) + assert self.indexnode is not None + if indextext: + self.indexnode["entries"].append( + (arity, indextext, node_id, "", None) + ) + + 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(".")) + + return tuple(fullname.split(".")) + + 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 QAPIIndex(Index): """ Index subclass to provide the QAPI definition index. From patchwork Tue Mar 11 11:30:45 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011602 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 81630C282EC for ; Tue, 11 Mar 2025 11:48:41 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxsH-0005qb-Ff; Tue, 11 Mar 2025 07:34:17 -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 1trxqn-0003Mh-Lp for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:49 -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 1trxqB-0006Vn-BC for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:44 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692717; 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=oisWfkS61zdF24rZ4fy5fo5E+tP9TzVK64LPlgqAuuE=; b=WNZ6sbfBuX6CpizIwcZCY4OZ2/aRNtQi2FTOAHmLzkLYOki4c5lYmSP+OIW1bLeZg6DpoY T+pGGm21Py34EdRuL9wtKRS0h23300Uh57EJ4demV1LBI5V+CfzvNNt6Bsn3f1H8ZI0OnV RQXPwHb8H32oGmVqt9RQl9n94ISmjKU= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-45-RraL3mpUPra3gES5BZhMGA-1; Tue, 11 Mar 2025 07:31:52 -0400 X-MC-Unique: RraL3mpUPra3gES5BZhMGA-1 X-Mimecast-MFC-AGG-ID: RraL3mpUPra3gES5BZhMGA_1741692709 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 78DCE1954B36 for ; Tue, 11 Mar 2025 11:31:49 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id E1DD51801747 for ; Tue, 11 Mar 2025 11:31:48 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id D545321E6561; Tue, 11 Mar 2025 12:31:37 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 09/61] docs/qapi-domain: add qapi:module directive Date: Tue, 11 Mar 2025 12:30:45 +0100 Message-ID: <20250311113137.1277125-10-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_PASS=-0.001, T_SPF_HELO_TEMPERROR=0.01 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: John Snow This adds the 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 unnecessary features excised. For example: .. qapi:module:: block-core Hello, and welcome to block-core! ================================= lorem ipsum, dolor sit amet ... Signed-off-by: John Snow Message-ID: <20250311034303.75779-12-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapi_domain.py | 71 ++++++++++++++++++++++++++++++++++---- 1 file changed, 65 insertions(+), 6 deletions(-) diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py index 0ee36b4644..e623d1f867 100644 --- a/docs/sphinx/qapi_domain.py +++ b/docs/sphinx/qapi_domain.py @@ -19,6 +19,7 @@ from docutils import nodes +from sphinx import addnodes from sphinx.addnodes import desc_signature, pending_xref from sphinx.directives import ObjectDescription from sphinx.domains import ( @@ -34,7 +35,7 @@ if TYPE_CHECKING: - from docutils.nodes import Element + from docutils.nodes import Element, Node from sphinx.application import Sphinx from sphinx.builders import Builder @@ -193,6 +194,60 @@ def _toc_entry_name(self, sig_node: desc_signature) -> str: return "" +class QAPIModule(QAPIDescription): + """ + 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 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. + :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 ... + """ + + def run(self) -> List[Node]: + modname = self.arguments[0].strip() + self.env.ref_context["qapi:module"] = modname + ret = super().run() + + # ObjectDescription always creates a visible signature bar. We + # want module items to be "invisible", however. + + # Extract the content body of the directive: + assert isinstance(ret[-1], addnodes.desc) + desc_node = ret.pop(-1) + assert isinstance(desc_node.children[1], addnodes.desc_content) + ret.extend(desc_node.children[1].children) + + # Re-home node_ids so anchor refs still work: + node_ids: List[str] + if node_ids := [ + node_id + for el in desc_node.children[0].traverse(nodes.Element) + for node_id in cast(List[str], el.get("ids", ())) + ]: + target_node = nodes.target(ids=node_ids) + ret.insert(1, target_node) + + return ret + + class QAPIIndex(Index): """ Index subclass to provide the QAPI definition index. @@ -258,17 +313,21 @@ 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. + object_types: Dict[str, ObjType] = { + "module": ObjType(_("module"), "mod", "any"), + } - # Actual table entries for module, command, event, etc will come in - # forthcoming commits. - object_types: Dict[str, ObjType] = {} - - directives = {} + # Each of these provides a rST directive, + # e.g. .. qapi:module:: block-core + directives = { + "module": QAPIModule, + } # 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(), "any": QAPIXRefRole(), # reference *any* type of QAPI object. } From patchwork Tue Mar 11 11:30:46 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011573 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 F01EDC28B2E for ; Tue, 11 Mar 2025 11:40:12 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxqX-0003Dz-JU; Tue, 11 Mar 2025 07:32:30 -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 1trxqA-00035K-Fv for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:07 -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 1trxpz-0006Sz-GT for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:05 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692711; 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=tv9oT81kD/IduAh4UJa5O71G9TAdSfSYd+QSG2v3UHI=; b=ZkEaT01WlkjH0QmYaG4PhzgXDEdCnfOycGBldYBhnPM12amZJoJXThvReIrHWCyC7ariam 1oYWptqfRnKrc9DWSAetKiF2htgf3AIRVCJPszUQGFd8RKd984GwqTV8pV5U0SgP9GYh9H ljU79SqwDhphL+0o2xcnSp4lzLHOT58= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-551-R5okrZLZPs-RhCdrpN38YA-1; Tue, 11 Mar 2025 07:31:50 -0400 X-MC-Unique: R5okrZLZPs-RhCdrpN38YA-1 X-Mimecast-MFC-AGG-ID: R5okrZLZPs-RhCdrpN38YA_1741692709 Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (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 mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id CBD621955BC5 for ; Tue, 11 Mar 2025 11:31:49 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 611F21956094 for ; Tue, 11 Mar 2025 11:31:48 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id D914A21E6562; Tue, 11 Mar 2025 12:31:37 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 10/61] docs/qapi-domain: add QAPIObject class Date: Tue, 11 Mar 2025 12:30:46 +0100 Message-ID: <20250311113137.1277125-11-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow This patch adds another abstract class that describes "a QAPI thingie". The main difference here is that this class will be generating visible documentation, unlike the QAPIDescription class. Signed-off-by: John Snow Message-ID: <20250311034303.75779-13-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapi_domain.py | 64 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py index e623d1f867..3109c0cb90 100644 --- a/docs/sphinx/qapi_domain.py +++ b/docs/sphinx/qapi_domain.py @@ -18,7 +18,9 @@ ) from docutils import nodes +from docutils.parsers.rst import directives +from compat import KeywordNode, SpaceNode from sphinx import addnodes from sphinx.addnodes import desc_signature, pending_xref from sphinx.directives import ObjectDescription @@ -40,6 +42,7 @@ 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__) @@ -99,6 +102,8 @@ def process_link( return title, target +# 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 @@ -194,6 +199,65 @@ def _toc_entry_name(self, sig_node: desc_signature) -> str: return "" +class QAPIObject(QAPIDescription): + """ + 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 = ( # type:ignore[misc] + ObjectDescription.option_spec.copy() + ) + option_spec.update( + { + # Borrowed from the Python domain: + "module": directives.unchanged, # Override contextual module name + } + ) + + def get_signature_prefix(self) -> List[nodes.Node]: + """Return a prefix to put before the object name in the signature.""" + assert self.objtype + return [ + KeywordNode("", self.objtype.title()), + SpaceNode(" "), + ] + + def get_signature_suffix(self) -> List[nodes.Node]: + """Return 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 + definition 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() + if sig_prefix: + signode += addnodes.desc_annotation( + str(sig_prefix), "", *sig_prefix + ) + signode += addnodes.desc_name(sig, sig) + signode += self.get_signature_suffix() + + return sig + + class QAPIModule(QAPIDescription): """ Directive to mark description of a new module. From patchwork Tue Mar 11 11:30:47 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011605 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 EEF5FC282EC for ; Tue, 11 Mar 2025 11:50:41 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxry-0004wY-3h; Tue, 11 Mar 2025 07:33:58 -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 1trxqB-00035N-54 for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:07 -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 1trxpy-0006So-JR for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:06 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692711; 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=Ci9++44Vu0AyVzxeH73rqBxxH/kB2g9E3U8CcJkrGx4=; b=Pl1tjy2epqEftidRxbB44gAdotWSoRuYNtO+9JyLr/BykBWZZOAbz6EwTybJBtOiNiRTv3 cR/wSKmK9OGIdtgYZF4PdqCFSMgw6BNCFF6EDgYXnq6UfBU1ExbkVluYVIkcx2+M+LAYm6 sRE3oT6gSxNWoZgr4CVoRNMMD9FcyZ8= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-116-Tf2x5mRnPB6nTPzY3Icd9w-1; Tue, 11 Mar 2025 07:31:49 -0400 X-MC-Unique: Tf2x5mRnPB6nTPzY3Icd9w-1 X-Mimecast-MFC-AGG-ID: Tf2x5mRnPB6nTPzY3Icd9w_1741692708 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C76AB18001E3 for ; Tue, 11 Mar 2025 11:31:48 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 619EE1801752 for ; Tue, 11 Mar 2025 11:31:48 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id DD0E721E64C0; Tue, 11 Mar 2025 12:31:37 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 11/61] docs/qapi-domain: add qapi:command directive Date: Tue, 11 Mar 2025 12:30:47 +0100 Message-ID: <20250311113137.1277125-12-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass client-ip=170.10.133.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H2=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow This commit adds a stubbed version of QAPICommand that utilizes the QAPIObject class, 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. Signed-off-by: John Snow Message-ID: <20250311034303.75779-14-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapi_domain.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py index 3109c0cb90..547040f75a 100644 --- a/docs/sphinx/qapi_domain.py +++ b/docs/sphinx/qapi_domain.py @@ -258,6 +258,12 @@ def handle_signature(self, sig: str, signode: desc_signature) -> Signature: return sig +class QAPICommand(QAPIObject): + """Description of a QAPI Command.""" + + # Nothing unique for now! Changed in later commits O:-) + + class QAPIModule(QAPIDescription): """ Directive to mark description of a new module. @@ -379,12 +385,14 @@ class QAPIDomain(Domain): # for each object type. object_types: Dict[str, ObjType] = { "module": ObjType(_("module"), "mod", "any"), + "command": ObjType(_("command"), "cmd", "any"), } # Each of these provides a rST directive, # e.g. .. qapi:module:: block-core directives = { "module": QAPIModule, + "command": QAPICommand, } # These are all cross-reference roles; e.g. @@ -392,6 +400,7 @@ class QAPIDomain(Domain): # the object_types table values above. roles = { "mod": QAPIXRefRole(), + "cmd": QAPIXRefRole(), "any": QAPIXRefRole(), # reference *any* type of QAPI object. } From patchwork Tue Mar 11 11:30:48 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011539 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 0D6DBC282EC for ; Tue, 11 Mar 2025 11:34:13 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxqJ-00039X-0G; Tue, 11 Mar 2025 07:32:15 -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 1trxq9-00034s-R5 for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:07 -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 1trxpy-0006TM-0M for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:02 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692712; 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=/CI14kO4UJbWg5wTu3gXivAFZrKjIYx/AgYjSxCmf0E=; b=Vvr7AifX7FSExaXCtCewn63AYkRfs/FAMC1J5vbP+Oh+QQbpa5MRDKC16GlkiiHWNAU4ui 6if9G7vtZmd6dgJqHFcand1lGwl4FItWwSvL7pFonx4PL4FvFbOp3H2g0g1h8SYM8vOBAX 8UPFh/jZYH+AE0X3b308kVlO8IajQoQ= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-549-biO4lXj7MVSTqrWZ5r4o-w-1; Tue, 11 Mar 2025 07:31:50 -0400 X-MC-Unique: biO4lXj7MVSTqrWZ5r4o-w-1 X-Mimecast-MFC-AGG-ID: biO4lXj7MVSTqrWZ5r4o-w_1741692709 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (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 mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id A058718009FC for ; Tue, 11 Mar 2025 11:31:49 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 0E05418001F6 for ; Tue, 11 Mar 2025 11:31:48 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id E0E6E21E64F2; Tue, 11 Mar 2025 12:31:37 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 12/61] docs/qapi-domain: add :since: directive option Date: Tue, 11 Mar 2025 12:30:48 +0100 Message-ID: <20250311113137.1277125-13-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow 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 Message-ID: <20250311034303.75779-15-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapi_domain.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py index 547040f75a..222b420d2a 100644 --- a/docs/sphinx/qapi_domain.py +++ b/docs/sphinx/qapi_domain.py @@ -214,6 +214,8 @@ class QAPIObject(QAPIDescription): { # Borrowed from the Python domain: "module": directives.unchanged, # Override contextual module name + # These are QAPI originals: + "since": directives.unchanged, } ) @@ -227,7 +229,17 @@ def get_signature_prefix(self) -> List[nodes.Node]: def get_signature_suffix(self) -> List[nodes.Node]: """Return a suffix to put after the object name in the signature.""" - return [] + ret: List[nodes.Node] = [] + + if "since" in self.options: + ret += [ + SpaceNode(" "), + addnodes.desc_sig_element( + "", f"(Since: {self.options['since']})" + ), + ] + + return ret def handle_signature(self, sig: str, signode: desc_signature) -> Signature: """ From patchwork Tue Mar 11 11:30:49 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011594 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 8BA60C35FF1 for ; Tue, 11 Mar 2025 11:46:10 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxqX-0003D2-5G; Tue, 11 Mar 2025 07:32:29 -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 1trxqC-00036i-AK for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:08 -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 1trxpy-0006SO-Tf for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:07 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692710; 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=G9XDf3T8UJV4h8z0CKZgSg3IL4y3MtZy/bjJYsVHFe4=; b=UBsa08ZHCEUmfEnLZKi+4XlzmHXgplBcUz9FseM6jOhs4j9w8MpYibJZTxNsMPvmP8YtTQ 26GyGEwPiget6M6DGP1e93PjQchV2YzXjrCebgFeFVj0nEI7ZHFTJAxD/0LAR/CPicfTWO V0hxzoVXbwuEQtIaF2klgoE83hgHs1w= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-543-l7xWEL8YMwChDPe3CdQy9w-1; Tue, 11 Mar 2025 07:31:49 -0400 X-MC-Unique: l7xWEL8YMwChDPe3CdQy9w-1 X-Mimecast-MFC-AGG-ID: l7xWEL8YMwChDPe3CdQy9w_1741692709 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (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 mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id F36AF1800875 for ; Tue, 11 Mar 2025 11:31:48 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 758AF3001D13 for ; Tue, 11 Mar 2025 11:31:48 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id E487B21E64F3; Tue, 11 Mar 2025 12:31:37 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 13/61] docs/qapi-domain: add "Arguments:" field lists Date: Tue, 11 Mar 2025 12:30:49 +0100 Message-ID: <20250311113137.1277125-14-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow This adds special rendering for Sphinx's typed info 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. You should not 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 Message-ID: <20250311034303.75779-16-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapi_domain.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py index 222b420d2a..b4289db6d8 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.nodes import make_id, make_refnode @@ -273,7 +274,18 @@ def handle_signature(self, sig: str, signode: desc_signature) -> Signature: class QAPICommand(QAPIObject): """Description of a QAPI Command.""" - # Nothing unique for now! Changed in later commits O:-) + doc_field_types = QAPIObject.doc_field_types.copy() + doc_field_types.extend( + [ + # :arg TypeName ArgName: descr + TypedField( + "argument", + label=_("Arguments"), + names=("arg",), + can_collapse=False, + ), + ] + ) class QAPIModule(QAPIDescription): From patchwork Tue Mar 11 11:30:50 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011538 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 74F50C282EC for ; Tue, 11 Mar 2025 11:34:06 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxqM-0003B0-VM; Tue, 11 Mar 2025 07:32:19 -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 1trxqA-00035M-Sq for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:07 -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 1trxpy-0006SG-LS for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:01 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692710; 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=AYKHergwRLxqUSHDV68n2DzdEXMCgX0/ziC0DrkQABo=; b=HL7Xr/OsPktnvtFuyK5mOB0ggje23m7cRKYbB0i3qRZRiouCA5tymYtJP3QQdk1HOpgxVf 2PC/ZxK5aIj6V70GR8gBiLdt2YknYE+SScifey6CoQE9Au+EKDi0dOjBQ2B9pmmX70rpuB zJBIzp6C4orLM2sKFgYQtCqtGKyND7M= Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-15-U3FUNxZmOb64Y1v-OOOfaQ-1; Tue, 11 Mar 2025 07:31:49 -0400 X-MC-Unique: U3FUNxZmOb64Y1v-OOOfaQ-1 X-Mimecast-MFC-AGG-ID: U3FUNxZmOb64Y1v-OOOfaQ_1741692708 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 9E6A11955DBA for ; Tue, 11 Mar 2025 11:31:48 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 1BB67180094A for ; Tue, 11 Mar 2025 11:31:48 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id E877921E64F4; Tue, 11 Mar 2025 12:31:37 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 14/61] docs/qapi-domain: add "Features:" field lists Date: Tue, 11 Mar 2025 12:30:50 +0100 Message-ID: <20250311113137.1277125-15-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow 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. The syntax for this field is: :feat name: description description cont'd Signed-off-by: John Snow Message-ID: <20250311034303.75779-17-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapi_domain.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py index b4289db6d8..8ec4482b29 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.nodes import make_id, make_refnode @@ -220,6 +220,16 @@ class QAPIObject(QAPIDescription): } ) + doc_field_types = [ + # :feat name: descr + GroupedField( + "feature", + label=_("Features"), + names=("feat",), + can_collapse=False, + ), + ] + def get_signature_prefix(self) -> List[nodes.Node]: """Return a prefix to put before the object name in the signature.""" assert self.objtype From patchwork Tue Mar 11 11:30:51 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011609 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 037E5C282EC for ; Tue, 11 Mar 2025 11:51:28 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxqy-0003LI-Sx; Tue, 11 Mar 2025 07:33:02 -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 1trxqI-000397-Er for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:14 -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 1trxq3-0006Ve-T9 for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:14 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692717; 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=8eheLperLewFGseZ6W5oySPfYG0lOZLsIqm9p3HURpg=; b=SJk6zCpzR9yQK2aGuNgB+nZmEu63s5XhaY6h2XNIQICu+fsYZ7yFmvSz0nrY3amgEZteKX nvv8YsnOaAYi2JcKCqN78rx2SzuYvJ8RewAR9xkzytDiJr8WfLXmCoxqnxMxsMLpNT6v80 hOnT6b/juwoIouwMTkGxbvxCw9f+73M= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-361--WB7nZTsPEu591VdmRuz5Q-1; Tue, 11 Mar 2025 07:31:54 -0400 X-MC-Unique: -WB7nZTsPEu591VdmRuz5Q-1 X-Mimecast-MFC-AGG-ID: -WB7nZTsPEu591VdmRuz5Q_1741692713 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 77667180AF4C for ; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 2BEF11801757 for ; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id EC50E21E64F7; Tue, 11 Mar 2025 12:31:37 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 15/61] docs/qapi-domain: add "Errors:" field lists Date: Tue, 11 Mar 2025 12:30:51 +0100 Message-ID: <20250311113137.1277125-16-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow ``:error: descr`` can now be used to document error conditions. The format of the description is not defined here; so the ability to name specific types is left to the document writer. Signed-off-by: John Snow Message-ID: <20250311034303.75779-18-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapi_domain.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py index 8ec4482b29..7535009078 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 GroupedField, TypedField +from sphinx.util.docfields import Field, GroupedField, TypedField from sphinx.util.nodes import make_id, make_refnode @@ -294,6 +294,13 @@ class QAPICommand(QAPIObject): names=("arg",), can_collapse=False, ), + # :error: descr + Field( + "error", + label=_("Errors"), + names=("error", "errors"), + has_arg=False, + ), ] ) From patchwork Tue Mar 11 11:30:52 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011563 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 9BA3CC282EC for ; Tue, 11 Mar 2025 11:37:11 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxr8-0003Wn-Vs; Tue, 11 Mar 2025 07:33:07 -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 1trxqW-0003Cz-80 for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:28 -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 1trxq7-0006VQ-1C for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:23 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692717; 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=bdvquLHI6GGmUASUDmeqDMm0k9Ul8PjFY+goxm/FAfM=; b=V8QEclNG+4tbdu1BZ+VAuElbDIwzJJ9vkjqdxpgWS4PYBd309hLbamMiCpSwU23kZDCMG3 jaV0GTGHsLd1Y1RwTT1Ya8E8ibdC2/3zIYU5f66d14/VadLn+/aVcih1OaYKALsAFHwriV 1YqwgUjvo+uFpdzLeTcU9eYdA/YJbj8= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-381-3qWP5D5NOxCUrHPdUBpopg-1; Tue, 11 Mar 2025 07:31:54 -0400 X-MC-Unique: 3qWP5D5NOxCUrHPdUBpopg-1 X-Mimecast-MFC-AGG-ID: 3qWP5D5NOxCUrHPdUBpopg_1741692713 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (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 mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id AEAFF19560B7 for ; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 565B91955BCB for ; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id F015121E64FB; Tue, 11 Mar 2025 12:31:37 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 16/61] docs/qapi-domain: add "Return:" field lists Date: Tue, 11 Mar 2025 12:30:52 +0100 Message-ID: <20250311113137.1277125-17-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow Add "Return:" 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. The syntax of the new field is: :return TypeName: description description cont'd This patch adds "Return" as a GroupedField, which means that multiple return values can be annotated - this is only done because Sphinx does not 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." The forthcoming QAPIDoc transmogrifier does not, in fact, ever "do that". Signed-off-by: John Snow Message-ID: <20250311034303.75779-19-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapi_domain.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py index 7535009078..45e69689d1 100644 --- a/docs/sphinx/qapi_domain.py +++ b/docs/sphinx/qapi_domain.py @@ -301,6 +301,13 @@ class QAPICommand(QAPIObject): names=("error", "errors"), has_arg=False, ), + # :return TypeName: descr + GroupedField( + "returnvalue", + label=_("Return"), + names=("return",), + can_collapse=True, + ), ] ) From patchwork Tue Mar 11 11:30:53 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011586 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 B163FC282EC for ; Tue, 11 Mar 2025 11:44:01 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxsQ-0006tL-FF; Tue, 11 Mar 2025 07:34:26 -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 1trxqW-0003Cw-7N for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:28 -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 1trxq4-0006Uv-JS for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:25 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692716; 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=iYZRPGi0gBXbuDfc+7wA62jvdqqY91oltspp9z9K/Bs=; b=gj21BAaD0Fz7gq1V9eTBJaRwj7v4DcyeUr2JmFPEAkdTQKNKN+VQ200rJTp/457mgX2zLl eFb5Upp5bsWVpXpDf36XzweMsvJFj+vYdbISWZhdEvqBuD8yc2y/0U7gmML07E9R376ttf OZHL6tEF1TouJYTjOfAu0pjtMV5yaW0= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-389-ub0DSv3yMe6pEq8oeooPDQ-1; Tue, 11 Mar 2025 07:31:54 -0400 X-MC-Unique: ub0DSv3yMe6pEq8oeooPDQ-1 X-Mimecast-MFC-AGG-ID: ub0DSv3yMe6pEq8oeooPDQ_1741692714 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (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 mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id D7616180AB1C for ; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 747ED3001D0E for ; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id F3D6421E675E; Tue, 11 Mar 2025 12:31:37 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 17/61] docs/qapi-domain: add qapi:enum directive Date: Tue, 11 Mar 2025 12:30:53 +0100 Message-ID: <20250311113137.1277125-18-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow 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 Message-ID: <20250311034303.75779-20-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapi_domain.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py index 45e69689d1..e399474dc5 100644 --- a/docs/sphinx/qapi_domain.py +++ b/docs/sphinx/qapi_domain.py @@ -312,6 +312,23 @@ class QAPICommand(QAPIObject): ) +class QAPIEnum(QAPIObject): + """Description of a QAPI Enum.""" + + doc_field_types = QAPIObject.doc_field_types.copy() + doc_field_types.extend( + [ + # :value name: descr + GroupedField( + "value", + label=_("Values"), + names=("value",), + can_collapse=False, + ) + ] + ) + + class QAPIModule(QAPIDescription): """ Directive to mark description of a new module. @@ -431,9 +448,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", "any"), "command": ObjType(_("command"), "cmd", "any"), + "enum": ObjType(_("enum"), "enum", "type", "any"), } # Each of these provides a rST directive, @@ -441,6 +463,7 @@ class QAPIDomain(Domain): directives = { "module": QAPIModule, "command": QAPICommand, + "enum": QAPIEnum, } # These are all cross-reference roles; e.g. @@ -449,6 +472,9 @@ class QAPIDomain(Domain): roles = { "mod": QAPIXRefRole(), "cmd": QAPIXRefRole(), + "enum": QAPIXRefRole(), + # reference any data type (excludes modules, commands, events) + "type": QAPIXRefRole(), "any": QAPIXRefRole(), # reference *any* type of QAPI object. } From patchwork Tue Mar 11 11:30:54 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011537 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 DA55CC282EC for ; Tue, 11 Mar 2025 11:33:39 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxqa-0003Ev-2Z; Tue, 11 Mar 2025 07:32:32 -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 1trxqE-000383-Ok for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:14 -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 1trxq2-0006Uo-MG for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:10 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692715; 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=r4iJVEy0u5pRD5/0vJ1dDhEmEleaG+zk/XWDcWBWEVs=; b=OTuF0e4rmbEcYjKjVKQQyY1ubYHJ6A0SPMNoqrxu6+ft1Txgqx/aAPmYN6UwT1ySBa0qQ2 6TVLAmaWtIxlfJXtK0syYAvc0qVVooSo867PPyaKgB2LRD2KEO+0/LteIc9B4kSky0yMAr lqneM1qsu7fr6fJNZbdvncTReguHrH0= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-355-RzjEHD0ZOcC1oT51AHYetQ-1; Tue, 11 Mar 2025 07:31:54 -0400 X-MC-Unique: RzjEHD0ZOcC1oT51AHYetQ-1 X-Mimecast-MFC-AGG-ID: RzjEHD0ZOcC1oT51AHYetQ_1741692713 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 5FECF1955F67 for ; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 032491800945 for ; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 04FD921E6497; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 18/61] docs/qapi-domain: add qapi:alternate directive Date: Tue, 11 Mar 2025 12:30:54 +0100 Message-ID: <20250311113137.1277125-19-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow Add the .. qapi:alternate:: directive, object, and qapi:alt:`name` cross-reference role. Add the "Alternatives:" 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. Signed-off-by: John Snow Message-ID: <20250311034303.75779-21-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapi_domain.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py index e399474dc5..506ed92700 100644 --- a/docs/sphinx/qapi_domain.py +++ b/docs/sphinx/qapi_domain.py @@ -329,6 +329,23 @@ class QAPIEnum(QAPIObject): ) +class QAPIAlternate(QAPIObject): + """Description of a QAPI Alternate.""" + + doc_field_types = QAPIObject.doc_field_types.copy() + doc_field_types.extend( + [ + # :alt type name: descr + TypedField( + "alternative", + label=_("Alternatives"), + names=("alt",), + can_collapse=False, + ), + ] + ) + + class QAPIModule(QAPIDescription): """ Directive to mark description of a new module. @@ -456,6 +473,7 @@ class QAPIDomain(Domain): "module": ObjType(_("module"), "mod", "any"), "command": ObjType(_("command"), "cmd", "any"), "enum": ObjType(_("enum"), "enum", "type", "any"), + "alternate": ObjType(_("alternate"), "alt", "type", "any"), } # Each of these provides a rST directive, @@ -464,6 +482,7 @@ class QAPIDomain(Domain): "module": QAPIModule, "command": QAPICommand, "enum": QAPIEnum, + "alternate": QAPIAlternate, } # These are all cross-reference roles; e.g. @@ -473,6 +492,7 @@ class QAPIDomain(Domain): "mod": QAPIXRefRole(), "cmd": QAPIXRefRole(), "enum": QAPIXRefRole(), + "alt": QAPIXRefRole(), # reference any data type (excludes modules, commands, events) "type": QAPIXRefRole(), "any": QAPIXRefRole(), # reference *any* type of QAPI object. From patchwork Tue Mar 11 11:30:55 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011590 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 2AE6BC35FF1 for ; Tue, 11 Mar 2025 11:45:45 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxs4-0005Q1-FR; Tue, 11 Mar 2025 07:34:05 -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 1trxqJ-0003A9-4K for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:15 -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 1trxq2-0006Us-Mm for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:14 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692715; 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=7iAMpLH0S4tkB/CSuTGIm3EY9NZe+vlRa5wgNKTRb08=; b=VKW7n7L2VOWv5uW19jm54Y3IPgaxJIw3gr09GgXv8bZVzjV4KCafOivEqKO3gqnqyqZ2OB Iuf07LjTkyTkVm3SYHkAV8q+RzXtk18735gDmW075k7CVHo4tNgb8P93CS/yTSeczkEJqG Axalj09kv07jK7n6rbWoB5lrZ3AiI4s= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-428-FqLXHrhANHapMKrqcrgvLw-1; Tue, 11 Mar 2025 07:31:54 -0400 X-MC-Unique: FqLXHrhANHapMKrqcrgvLw-1 X-Mimecast-MFC-AGG-ID: FqLXHrhANHapMKrqcrgvLw_1741692713 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (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 mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id AF26919560B8 for ; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 5B67D30001A2 for ; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 076AB21E6499; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 19/61] docs/qapi-domain: add qapi:event directive Date: Tue, 11 Mar 2025 12:30:55 +0100 Message-ID: <20250311113137.1277125-20-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Received-SPF: pass client-ip=170.10.133.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H2=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow 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. Signed-off-by: John Snow Message-ID: <20250311034303.75779-22-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapi_domain.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py index 506ed92700..3ffb3eb72d 100644 --- a/docs/sphinx/qapi_domain.py +++ b/docs/sphinx/qapi_domain.py @@ -346,6 +346,27 @@ class QAPIAlternate(QAPIObject): ) +class QAPIObjectWithMembers(QAPIObject): + """Base class for Events/Structs/Unions""" + + doc_field_types = QAPIObject.doc_field_types.copy() + doc_field_types.extend( + [ + # :member type name: descr + TypedField( + "member", + label=_("Members"), + names=("memb",), + can_collapse=False, + ), + ] + ) + + +class QAPIEvent(QAPIObjectWithMembers): + """Description of a QAPI Event.""" + + class QAPIModule(QAPIDescription): """ Directive to mark description of a new module. @@ -472,6 +493,7 @@ class QAPIDomain(Domain): object_types: Dict[str, ObjType] = { "module": ObjType(_("module"), "mod", "any"), "command": ObjType(_("command"), "cmd", "any"), + "event": ObjType(_("event"), "event", "any"), "enum": ObjType(_("enum"), "enum", "type", "any"), "alternate": ObjType(_("alternate"), "alt", "type", "any"), } @@ -481,6 +503,7 @@ class QAPIDomain(Domain): directives = { "module": QAPIModule, "command": QAPICommand, + "event": QAPIEvent, "enum": QAPIEnum, "alternate": QAPIAlternate, } @@ -491,6 +514,7 @@ class QAPIDomain(Domain): roles = { "mod": QAPIXRefRole(), "cmd": QAPIXRefRole(), + "event": QAPIXRefRole(), "enum": QAPIXRefRole(), "alt": QAPIXRefRole(), # reference any data type (excludes modules, commands, events) From patchwork Tue Mar 11 11:30:56 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011546 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 9DE04C282EC for ; Tue, 11 Mar 2025 11:35:41 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxqb-0003GR-2d; Tue, 11 Mar 2025 07:32: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 1trxqL-0003B1-4h for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:17 -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 1trxq2-0006Uq-Nv for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:16 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692715; 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=zMCCV60TbkWT6eOjqy0/DKgYc2iniJRfLzqDSQLP1mc=; b=ghRycBgLxKviz9V1SR6DwOrgP9ZUqlabGS5KiHW7S+OoaB34pa3Nt66YUp5YTWVDH21ma1 zy2jdvLpUUmowS8j1MkWwAB9tzmCQgR5gLEuAJl6NUK+hZDnLCAGYpSYIYjnFxRB+NYSDT 2DOUvW8AcFzeQRvNHYSDVltpqQW95zY= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-421-yjjUQTchO6CX3Z0XLG0mzw-1; Tue, 11 Mar 2025 07:31:54 -0400 X-MC-Unique: yjjUQTchO6CX3Z0XLG0mzw-1 X-Mimecast-MFC-AGG-ID: yjjUQTchO6CX3Z0XLG0mzw_1741692713 Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (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 mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id AE3F4195608B for ; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 595DB1956094 for ; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 0B36821E64A8; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 20/61] docs/qapi-domain: add qapi:object directive Date: Tue, 11 Mar 2025 12:30:56 +0100 Message-ID: <20250311113137.1277125-21-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, DKIM_INVALID=0.1, DKIM_SIGNED=0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no 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: John Snow Adds the .. qapi:object:: directive, object, and :qapi:obj:`name` cross-referencing role. This directive is meant to document both structs and unions. As per usual, QAPI cross-referencing for types in the member field list will be added in a forthcoming commit. Signed-off-by: John Snow Message-ID: <20250311034303.75779-23-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapi_domain.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py index 3ffb3eb72d..b11300bc85 100644 --- a/docs/sphinx/qapi_domain.py +++ b/docs/sphinx/qapi_domain.py @@ -367,6 +367,10 @@ class QAPIEvent(QAPIObjectWithMembers): """Description of a QAPI Event.""" +class QAPIJSONObject(QAPIObjectWithMembers): + """Description of a QAPI Object: structs and unions.""" + + class QAPIModule(QAPIDescription): """ Directive to mark description of a new module. @@ -495,6 +499,7 @@ class QAPIDomain(Domain): "command": ObjType(_("command"), "cmd", "any"), "event": ObjType(_("event"), "event", "any"), "enum": ObjType(_("enum"), "enum", "type", "any"), + "object": ObjType(_("object"), "obj", "type", "any"), "alternate": ObjType(_("alternate"), "alt", "type", "any"), } @@ -505,6 +510,7 @@ class QAPIDomain(Domain): "command": QAPICommand, "event": QAPIEvent, "enum": QAPIEnum, + "object": QAPIJSONObject, "alternate": QAPIAlternate, } @@ -516,6 +522,7 @@ class QAPIDomain(Domain): "cmd": QAPIXRefRole(), "event": QAPIXRefRole(), "enum": QAPIXRefRole(), + "obj": QAPIXRefRole(), # specifically structs and unions. "alt": QAPIXRefRole(), # reference any data type (excludes modules, commands, events) "type": QAPIXRefRole(), From patchwork Tue Mar 11 11:30:57 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011569 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 BEC39C282EC for ; Tue, 11 Mar 2025 11:39:03 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxsG-0005rA-8P; Tue, 11 Mar 2025 07:34:16 -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 1trxqN-0003Bm-OC for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:20 -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 1trxq4-0006Vf-12 for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:19 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692717; 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=JLZlz2uI650EPNnAM7UdPDCfQjGsEu2vAEr73jJzngE=; b=Z+OsSGmQ5QjLsxzVF3uSDzPkkKFrvS7/PiyYRgHaAVhDYRo8UzfGnv4DG1Z9EkOOGIEyxb 6tREk67FLd3SRgCBgHs48V9nsCWVXt8oJtd2W/+lbewVlwbUIoCdXJKS2+8tfNIqh4vTfe O3kHvJ4+aN5dxYR/TljQuLDY+zmG87Q= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-504-pZMCyK4yMRenwaK5X38DGA-1; Tue, 11 Mar 2025 07:31:54 -0400 X-MC-Unique: pZMCyK4yMRenwaK5X38DGA-1 X-Mimecast-MFC-AGG-ID: pZMCyK4yMRenwaK5X38DGA_1741692713 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 84F0C1956080; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 2BF331801758; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 0F21F21E64AA; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow , Harmonie Snow Subject: [PULL 21/61] docs/qapi-domain: add :deprecated: directive option Date: Tue, 11 Mar 2025 12:30:57 +0100 Message-ID: <20250311113137.1277125-22-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass client-ip=170.10.133.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H2=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow 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 forthcoming Transmogrifier in qapidoc.py will add this option whenever it detects that the features list attached to a definition contains the "deprecated" entry. P.S., I outsourced the CSS ;) Signed-off-by: Harmonie Snow Signed-off-by: John Snow Message-ID: <20250311034303.75779-24-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx-static/theme_overrides.css | 25 +++++++++++++++++++++++++ docs/sphinx/qapi_domain.py | 26 ++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/docs/sphinx-static/theme_overrides.css b/docs/sphinx-static/theme_overrides.css index 965ecac54f..3765cab1b2 100644 --- a/docs/sphinx-static/theme_overrides.css +++ b/docs/sphinx-static/theme_overrides.css @@ -208,3 +208,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 b11300bc85..b672ae6c50 100644 --- a/docs/sphinx/qapi_domain.py +++ b/docs/sphinx/qapi_domain.py @@ -217,6 +217,7 @@ class QAPIObject(QAPIDescription): "module": directives.unchanged, # Override contextual module name # These are QAPI originals: "since": directives.unchanged, + "deprecated": directives.flag, } ) @@ -280,6 +281,31 @@ def handle_signature(self, sig: str, signode: desc_signature) -> Signature: return sig + 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 transform_content(self, content_node: addnodes.desc_content) -> None: + self._add_infopips(content_node) + class QAPICommand(QAPIObject): """Description of a QAPI Command.""" From patchwork Tue Mar 11 11:30:58 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011542 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 17126C282EC for ; Tue, 11 Mar 2025 11:34:41 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxqf-0003K5-3h; Tue, 11 Mar 2025 07:32:37 -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 1trxqW-0003Cu-6u for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:28 -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 1trxq3-0006Vd-OP for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:23 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692717; 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=Z5JnxTF2fWSokQik72i6XozThJKgzO0cO0R+SFAf/nI=; b=e9NJNwTgo2A6odpgwFTK9me9gqwtKHjhNwCIXTI1XCUvKMzZvKUbvUxXpU6zVs7rMux3b8 ijdv7n3QdiXEtH+R9/fk1/oa7b52DPQCVWxK3DcE80xBL59lR30hNDvVeyrgQoIedkifIF wM9xMBCgvOj0XbZLuDqlqmRDz2migg8= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-621-2OvqSt-NNteRZqRALzyZ3w-1; Tue, 11 Mar 2025 07:31:54 -0400 X-MC-Unique: 2OvqSt-NNteRZqRALzyZ3w-1 X-Mimecast-MFC-AGG-ID: 2OvqSt-NNteRZqRALzyZ3w_1741692713 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 7A0DB1956059; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 128591801756; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 12DAA21E64AC; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow , Harmonie Snow Subject: [PULL 22/61] docs/qapi-domain: add :unstable: directive option Date: Tue, 11 Mar 2025 12:30:58 +0100 Message-ID: <20250311113137.1277125-23-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow 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 forthcoming Transmogrifier in qapidoc.py will add this option whenever it detects that the features list attached to a definition contains the "unstable" entry. Signed-off-by: Harmonie Snow Signed-off-by: John Snow Message-ID: <20250311034303.75779-25-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx-static/theme_overrides.css | 6 +++++- docs/sphinx/qapi_domain.py | 8 ++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/sphinx-static/theme_overrides.css b/docs/sphinx-static/theme_overrides.css index 3765cab1b2..5f58f1d524 100644 --- a/docs/sphinx-static/theme_overrides.css +++ b/docs/sphinx-static/theme_overrides.css @@ -221,7 +221,7 @@ div[class^="highlight"] pre { margin: 0.25em; } -.qapi-deprecated { +.qapi-deprecated,.qapi-unstable { background-color: #fffef5; border: solid #fff176 6px; font-weight: bold; @@ -230,6 +230,10 @@ div[class^="highlight"] pre { margin: 5px; } +.qapi-unstable::before { + content: ' From patchwork Tue Mar 11 11:30:59 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011561 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 C6476C282EC for ; Tue, 11 Mar 2025 11:36:45 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxsK-0006Ea-TR; Tue, 11 Mar 2025 07:34:20 -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 1trxqP-0003CW-UE for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:22 -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 1trxq6-0006W2-2p for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:20 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692718; 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=kAYqniCMLzAyv5FL5S5fpS2iROklEwvuiGIfKWs8y8A=; b=UkutpKkqTrfxCROvNjh5kN4l84WalVndyEJuWWfyJOkN5+JeAas6VRNTs/tOa0P4RWmJjr 9HIENur/XIRoAaxH88V9Nv90idxFa1/aEIFloHuNyV/h0hJTEQmTuh1DnouiMe8/FucVaK a61gzGtAS84cEiBc1G6lARnc97YxJRE= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-421-ZwbIyeHCP0-15qGDJiU3tg-1; Tue, 11 Mar 2025 07:31:54 -0400 X-MC-Unique: ZwbIyeHCP0-15qGDJiU3tg-1 X-Mimecast-MFC-AGG-ID: ZwbIyeHCP0-15qGDJiU3tg_1741692713 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (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 mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id A37851955F69; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 2CA3219560AB; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 171C321E64AE; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow , Harmonie Snow Subject: [PULL 23/61] docs/qapi-domain: add :ifcond: directive option Date: Tue, 11 Mar 2025 12:30:59 +0100 Message-ID: <20250311113137.1277125-24-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow Add a special :ifcond: option that allows us to annotate the definition-level conditionals. The syntax of the argument is currently undefined, but it's possible we can apply better formatting in the future. Currently, we just display the ifcond string as preformatted text. Signed-off-by: Harmonie Snow Signed-off-by: John Snow Message-ID: <20250311034303.75779-26-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx-static/theme_overrides.css | 13 +++++++++++++ docs/sphinx/qapi_domain.py | 23 +++++++++++++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/docs/sphinx-static/theme_overrides.css b/docs/sphinx-static/theme_overrides.css index 5f58f1d524..3fd326613d 100644 --- a/docs/sphinx-static/theme_overrides.css +++ b/docs/sphinx-static/theme_overrides.css @@ -237,3 +237,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 Tue Mar 11 11:31:00 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011562 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 9F71FC28B2E for ; Tue, 11 Mar 2025 11:36:46 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxqb-0003Gk-A8; Tue, 11 Mar 2025 07:32: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 1trxqO-0003Bs-01 for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:20 -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 1trxq3-0006Vj-Tm for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:19 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692717; 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=qZu5A5HVKpNveCGYnJSjm3oY88cHVB8L/mvhdhIhxjQ=; b=KULcTU/2Ej1izq1v7jWw/4ksvblLUbkzqLX6OYuq7U32x8Y2ke6qqj1WcFwbJd3r3Xjj3l eGc7x/bMLMKdAWu6gJbPgTNUFR758lFr8qD7xnuFjqvrEEOpj0Ijj5nauy8gzr1szyzYqN pWx8lElFbLKuMCO8gJ7Bg9kAvRQd/PA= Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-499-42aZZNdIP1y2g7Th5lBh-Q-1; Tue, 11 Mar 2025 07:31:56 -0400 X-MC-Unique: 42aZZNdIP1y2g7Th5lBh-Q-1 X-Mimecast-MFC-AGG-ID: 42aZZNdIP1y2g7Th5lBh-Q_1741692715 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (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 mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 0134719560B7 for ; Tue, 11 Mar 2025 11:31:54 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 55410195608F for ; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 1AF3F21E64B1; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 24/61] docs/qapi-domain: add warnings for malformed field lists Date: Tue, 11 Mar 2025 12:31:00 +0100 Message-ID: <20250311113137.1277125-25-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, T_SPF_TEMPERROR=0.01 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: John Snow 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. Signed-off-by: John Snow Message-ID: <20250311034303.75779-27-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/conf.py | 9 +++++ docs/sphinx/qapi_domain.py | 74 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/docs/conf.py b/docs/conf.py index 49d9de894c..a3f9fa63d9 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -153,6 +153,15 @@ 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 = { + "see also", +} + + # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py index 4531b5d857..9fe006eef3 100644 --- a/docs/sphinx/qapi_domain.py +++ b/docs/sphinx/qapi_domain.py @@ -49,6 +49,19 @@ logger = logging.getLogger(__name__) +def _unpack_field( + field: nodes.Node, +) -> Tuple[nodes.field_name, nodes.field_body]: + """ + docutils helper: unpack a field node in a type-safe manner. + """ + assert isinstance(field, nodes.field) + assert len(field.children) == 2 + assert isinstance(field.children[0], nodes.field_name) + assert isinstance(field.children[1], nodes.field_body) + return (field.children[0], field.children[1]) + + class ObjectEntry(NamedTuple): docname: str node_id: str @@ -330,9 +343,64 @@ def _add_pip( if infopips.children: contentnode.insert(0, infopips) + def _validate_field(self, field: nodes.field) -> None: + """Validate field lists in this QAPI Object Description.""" + name, _ = _unpack_field(field) + allowed_fields = set(self.env.app.config.qapi_allowed_fields) + + field_label = name.astext() + if field_label in allowed_fields: + # Explicitly allowed field list name, OK. + return + + try: + # split into field type and argument (if provided) + # e.g. `:arg type name: descr` is + # field_type = "arg", field_arg = "type name". + field_type, field_arg = field_label.split(None, 1) + except ValueError: + # No arguments provided + field_type = field_label + field_arg = "" + + typemap = self.get_field_type_map() + if field_type in typemap: + # This is a special docfield, yet-to-be-processed. Catch + # correct names, but incorrect arguments. This mismatch WILL + # cause Sphinx to render this field incorrectly (without a + # warning), which is never what we want. + typedesc = typemap[field_type][0] + if typedesc.has_arg != bool(field_arg): + msg = f"docfield 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. It's valid rST to use + # arbitrary fields, but let's ensure the documentation + # writer has done this intentionally. + 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, content_node: addnodes.desc_content) -> None: self._add_infopips(content_node) + # Validate field lists. + for child in content_node: + if isinstance(child, nodes.field_list): + for field in child.children: + assert isinstance(field, nodes.field) + self._validate_field(field) + class QAPICommand(QAPIObject): """Description of a QAPI Command.""" @@ -769,6 +837,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 Tue Mar 11 11:31:01 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011574 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 24133C282EC for ; Tue, 11 Mar 2025 11:40:55 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxsU-00074O-0k; Tue, 11 Mar 2025 07:34:30 -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 1trxrM-0003wC-NM for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:33:21 -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 1trxrC-0006mD-9D for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:33:20 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692789; 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=n2UvpuDlRGMy9AJ9cAmINv4qPS+gh0yoTEPLCGHQ/U4=; b=d3rYA/WW/CQ9UYuLZkzs0dHtMwrUB1VldZQOjmddhKzAnt7z9Jr+zpR5KOSZWidyBp3sK9 534mPUH6iRPjYIoHrXNeZJilfg9D2odVsRJqAZONIatEmQeLxoJylu7vdHITShTZH9ErzR h51ivjxjqPHzlKcSrWnNcXkYCecGwB0= Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-661--LcROBTZOP-paD3Yj5WrBA-1; Tue, 11 Mar 2025 07:31:56 -0400 X-MC-Unique: -LcROBTZOP-paD3Yj5WrBA-1 X-Mimecast-MFC-AGG-ID: -LcROBTZOP-paD3Yj5WrBA_1741692715 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (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 mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 7A74319560AB for ; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 2CA5919560AD for ; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 1EBFA21E64B5; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 25/61] docs/qapi-domain: add type cross-refs to field lists Date: Tue, 11 Mar 2025 12:31:01 +0100 Message-ID: <20250311113137.1277125-26-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 Received-SPF: pass client-ip=170.10.133.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H2=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, T_SPF_TEMPERROR=0.01 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: John Snow 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 rST that would cause parsing errors, we elect to use "?" instead. The special syntax processing 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. Signed-off-by: John Snow Message-ID: <20250311034303.75779-28-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapi_domain.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py index 9fe006eef3..06fe78ce0b 100644 --- a/docs/sphinx/qapi_domain.py +++ b/docs/sphinx/qapi_domain.py @@ -2,6 +2,9 @@ QAPI domain extension. """ +# The best laid plans of mice and men, ... +# pylint: disable=too-many-lines + from __future__ import annotations from typing import ( @@ -116,6 +119,28 @@ def process_link( return title, target + def result_nodes( + self, + document: nodes.document, + env: BuildEnvironment, + node: Element, + is_ref: bool, + ) -> Tuple[List[nodes.Node], List[nodes.system_message]]: + + # node here is the pending_xref node (or whatever nodeclass was + # configured at XRefRole class instantiation time). + results: List[nodes.Node] = [node] + + if node.get("qapi:array"): + results.insert(0, nodes.literal("[", "[")) + results.append(nodes.literal("]", "]")) + + if node.get("qapi:optional"): + results.append(nodes.Text(", ")) + results.append(nodes.emphasis("?", "optional")) + + return results, [] + # Alias for the return of handle_signature(), which is used in several places. # (In the Python domain, this is Tuple[str, str] instead.) @@ -413,6 +438,7 @@ class QAPICommand(QAPIObject): "argument", label=_("Arguments"), names=("arg",), + typerolename="type", can_collapse=False, ), # :error: descr @@ -426,6 +452,7 @@ class QAPICommand(QAPIObject): GroupedField( "returnvalue", label=_("Return"), + rolename="type", names=("return",), can_collapse=True, ), @@ -461,6 +488,7 @@ class QAPIAlternate(QAPIObject): "alternative", label=_("Alternatives"), names=("alt",), + typerolename="type", can_collapse=False, ), ] @@ -478,6 +506,7 @@ class QAPIObjectWithMembers(QAPIObject): "member", label=_("Members"), names=("memb",), + typerolename="type", can_collapse=False, ), ] From patchwork Tue Mar 11 11:31:02 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011614 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 371DAC28B30 for ; Tue, 11 Mar 2025 11:52:22 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxqd-0003JA-Vj; Tue, 11 Mar 2025 07:32:36 -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 1trxqN-0003Bn-OI for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:20 -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 1trxq4-0006WF-Nv for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:19 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692719; 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=6Hlbs1hovEuCbdsqBe7iz8d3ED9SWpS2plDRmLQQt/o=; b=g7A6hJ+k4QKp4zILkU0m6+Try5/ve+1hmLMMGhQ5rWQYUy4HWDHiwpWYNICv5GxFIzK4Bh DKGt5JyHhet3acpuLmhakeXDkb/Q/Rjf1c38btZnzzSgubTOpfkZ9RE2baxWXIM6eWgeq2 P5HUnDUbC66emEvd2ZEoJk8YBbRq00c= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-361-Z1zVohkDNcapuZacMkEjfQ-1; Tue, 11 Mar 2025 07:31:54 -0400 X-MC-Unique: Z1zVohkDNcapuZacMkEjfQ-1 X-Mimecast-MFC-AGG-ID: Z1zVohkDNcapuZacMkEjfQ_1741692713 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (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 mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 8284B1800267; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 133A118001E9; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 2297C21E64B6; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow , Harmonie Snow Subject: [PULL 26/61] docs/qapi-domain: add CSS styling Date: Tue, 11 Mar 2025 12:31:02 +0100 Message-ID: <20250311113137.1277125-27-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John 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 Message-ID: <20250311034303.75779-29-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx-static/theme_overrides.css | 56 +++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/docs/sphinx-static/theme_overrides.css b/docs/sphinx-static/theme_overrides.css index 3fd326613d..b225bf706f 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; } @@ -211,6 +211,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; } @@ -250,3 +262,43 @@ 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; +} + +/* Sphinx 3.x: unresolved xrefs */ +.rst-content *:not(a) > code.xref { + font-weight: 400; + color: #333333; +} From patchwork Tue Mar 11 11:31:03 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011607 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 6B64CC282EC for ; Tue, 11 Mar 2025 11:51:13 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxqd-0003IR-8S; Tue, 11 Mar 2025 07:32:35 -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 1trxqG-00038Q-QF for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:14 -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 1trxq2-0006VA-Ox for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:12 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692716; 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=5fZBYHPU0s8pnspvGGVnSt0xUuMA4YP0JAp3hNrbBEI=; b=Mrltsf1saC5q7yzAMKJL2MFFhajMZY32Vvf0/PbT3lv3NyBxPJJTPBh+qnwkvE9/GEWOPa MRoRrozAvra78jIavgvL9xRMFq6PPFsmcM59fVe1PmHOKf+Lvyr1TpoZ1hwEevZ+YHaliZ XqNReAoPR7P2VVXs5gNMkJB6srzAto0= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-651-smId9DynP-SzZnAlpwPY_g-1; Tue, 11 Mar 2025 07:31:54 -0400 X-MC-Unique: smId9DynP-SzZnAlpwPY_g-1 X-Mimecast-MFC-AGG-ID: smId9DynP-SzZnAlpwPY_g_1741692714 Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (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 mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 01EA31955BCC for ; Tue, 11 Mar 2025 11:31:54 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 596CE19560B9 for ; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 268DA21E64BD; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 27/61] docs/qapi-domain: add XREF compatibility goop for Sphinx < 4.1 Date: Tue, 11 Mar 2025 12:31:03 +0100 Message-ID: <20250311113137.1277125-28-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow Sphinx < 4.1 handles cross-references ... differently. Factor out and isolate the compatibility goop we need to make cross references work properly in old versions of Sphinx. Yes, it's ugly. Yes, it works. No, I don't want to talk about it. Understand that this patch exists because of the overflowing love in my heart. Signed-off-by: John Snow Message-ID: <20250311034303.75779-30-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/compat.py | 136 +++++++++++++++++++++++++++++++++++-- docs/sphinx/qapi_domain.py | 23 ++++--- 2 files changed, 144 insertions(+), 15 deletions(-) diff --git a/docs/sphinx/compat.py b/docs/sphinx/compat.py index 6bc698c5ad..f068d70388 100644 --- a/docs/sphinx/compat.py +++ b/docs/sphinx/compat.py @@ -2,14 +2,31 @@ Sphinx cross-version compatibility goop """ -from typing import Callable +import re +from typing import ( + Any, + Callable, + Optional, + Type, +) +from docutils import nodes from docutils.nodes import Element, Node, Text import sphinx -from sphinx import addnodes -from sphinx.util import nodes -from sphinx.util.docutils import SphinxDirective, switch_source_input +from sphinx import addnodes, util +from sphinx.environment import BuildEnvironment +from sphinx.roles import XRefRole +from sphinx.util import docfields +from sphinx.util.docutils import ( + ReferenceRole, + SphinxDirective, + switch_source_input, +) +from sphinx.util.typing import TextlikeNode + + +MAKE_XREF_WORKAROUND = sphinx.version_info[:3] < (4, 1, 0) SpaceNode: Callable[[str], Node] @@ -36,7 +53,7 @@ def nested_parse_with_titles( try: # Modern sphinx (6.2.0+) supports proper offsetting for # nested parse error context management - nodes.nested_parse_with_titles( + util.nodes.nested_parse_with_titles( directive.state, directive.content, content_node, @@ -45,6 +62,113 @@ def nested_parse_with_titles( except TypeError: # No content_offset argument. Fall back to SSI method. with switch_source_input(directive.state, directive.content): - nodes.nested_parse_with_titles( + util.nodes.nested_parse_with_titles( directive.state, directive.content, content_node ) + + +# ########################################### +# xref compatibility hacks for Sphinx < 4.1 # +# ########################################### + +# When we require >= Sphinx 4.1, the following function and the +# subsequent 3 compatibility classes can be removed. Anywhere in +# qapi_domain that uses one of these Compat* types can be switched to +# using the garden-variety lib-provided classes with no trickery. + + +def _compat_make_xref( # pylint: disable=unused-argument + self: sphinx.util.docfields.Field, + rolename: str, + domain: str, + target: str, + innernode: Type[TextlikeNode] = addnodes.literal_emphasis, + contnode: Optional[Node] = None, + env: Optional[BuildEnvironment] = None, + inliner: Any = None, + location: Any = None, +) -> Node: + """ + Compatibility workaround for Sphinx versions prior to 4.1.0. + + Older sphinx versions do not use the domain's XRefRole for parsing + and formatting cross-references, so we need to perform this magick + ourselves to avoid needing to write the parser/formatter in two + separate places. + + This workaround isn't brick-for-brick compatible with modern Sphinx + versions, because we do not have access to the parent directive's + state during this parsing like we do in more modern versions. + + It's no worse than what pre-Sphinx 4.1.0 does, so... oh well! + """ + + # Yes, this function is gross. Pre-4.1 support is a miracle. + # pylint: disable=too-many-locals + + assert env + # Note: Sphinx's own code ignores the type warning here, too. + if not rolename: + return contnode or innernode(target, target) # type: ignore[call-arg] + + # Get the role instance, but don't *execute it* - we lack the + # correct state to do so. Instead, we'll just use its public + # methods to do our reference formatting, and emulate the rest. + role = env.get_domain(domain).roles[rolename] + assert isinstance(role, XRefRole) + + # XRefRole features not supported by this compatibility shim; + # these were not supported in Sphinx 3.x either, so nothing of + # value is really lost. + assert not target.startswith("!") + assert not re.match(ReferenceRole.explicit_title_re, target) + assert not role.lowercase + assert not role.fix_parens + + # Code below based mostly on sphinx.roles.XRefRole; run() and + # create_xref_node() + options = { + "refdoc": env.docname, + "refdomain": domain, + "reftype": rolename, + "refexplicit": False, + "refwarn": role.warn_dangling, + } + refnode = role.nodeclass(target, **options) + title, target = role.process_link(env, refnode, False, target, target) + refnode["reftarget"] = target + classes = ["xref", domain, f"{domain}-{rolename}"] + refnode += role.innernodeclass(target, title, classes=classes) + + # This is the very gross part of the hack. Normally, + # result_nodes takes a document object to which we would pass + # self.inliner.document. Prior to Sphinx 4.1, we don't *have* an + # inliner to pass, so we have nothing to pass here. However, the + # actual implementation of role.result_nodes in this case + # doesn't actually use that argument, so this winds up being + # ... fine. Rest easy at night knowing this code only runs under + # old versions of Sphinx, so at least it won't change in the + # future on us and lead to surprising new failures. + # Gross, I know. + result_nodes, _messages = role.result_nodes( + None, # type: ignore + env, + refnode, + is_ref=True, + ) + return nodes.inline(target, "", *result_nodes) + + +class CompatField(docfields.Field): + if MAKE_XREF_WORKAROUND: + make_xref = _compat_make_xref + + +class CompatGroupedField(docfields.GroupedField): + if MAKE_XREF_WORKAROUND: + make_xref = _compat_make_xref + + +class CompatTypedField(docfields.TypedField): + if MAKE_XREF_WORKAROUND: + make_xref = _compat_make_xref diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py index 06fe78ce0b..3b1490e29a 100644 --- a/docs/sphinx/qapi_domain.py +++ b/docs/sphinx/qapi_domain.py @@ -24,7 +24,13 @@ from docutils import nodes from docutils.parsers.rst import directives -from compat import KeywordNode, SpaceNode +from compat import ( + CompatField, + CompatGroupedField, + CompatTypedField, + KeywordNode, + SpaceNode, +) from sphinx import addnodes from sphinx.addnodes import desc_signature, pending_xref from sphinx.directives import ObjectDescription @@ -37,7 +43,6 @@ from sphinx.locale import _, __ from sphinx.roles import XRefRole from sphinx.util import logging -from sphinx.util.docfields import Field, GroupedField, TypedField from sphinx.util.nodes import make_id, make_refnode @@ -264,7 +269,7 @@ class QAPIObject(QAPIDescription): doc_field_types = [ # :feat name: descr - GroupedField( + CompatGroupedField( "feature", label=_("Features"), names=("feat",), @@ -434,7 +439,7 @@ class QAPICommand(QAPIObject): doc_field_types.extend( [ # :arg TypeName ArgName: descr - TypedField( + CompatTypedField( "argument", label=_("Arguments"), names=("arg",), @@ -442,14 +447,14 @@ class QAPICommand(QAPIObject): can_collapse=False, ), # :error: descr - Field( + CompatField( "error", label=_("Errors"), names=("error", "errors"), has_arg=False, ), # :return TypeName: descr - GroupedField( + CompatGroupedField( "returnvalue", label=_("Return"), rolename="type", @@ -467,7 +472,7 @@ class QAPIEnum(QAPIObject): doc_field_types.extend( [ # :value name: descr - GroupedField( + CompatGroupedField( "value", label=_("Values"), names=("value",), @@ -484,7 +489,7 @@ class QAPIAlternate(QAPIObject): doc_field_types.extend( [ # :alt type name: descr - TypedField( + CompatTypedField( "alternative", label=_("Alternatives"), names=("alt",), @@ -502,7 +507,7 @@ class QAPIObjectWithMembers(QAPIObject): doc_field_types.extend( [ # :member type name: descr - TypedField( + CompatTypedField( "member", label=_("Members"), names=("memb",), From patchwork Tue Mar 11 11:31:04 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011540 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 278F7C282EC for ; Tue, 11 Mar 2025 11:34:36 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxqb-0003Eh-2P; Tue, 11 Mar 2025 07:32: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 1trxqD-00037e-B2 for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:13 -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 1trxq2-0006V3-Gm for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:08 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692716; 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=8w8JPzbCqCu7+BNJ2brD8hkE/otEgSOTWftx8sadi7A=; b=Ni03+DA4FiaLktdK8Vl/ZtKHKSsQ6yXQcFBjoXPgrsOn/3v4k+O2JIJP2vLA8hjJYHPblf BYqZf7CZ5k4hR1ja1aorQ+1ut1H/WDvzIW7idea773d0K58LEjlIGe8kWtrD4CCE8WcRhr gtOdFpDOkmBeDvmAbUqj3P4jWdLv4O0= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-468-n7KxawBkMxC24UgtQUOGqw-1; Tue, 11 Mar 2025 07:31:54 -0400 X-MC-Unique: n7KxawBkMxC24UgtQUOGqw-1 X-Mimecast-MFC-AGG-ID: n7KxawBkMxC24UgtQUOGqw_1741692714 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (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 mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id E8CB9180AF66 for ; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 9CDB71828A92 for ; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 2A5D321E6187; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 28/61] docs/qapi-domain: warn when QAPI domain xrefs fail to resolve Date: Tue, 11 Mar 2025 12:31:04 +0100 Message-ID: <20250311113137.1277125-29-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass client-ip=170.10.133.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H2=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow This patch adds a warning (which is a build failure under our current build settings) whenever a QAPI cross-reference fails to resolve. This applies to any cross-references of the form :qapi:{role}:`foo`, which covers all of the automatically generated references by the qapi domain, and any such references that are manually written into the documentation rst files. Cross-references of the form `foo` do not use this system, but are already configured to issue a warning (Again, a build failure) if the cross-reference isn't found anywhere. Adds warnings that look like the following: docs/qapi/index.rst:48: WARNING: qapi:type reference target not found: 'footype' [ref.qapi] docs/qapi/index.rst:50: WARNING: qapi:mod reference target not found: 'foomod' [ref.qapi] Signed-off-by: John Snow Message-ID: <20250311034303.75779-31-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapi_domain.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py index 3b1490e29a..b23db1eba2 100644 --- a/docs/sphinx/qapi_domain.py +++ b/docs/sphinx/qapi_domain.py @@ -830,6 +830,29 @@ def resolve_xref( matches = self.find_obj(modname, target, typ) if not matches: + # Normally, we could pass warn_dangling=True to QAPIXRefRole(), + # but that will trigger on references to these built-in types, + # which we'd like to ignore instead. + + # Take care of that warning here instead, so long as the + # reference isn't to one of our built-in core types. + if target not in ( + "string", + "number", + "int", + "boolean", + "null", + "value", + "q_empty", + ): + logger.warning( + __("qapi:%s reference target not found: %r"), + typ, + target, + type="ref", + subtype="qapi", + location=node, + ) return None if len(matches) > 1: From patchwork Tue Mar 11 11:31:05 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011536 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 D6DDEC282EC for ; Tue, 11 Mar 2025 11:33:34 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxqZ-0003EO-Mt; Tue, 11 Mar 2025 07:32:31 -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 1trxqF-000385-N6 for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:14 -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 1trxq2-0006VC-LU for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:11 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692716; 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=MzgzaaGvIpDq4XniT4JU4yhPMfUYhG5BKDfJM+EEXp4=; b=HJxzaP31EremXVr1+GRcULs+GtM0xEesyrPdv3t3kBqq38FrUi2HRyIqVRO+58zI1YwIil 6ydKHEquVUDyb0y47g8nAfcPg8N5oek67yjeT1+w7cq8BVwprk1kuu7BtvdD2sCSMSZjgV bQEOKWVhz+GUQgeBZGcDFGEuRptq6Ps= Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-395-lYCE5hv4MziH34GkqMnTnw-1; Tue, 11 Mar 2025 07:31:55 -0400 X-MC-Unique: lYCE5hv4MziH34GkqMnTnw-1 X-Mimecast-MFC-AGG-ID: lYCE5hv4MziH34GkqMnTnw_1741692714 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 5DFF51955DDE for ; Tue, 11 Mar 2025 11:31:54 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id A76B2180094A for ; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 2E2A621E61A4; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 29/61] docs/qapi-domain: Fix error context reporting in Sphinx 5.x and 6.x Date: Tue, 11 Mar 2025 12:31:05 +0100 Message-ID: <20250311113137.1277125-30-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow 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. The reporting will be incorrect.) 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 Message-ID: <20250311034303.75779-32-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/compat.py | 56 ++++++++++++++++++++++++++++++++++++++ docs/sphinx/qapi_domain.py | 15 ++++++---- 2 files changed, 65 insertions(+), 6 deletions(-) diff --git a/docs/sphinx/compat.py b/docs/sphinx/compat.py index f068d70388..9cf7fe006e 100644 --- a/docs/sphinx/compat.py +++ b/docs/sphinx/compat.py @@ -4,6 +4,7 @@ import re from typing import ( + TYPE_CHECKING, Any, Callable, Optional, @@ -12,9 +13,11 @@ from docutils import nodes from docutils.nodes import Element, Node, Text +from docutils.statemachine import StringList import sphinx from sphinx import addnodes, util +from sphinx.directives import ObjectDescription from sphinx.environment import BuildEnvironment from sphinx.roles import XRefRole from sphinx.util import docfields @@ -172,3 +175,56 @@ class CompatGroupedField(docfields.GroupedField): class CompatTypedField(docfields.TypedField): if MAKE_XREF_WORKAROUND: make_xref = _compat_make_xref + + +# ################################################################ +# Nested parsing error location fix for Sphinx 5.3.0 < x < 6.2.0 # +# ################################################################ + +# When we require Sphinx 4.x, the TYPE_CHECKING hack where we avoid +# subscripting ObjectDescription at runtime can be removed in favor of +# just always subscripting the class. + +# When we require Sphinx > 6.2.0, the rest of this compatibility hack +# can be dropped and QAPIObject can just inherit directly from +# ObjectDescription[Signature]. + +SOURCE_LOCATION_FIX = (5, 3, 0) <= sphinx.version_info[:3] < (6, 2, 0) + +Signature = str + + +if TYPE_CHECKING: + _BaseClass = ObjectDescription[Signature] +else: + _BaseClass = ObjectDescription + + +class ParserFix(_BaseClass): + + _temp_content: StringList + _temp_offset: int + _temp_node: Optional[addnodes.desc_content] + + 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 SOURCE_LOCATION_FIX: + 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, content_node: addnodes.desc_content) -> None: + # Sphinx workaround: Inject our parsed content and restore state. + if self._temp_node: + content_node += self._temp_node.children + self.content = self._temp_content + self.content_offset = self._temp_offset diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py index b23db1eba2..ca3f3a7e2d 100644 --- a/docs/sphinx/qapi_domain.py +++ b/docs/sphinx/qapi_domain.py @@ -29,6 +29,8 @@ CompatGroupedField, CompatTypedField, KeywordNode, + ParserFix, + Signature, SpaceNode, ) from sphinx import addnodes @@ -147,12 +149,7 @@ def result_nodes( return results, [] -# 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 QAPIDescription(ObjectDescription[Signature]): +class QAPIDescription(ParserFix): """ Generic QAPI description. @@ -422,6 +419,10 @@ def _validate_field(self, field: nodes.field) -> None: logger.warning(msg, location=field) def transform_content(self, content_node: addnodes.desc_content) -> None: + # This hook runs after before_content and the nested parse, but + # before the DocFieldTransformer is executed. + super().transform_content(content_node) + self._add_infopips(content_node) # Validate field lists. @@ -519,10 +520,12 @@ class QAPIObjectWithMembers(QAPIObject): class QAPIEvent(QAPIObjectWithMembers): + # pylint: disable=too-many-ancestors """Description of a QAPI Event.""" class QAPIJSONObject(QAPIObjectWithMembers): + # pylint: disable=too-many-ancestors """Description of a QAPI Object: structs and unions.""" From patchwork Tue Mar 11 11:31:06 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011622 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 D87FDC282EC for ; Tue, 11 Mar 2025 11:53:25 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxsA-0005bI-Tr; Tue, 11 Mar 2025 07:34:11 -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 1trxqL-0003Aw-3F for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:17 -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 1trxq3-0006V1-OT for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:16 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692716; 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=PdZ/jotGGHqzTZZfbwXEHi2HslXgTGd6lARWNm/H+78=; b=AtWd4BDvwrL/AuS/6dtjulN0cVJmuRYfxsbjM/Jj0YAKevufZ1ZrOtij67rdc/vreq0PfM T0VlYS9QBk1g6zfJU55F132zi0gzU8RhJZM9Mm9PHV1HDePdrQFk92vDE9EQpxHND0OLi9 gCb1k55TwM339wldmItyMG/KEbc7B+I= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-411-Yg6WqfBIPKCEOnDIurpaKg-1; Tue, 11 Mar 2025 07:31:54 -0400 X-MC-Unique: Yg6WqfBIPKCEOnDIurpaKg-1 X-Mimecast-MFC-AGG-ID: Yg6WqfBIPKCEOnDIurpaKg_1741692714 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id E7FAF180AF65 for ; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 9C6461800945 for ; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 31D9C21E61A5; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 30/61] qapi/parser: adjust info location for doc body section Date: Tue, 11 Mar 2025 12:31:06 +0100 Message-ID: <20250311113137.1277125-31-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow Instead of using the info object for the doc block as a whole (which always points to the very first line of the block), update the info pointer for each call to ensure_untagged_section when the existing section is otherwise empty. This way, Sphinx error information will match precisely to where the text actually starts. For example, this patch will move the info pointer for the "Hello!" untagged section ... > ## <-- from here ... > # Hello! <-- ... to here. > ## This doesn't seem to improve error reporting now. It will with the forthcoming QAPI doc transmogrifier. If I stick bad rST into qapi/block-core.json like this: > ## > # @SnapshotInfo: > # > +# rST syntax error: *ahh! > +# > # @id: unique shapshot id > # > # @name: user chosen name The existing code's error message will point to the beginning of the doc comment, which is less than helpful. The transmogrifier's message will point to the erroneous line, but to accomplish this, it needs this patch. Signed-off-by: John Snow Message-ID: <20250311034303.75779-33-jsnow@redhat.com> Reviewed-by: Markus Armbruster Signed-off-by: Markus Armbruster --- scripts/qapi/parser.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py index 64f0bb824a..97def9f0e4 100644 --- a/scripts/qapi/parser.py +++ b/scripts/qapi/parser.py @@ -686,7 +686,11 @@ def end(self) -> None: def ensure_untagged_section(self, info: QAPISourceInfo) -> None: if self.all_sections and not self.all_sections[-1].tag: # extend current section - self.all_sections[-1].text += '\n' + section = self.all_sections[-1] + if not section.text: + # Section is empty so far; update info to start *here*. + section.info = info + section.text += '\n' return # start new section section = self.Section(info) From patchwork Tue Mar 11 11:31:07 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011606 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 34BE9C35FF1 for ; Tue, 11 Mar 2025 11:50:42 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxsf-00087D-EH; Tue, 11 Mar 2025 07:34:41 -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 1trxqW-0003Ct-6U for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:28 -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 1trxq9-0006Vc-1P for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:25 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692717; 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=WGVrBYsiq7W1vAcIrspew+rSYJpEs9GSJRb6vtVbA0A=; b=Vcqko+uOzvBT2BXW4axzjEQWyNObswWfsT3OmjYjtcw3knselxT+hO4XDqPNP52T49T83b u/Vam9qtct9jJj3pmnMrZ2NAOGjDYAVqOFSjAUbbJD6pUDfd67kjW3lu0GfQvo1A1rKP5W GWJUW56JkkfF91yHnrYXch8BsWJOPL8= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-445-8yafwbsNNCe_tJBKpxPT3A-1; Tue, 11 Mar 2025 07:31:55 -0400 X-MC-Unique: 8yafwbsNNCe_tJBKpxPT3A-1 X-Mimecast-MFC-AGG-ID: 8yafwbsNNCe_tJBKpxPT3A_1741692715 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (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 mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 45339180AF70 for ; Tue, 11 Mar 2025 11:31:54 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 9CDD81828A95 for ; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 35BEB21E61AA; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 31/61] qapi: clean up encoding of section kinds Date: Tue, 11 Mar 2025 12:31:07 +0100 Message-ID: <20250311113137.1277125-32-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow We have several kinds of sections, and to tell them apart, we use Section attribute @tag and also the section object's Python type: type @tag untagged Section None @foo: ArgSection 'foo' Returns: Section 'Returns' Errors: Section 'Errors' Since: Section 'Since' TODO: Section 'TODO' Note: * @foo can be a member or a feature description, depending on context. * tag == 'Since' can be a Since: section or a member or feature description. If it's a Section, it's the former, and if it's an ArgSection, it's the latter. Clean this up as follows. Move the member or feature name to new ArgSection attribute @name, and replace @tag by enum @kind like this: type kind name untagged Section PLAIN @foo: ArgSection MEMBER 'foo' if member or argument ArgSection FEATURE 'foo' if feature Returns: Section RETURNS Errors: Section ERRORS Since: Section SINCE TODO: Section TODO The qapi-schema tests are updated to account for the new section names; "TODO" becomes "Todo" and `None` becomes "Plain" there. Signed-off-by: John Snow Message-ID: <20250311034303.75779-34-jsnow@redhat.com> Reviewed-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapidoc.py | 7 +-- scripts/qapi/parser.py | 97 ++++++++++++++++++++++++---------- tests/qapi-schema/doc-good.out | 10 ++-- tests/qapi-schema/test-qapi.py | 2 +- 4 files changed, 80 insertions(+), 36 deletions(-) diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py index 61997fd21a..d622398f1d 100644 --- a/docs/sphinx/qapidoc.py +++ b/docs/sphinx/qapidoc.py @@ -35,6 +35,7 @@ from docutils.statemachine import ViewList from qapi.error import QAPIError, QAPISemError from qapi.gen import QAPISchemaVisitor +from qapi.parser import QAPIDoc from qapi.schema import QAPISchema from sphinx import addnodes @@ -258,11 +259,11 @@ def _nodes_for_sections(self, doc): """Return list of doctree nodes for additional sections""" nodelist = [] for section in doc.sections: - if section.tag and section.tag == 'TODO': + if section.kind == QAPIDoc.Kind.TODO: # Hide TODO: sections continue - if not section.tag: + if section.kind == QAPIDoc.Kind.PLAIN: # Sphinx cannot handle sectionless titles; # Instead, just append the results to the prior section. container = nodes.container() @@ -270,7 +271,7 @@ def _nodes_for_sections(self, doc): nodelist += container.children continue - snode = self._make_section(section.tag) + snode = self._make_section(section.kind.name.title()) self._parse_text_into_node(dedent(section.text), snode) nodelist.append(snode) return nodelist diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py index 97def9f0e4..94d5322f8a 100644 --- a/scripts/qapi/parser.py +++ b/scripts/qapi/parser.py @@ -14,6 +14,7 @@ # This work is licensed under the terms of the GNU GPL, version 2. # See the COPYING file in the top-level directory. +import enum import os import re from typing import ( @@ -574,7 +575,10 @@ def get_doc(self) -> 'QAPIDoc': ) raise QAPIParseError(self, emsg) - doc.new_tagged_section(self.info, match.group(1)) + doc.new_tagged_section( + self.info, + QAPIDoc.Kind.from_string(match.group(1)) + ) text = line[match.end():] if text: doc.append_line(text) @@ -585,7 +589,7 @@ def get_doc(self) -> 'QAPIDoc': self, "unexpected '=' markup in definition documentation") else: - # tag-less paragraph + # plain paragraph doc.ensure_untagged_section(self.info) doc.append_line(line) line = self.get_doc_paragraph(doc) @@ -634,14 +638,33 @@ class QAPIDoc: Free-form documentation blocks consist only of a body section. """ + class Kind(enum.Enum): + PLAIN = 0 + MEMBER = 1 + FEATURE = 2 + RETURNS = 3 + ERRORS = 4 + SINCE = 5 + TODO = 6 + + @staticmethod + def from_string(kind: str) -> 'QAPIDoc.Kind': + return QAPIDoc.Kind[kind.upper()] + + def __str__(self) -> str: + return self.name.title() + class Section: # pylint: disable=too-few-public-methods - def __init__(self, info: QAPISourceInfo, - tag: Optional[str] = None): + def __init__( + self, + info: QAPISourceInfo, + kind: 'QAPIDoc.Kind', + ): # section source info, i.e. where it begins self.info = info - # section tag, if any ('Returns', '@name', ...) - self.tag = tag + # section kind + self.kind = kind # section text without tag self.text = '' @@ -649,8 +672,14 @@ def append_line(self, line: str) -> None: self.text += line + '\n' class ArgSection(Section): - def __init__(self, info: QAPISourceInfo, tag: str): - super().__init__(info, tag) + def __init__( + self, + info: QAPISourceInfo, + kind: 'QAPIDoc.Kind', + name: str + ): + super().__init__(info, kind) + self.name = name self.member: Optional['QAPISchemaMember'] = None def connect(self, member: 'QAPISchemaMember') -> None: @@ -662,7 +691,9 @@ def __init__(self, info: QAPISourceInfo, symbol: Optional[str] = None): # definition doc's symbol, None for free-form doc self.symbol: Optional[str] = symbol # the sections in textual order - self.all_sections: List[QAPIDoc.Section] = [QAPIDoc.Section(info)] + self.all_sections: List[QAPIDoc.Section] = [ + QAPIDoc.Section(info, QAPIDoc.Kind.PLAIN) + ] # the body section self.body: Optional[QAPIDoc.Section] = self.all_sections[0] # dicts mapping parameter/feature names to their description @@ -679,12 +710,14 @@ def __init__(self, info: QAPISourceInfo, symbol: Optional[str] = None): def end(self) -> None: for section in self.all_sections: section.text = section.text.strip('\n') - if section.tag is not None and section.text == '': + if section.kind != QAPIDoc.Kind.PLAIN and section.text == '': raise QAPISemError( - section.info, "text required after '%s:'" % section.tag) + section.info, "text required after '%s:'" % section.kind) def ensure_untagged_section(self, info: QAPISourceInfo) -> None: - if self.all_sections and not self.all_sections[-1].tag: + kind = QAPIDoc.Kind.PLAIN + + if self.all_sections and self.all_sections[-1].kind == kind: # extend current section section = self.all_sections[-1] if not section.text: @@ -692,46 +725,56 @@ def ensure_untagged_section(self, info: QAPISourceInfo) -> None: section.info = info section.text += '\n' return + # start new section - section = self.Section(info) + section = self.Section(info, kind) self.sections.append(section) self.all_sections.append(section) - def new_tagged_section(self, info: QAPISourceInfo, tag: str) -> None: - section = self.Section(info, tag) - if tag == 'Returns': + def new_tagged_section( + self, + info: QAPISourceInfo, + kind: 'QAPIDoc.Kind', + ) -> None: + section = self.Section(info, kind) + if kind == QAPIDoc.Kind.RETURNS: if self.returns: raise QAPISemError( - info, "duplicated '%s' section" % tag) + info, "duplicated '%s' section" % kind) self.returns = section - elif tag == 'Errors': + elif kind == QAPIDoc.Kind.ERRORS: if self.errors: raise QAPISemError( - info, "duplicated '%s' section" % tag) + info, "duplicated '%s' section" % kind) self.errors = section - elif tag == 'Since': + elif kind == QAPIDoc.Kind.SINCE: if self.since: raise QAPISemError( - info, "duplicated '%s' section" % tag) + info, "duplicated '%s' section" % kind) self.since = section self.sections.append(section) self.all_sections.append(section) - def _new_description(self, info: QAPISourceInfo, name: str, - desc: Dict[str, ArgSection]) -> None: + def _new_description( + self, + info: QAPISourceInfo, + name: str, + kind: 'QAPIDoc.Kind', + desc: Dict[str, ArgSection] + ) -> None: if not name: raise QAPISemError(info, "invalid parameter name") if name in desc: raise QAPISemError(info, "'%s' parameter name duplicated" % name) - section = self.ArgSection(info, '@' + name) + section = self.ArgSection(info, kind, name) self.all_sections.append(section) desc[name] = section def new_argument(self, info: QAPISourceInfo, name: str) -> None: - self._new_description(info, name, self.args) + self._new_description(info, name, QAPIDoc.Kind.MEMBER, self.args) def new_feature(self, info: QAPISourceInfo, name: str) -> None: - self._new_description(info, name, self.features) + self._new_description(info, name, QAPIDoc.Kind.FEATURE, self.features) def append_line(self, line: str) -> None: self.all_sections[-1].append_line(line) @@ -744,7 +787,7 @@ def connect_member(self, member: 'QAPISchemaMember') -> None: "%s '%s' lacks documentation" % (member.role, member.name)) self.args[member.name] = QAPIDoc.ArgSection( - self.info, '@' + member.name) + self.info, QAPIDoc.Kind.MEMBER, member.name) self.args[member.name].connect(member) def connect_feature(self, feature: 'QAPISchemaFeature') -> None: diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out index 0a9da3efde..5773f1dd6d 100644 --- a/tests/qapi-schema/doc-good.out +++ b/tests/qapi-schema/doc-good.out @@ -113,7 +113,7 @@ The _one_ {and only}, description on the same line Also _one_ {and only} feature=enum-member-feat a member feature - section=None + section=Plain @two is undocumented doc symbol=Base body= @@ -171,15 +171,15 @@ description starts on the same line a feature feature=cmd-feat2 another feature - section=None + section=Plain .. note:: @arg3 is undocumented section=Returns @Object section=Errors some - section=TODO + section=Todo frobnicate - section=None + section=Plain .. admonition:: Notes - Lorem ipsum dolor sit amet @@ -212,7 +212,7 @@ If you're bored enough to read this, go see a video of boxed cats a feature feature=cmd-feat2 another feature - section=None + section=Plain .. qmp-example:: -> "this example" diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py index 8fe951c880..4be930228c 100755 --- a/tests/qapi-schema/test-qapi.py +++ b/tests/qapi-schema/test-qapi.py @@ -122,7 +122,7 @@ def test_frontend(fname): for feat, section in doc.features.items(): print(' feature=%s\n%s' % (feat, section.text)) for section in doc.sections: - print(' section=%s\n%s' % (section.tag, section.text)) + print(' section=%s\n%s' % (section.kind, section.text)) def open_test_result(dir_name, file_name, update): From patchwork Tue Mar 11 11:31:08 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011560 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 C6C39C28B30 for ; Tue, 11 Mar 2025 11:36:44 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxsT-00074N-PB; Tue, 11 Mar 2025 07:34:31 -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 1trxqf-0003KN-FX for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32: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 1trxqA-0006Ya-W0 for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:37 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692725; 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=2jQz4bkCcDUhuUUoHnd6qBjJRWryEKXvfKz9VfbukNo=; b=V/XQ/iLLGTNdheriyYGHrrvVeGT6AWF3ip7le4flZ/Zk4yRREgQogVsWS5qYoNEsk8LeFp 6JjaC9pFuOQjRp404QEhgiHLfpLOGZushb0r9eqbQnZdhfRBkYmGAKl6DLeRiD+snSuNJ+ 5JyarZO3oFGHW7z2eoCYAyUTOSK5dAo= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-661-7BCNJjvANqOuIiWmnZpU-A-1; Tue, 11 Mar 2025 07:31:55 -0400 X-MC-Unique: 7BCNJjvANqOuIiWmnZpU-A-1 X-Mimecast-MFC-AGG-ID: 7BCNJjvANqOuIiWmnZpU-A_1741692715 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (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 mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 65CEF180AF72 for ; Tue, 11 Mar 2025 11:31:54 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id BB5F830001A2 for ; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 3965221E61AD; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 32/61] qapi/schema: add __repr__ to QAPIDoc.Section Date: Tue, 11 Mar 2025 12:31:08 +0100 Message-ID: <20250311113137.1277125-33-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow Makes debugging far more pleasant when you can just print(section) and get something reasonable to display. Signed-off-by: John Snow Message-ID: <20250311034303.75779-35-jsnow@redhat.com> Reviewed-by: Markus Armbruster Signed-off-by: Markus Armbruster --- scripts/qapi/parser.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py index 94d5322f8a..11c11bb09e 100644 --- a/scripts/qapi/parser.py +++ b/scripts/qapi/parser.py @@ -668,6 +668,9 @@ def __init__( # section text without tag self.text = '' + def __repr__(self) -> str: + return f"" + def append_line(self, line: str) -> None: self.text += line + '\n' From patchwork Tue Mar 11 11:31:09 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011567 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 47CBBC28B2E for ; Tue, 11 Mar 2025 11:37:24 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxsB-0005dQ-8p; Tue, 11 Mar 2025 07:34:11 -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 1trxqN-0003Bl-MK for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:20 -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 1trxq3-0006VE-OE for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:19 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692716; 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=X8mAzh3dVPM3dGcWghR6UuAv8vwUe7j41DMBEXsxS48=; b=ex+qQIo3sHeVxaZiYGqCYOwiTWpLCwm2xItdKA+WQrwB9PSDGpBJeL63+uWkTbxrAvG2Uf JDFNGGwiNb4eIbuhIQ6Ws7eNEJWCf3lh6UlonTQWMIVG+QXWVAplwVPcKensrUUGzwMhlK TbZomqPfNG0X0RaLAtVqzF0ADbb3lkU= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-122-7D31lJEJMyeumfYRHJWndw-1; Tue, 11 Mar 2025 07:31:55 -0400 X-MC-Unique: 7D31lJEJMyeumfYRHJWndw-1 X-Mimecast-MFC-AGG-ID: 7D31lJEJMyeumfYRHJWndw_1741692714 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (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 mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 47CB819560B5 for ; Tue, 11 Mar 2025 11:31:54 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id E444519560AB for ; Tue, 11 Mar 2025 11:31:53 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 3D57D21E64B3; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 33/61] docs/qapidoc: add transmogrifier stub Date: Tue, 11 Mar 2025 12:31:09 +0100 Message-ID: <20250311113137.1277125-34-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 Received-SPF: pass client-ip=170.10.133.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_PASS=-0.001, T_SPF_HELO_TEMPERROR=0.01 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: John Snow This commit adds a stubbed option to the qapi-doc directive that opts-in to the new rST generator; the implementation of which will follow in subsequent commits. Once all QAPI documents have been converted, this option and the old qapidoc implementation can be dropped. Note that moving code outside of the try...except block has no impact because the code moved outside of that block does not ever raise a QAPIError. Signed-off-by: John Snow Message-ID: <20250311034303.75779-36-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapidoc.py | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py index d622398f1d..dc72f3fd3f 100644 --- a/docs/sphinx/qapidoc.py +++ b/docs/sphinx/qapidoc.py @@ -452,9 +452,9 @@ def _parse_text_into_node(self, doctext, node): rstlist.append("", self._cur_doc.info.fname, self._cur_doc.info.line) self._sphinx_directive.do_parse(rstlist, node) - def get_document_nodes(self): - """Return the list of docutils nodes which make up the document""" - return self._top_node.children + def get_document_node(self): + """Return the root docutils node which makes up the document""" + return self._top_node # Turn the black formatter on for the rest of the file. @@ -503,7 +503,10 @@ class QAPIDocDirective(NestedDirective): required_argument = 1 optional_arguments = 1 - option_spec = {"qapifile": directives.unchanged_required} + option_spec = { + "qapifile": directives.unchanged_required, + "transmogrify": directives.flag, + } has_content = False def new_serialno(self): @@ -511,10 +514,24 @@ def new_serialno(self): env = self.state.document.settings.env return "qapidoc-%d" % env.new_serialno("qapidoc") + def transmogrify(self, schema) -> nodes.Element: + raise NotImplementedError + + def legacy(self, schema) -> nodes.Element: + vis = QAPISchemaGenRSTVisitor(self) + vis.visit_begin(schema) + for doc in schema.docs: + if doc.symbol: + vis.symbol(doc, schema.lookup_entity(doc.symbol)) + else: + vis.freeform(doc) + return vis.get_document_node() + def run(self): env = self.state.document.settings.env qapifile = env.config.qapidoc_srctree + "/" + self.arguments[0] qapidir = os.path.dirname(qapifile) + transmogrify = "transmogrify" in self.options try: schema = QAPISchema(qapifile) @@ -522,20 +539,18 @@ def run(self): # First tell Sphinx about all the schema files that the # output documentation depends on (including 'qapifile' itself) schema.visit(QAPISchemaGenDepVisitor(env, qapidir)) - - vis = QAPISchemaGenRSTVisitor(self) - vis.visit_begin(schema) - for doc in schema.docs: - if doc.symbol: - vis.symbol(doc, schema.lookup_entity(doc.symbol)) - else: - vis.freeform(doc) - return vis.get_document_nodes() except QAPIError as err: # Launder QAPI parse errors into Sphinx extension errors # so they are displayed nicely to the user raise ExtensionError(str(err)) from err + if transmogrify: + contentnode = self.transmogrify(schema) + else: + contentnode = self.legacy(schema) + + return contentnode.children + class QMPExample(CodeBlock, NestedDirective): """ From patchwork Tue Mar 11 11:31:10 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011585 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 4CA60C282EC for ; Tue, 11 Mar 2025 11:41:53 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxsw-0000bq-03; Tue, 11 Mar 2025 07:34:58 -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 1trxr7-0003Tt-KA for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:33:06 -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 1trxqC-0006X1-21 for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:33:05 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692720; 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=RRzfkXjRrghMzDuY8ig+T77LLrWgb0OAQdMJd3QshR0=; b=hgxgf1cgeuE6IpeMn+AUOa+YV2gVE980TBtgpWVc+DvTvn0cCx0at54vNQi5lwMTchcXsT 22cqBAybY9CFfb5PUMOZrDbHswr2kV9H+P6Ut8b0cpYVbUy2MdXkKzVt/z7AEtO4XBYWr9 DV0SdCDJ44mbKFuyvNrB/WjrA5anG9Y= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-459-NOuE_msiPjGeZwHwYuibwA-1; Tue, 11 Mar 2025 07:31:59 -0400 X-MC-Unique: NOuE_msiPjGeZwHwYuibwA-1 X-Mimecast-MFC-AGG-ID: NOuE_msiPjGeZwHwYuibwA_1741692718 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (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 mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 368A9195609E for ; Tue, 11 Mar 2025 11:31:58 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 3879118001F6 for ; Tue, 11 Mar 2025 11:31:57 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 41AAF21E61B3; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 34/61] docs/qapidoc: split old implementation into qapidoc_legacy.py Date: Tue, 11 Mar 2025 12:31:10 +0100 Message-ID: <20250311113137.1277125-35-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, 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_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, T_SPF_TEMPERROR=0.01 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: John Snow This is being done primarily to be able to type check and delint the new implementation without needing to worry about fixing up the old implementation. I'm adding the new implementation into the existing file instead of into a new file so that when the dust settles, qapidoc.py will contain the full history of development on this generative module. This patch *should* be pure motion, give or take the import statements. Signed-off-by: John Snow Message-ID: <20250311034303.75779-37-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapidoc.py | 420 +------------------------------- docs/sphinx/qapidoc_legacy.py | 439 ++++++++++++++++++++++++++++++++++ 2 files changed, 441 insertions(+), 418 deletions(-) create mode 100644 docs/sphinx/qapidoc_legacy.py diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py index dc72f3fd3f..f4abf42e7b 100644 --- a/docs/sphinx/qapidoc.py +++ b/docs/sphinx/qapidoc.py @@ -25,19 +25,16 @@ """ import os -import re import sys -import textwrap from typing import List from docutils import nodes from docutils.parsers.rst import Directive, directives -from docutils.statemachine import ViewList -from qapi.error import QAPIError, QAPISemError +from qapi.error import QAPIError from qapi.gen import QAPISchemaVisitor -from qapi.parser import QAPIDoc from qapi.schema import QAPISchema +from qapidoc_legacy import QAPISchemaGenRSTVisitor from sphinx import addnodes from sphinx.directives.code import CodeBlock from sphinx.errors import ExtensionError @@ -48,419 +45,6 @@ __version__ = "1.0" -def dedent(text: str) -> str: - # Adjust indentation to make description text parse as paragraph. - - lines = text.splitlines(True) - if re.match(r"\s+", lines[0]): - # First line is indented; description started on the line after - # the name. dedent the whole block. - return textwrap.dedent(text) - - # Descr started on same line. Dedent line 2+. - return lines[0] + textwrap.dedent("".join(lines[1:])) - - -# Disable black auto-formatter until re-enabled: -# fmt: off - - -class QAPISchemaGenRSTVisitor(QAPISchemaVisitor): - """A QAPI schema visitor which generates docutils/Sphinx nodes - - This class builds up a tree of docutils/Sphinx nodes corresponding - to documentation for the various QAPI objects. To use it, first - create a QAPISchemaGenRSTVisitor object, and call its - visit_begin() method. Then you can call one of the two methods - 'freeform' (to add documentation for a freeform documentation - chunk) or 'symbol' (to add documentation for a QAPI symbol). These - will cause the visitor to build up the tree of document - nodes. Once you've added all the documentation via 'freeform' and - 'symbol' method calls, you can call 'get_document_nodes' to get - the final list of document nodes (in a form suitable for returning - from a Sphinx directive's 'run' method). - """ - def __init__(self, sphinx_directive): - self._cur_doc = None - self._sphinx_directive = sphinx_directive - self._top_node = nodes.section() - self._active_headings = [self._top_node] - - def _make_dlitem(self, term, defn): - """Return a dlitem node with the specified term and definition. - - term should be a list of Text and literal nodes. - defn should be one of: - - a string, which will be handed to _parse_text_into_node - - a list of Text and literal nodes, which will be put into - a paragraph node - """ - dlitem = nodes.definition_list_item() - dlterm = nodes.term('', '', *term) - dlitem += dlterm - if defn: - dldef = nodes.definition() - if isinstance(defn, list): - dldef += nodes.paragraph('', '', *defn) - else: - self._parse_text_into_node(defn, dldef) - dlitem += dldef - return dlitem - - def _make_section(self, title): - """Return a section node with optional title""" - section = nodes.section(ids=[self._sphinx_directive.new_serialno()]) - if title: - section += nodes.title(title, title) - return section - - def _nodes_for_ifcond(self, ifcond, with_if=True): - """Return list of Text, literal nodes for the ifcond - - Return a list which gives text like ' (If: condition)'. - If with_if is False, we don't return the "(If: " and ")". - """ - - doc = ifcond.docgen() - if not doc: - return [] - doc = nodes.literal('', doc) - if not with_if: - return [doc] - - nodelist = [nodes.Text(' ('), nodes.strong('', 'If: ')] - nodelist.append(doc) - nodelist.append(nodes.Text(')')) - return nodelist - - def _nodes_for_one_member(self, member): - """Return list of Text, literal nodes for this member - - Return a list of doctree nodes which give text like - 'name: type (optional) (If: ...)' suitable for use as the - 'term' part of a definition list item. - """ - term = [nodes.literal('', member.name)] - if member.type.doc_type(): - term.append(nodes.Text(': ')) - term.append(nodes.literal('', member.type.doc_type())) - if member.optional: - term.append(nodes.Text(' (optional)')) - if member.ifcond.is_present(): - term.extend(self._nodes_for_ifcond(member.ifcond)) - return term - - def _nodes_for_variant_when(self, branches, variant): - """Return list of Text, literal nodes for variant 'when' clause - - Return a list of doctree nodes which give text like - 'when tagname is variant (If: ...)' suitable for use in - the 'branches' part of a definition list. - """ - term = [nodes.Text(' when '), - nodes.literal('', branches.tag_member.name), - nodes.Text(' is '), - nodes.literal('', '"%s"' % variant.name)] - if variant.ifcond.is_present(): - term.extend(self._nodes_for_ifcond(variant.ifcond)) - return term - - def _nodes_for_members(self, doc, what, base=None, branches=None): - """Return list of doctree nodes for the table of members""" - dlnode = nodes.definition_list() - for section in doc.args.values(): - term = self._nodes_for_one_member(section.member) - # TODO drop fallbacks when undocumented members are outlawed - if section.text: - defn = dedent(section.text) - else: - defn = [nodes.Text('Not documented')] - - dlnode += self._make_dlitem(term, defn) - - if base: - dlnode += self._make_dlitem([nodes.Text('The members of '), - nodes.literal('', base.doc_type())], - None) - - if branches: - for v in branches.variants: - if v.type.name == 'q_empty': - continue - assert not v.type.is_implicit() - term = [nodes.Text('The members of '), - nodes.literal('', v.type.doc_type())] - term.extend(self._nodes_for_variant_when(branches, v)) - dlnode += self._make_dlitem(term, None) - - if not dlnode.children: - return [] - - section = self._make_section(what) - section += dlnode - return [section] - - def _nodes_for_enum_values(self, doc): - """Return list of doctree nodes for the table of enum values""" - seen_item = False - dlnode = nodes.definition_list() - for section in doc.args.values(): - termtext = [nodes.literal('', section.member.name)] - if section.member.ifcond.is_present(): - termtext.extend(self._nodes_for_ifcond(section.member.ifcond)) - # TODO drop fallbacks when undocumented members are outlawed - if section.text: - defn = dedent(section.text) - else: - defn = [nodes.Text('Not documented')] - - dlnode += self._make_dlitem(termtext, defn) - seen_item = True - - if not seen_item: - return [] - - section = self._make_section('Values') - section += dlnode - return [section] - - def _nodes_for_arguments(self, doc, arg_type): - """Return list of doctree nodes for the arguments section""" - if arg_type and not arg_type.is_implicit(): - assert not doc.args - section = self._make_section('Arguments') - dlnode = nodes.definition_list() - dlnode += self._make_dlitem( - [nodes.Text('The members of '), - nodes.literal('', arg_type.name)], - None) - section += dlnode - return [section] - - return self._nodes_for_members(doc, 'Arguments') - - def _nodes_for_features(self, doc): - """Return list of doctree nodes for the table of features""" - seen_item = False - dlnode = nodes.definition_list() - for section in doc.features.values(): - dlnode += self._make_dlitem( - [nodes.literal('', section.member.name)], dedent(section.text)) - seen_item = True - - if not seen_item: - return [] - - section = self._make_section('Features') - section += dlnode - return [section] - - def _nodes_for_sections(self, doc): - """Return list of doctree nodes for additional sections""" - nodelist = [] - for section in doc.sections: - if section.kind == QAPIDoc.Kind.TODO: - # Hide TODO: sections - continue - - if section.kind == QAPIDoc.Kind.PLAIN: - # Sphinx cannot handle sectionless titles; - # Instead, just append the results to the prior section. - container = nodes.container() - self._parse_text_into_node(section.text, container) - nodelist += container.children - continue - - snode = self._make_section(section.kind.name.title()) - self._parse_text_into_node(dedent(section.text), snode) - nodelist.append(snode) - return nodelist - - def _nodes_for_if_section(self, ifcond): - """Return list of doctree nodes for the "If" section""" - nodelist = [] - if ifcond.is_present(): - snode = self._make_section('If') - snode += nodes.paragraph( - '', '', *self._nodes_for_ifcond(ifcond, with_if=False) - ) - nodelist.append(snode) - return nodelist - - def _add_doc(self, typ, sections): - """Add documentation for a command/object/enum... - - We assume we're documenting the thing defined in self._cur_doc. - typ is the type of thing being added ("Command", "Object", etc) - - sections is a list of nodes for sections to add to the definition. - """ - - doc = self._cur_doc - snode = nodes.section(ids=[self._sphinx_directive.new_serialno()]) - snode += nodes.title('', '', *[nodes.literal(doc.symbol, doc.symbol), - nodes.Text(' (' + typ + ')')]) - self._parse_text_into_node(doc.body.text, snode) - for s in sections: - if s is not None: - snode += s - self._add_node_to_current_heading(snode) - - def visit_enum_type(self, name, info, ifcond, features, members, prefix): - doc = self._cur_doc - self._add_doc('Enum', - self._nodes_for_enum_values(doc) - + self._nodes_for_features(doc) - + self._nodes_for_sections(doc) - + self._nodes_for_if_section(ifcond)) - - def visit_object_type(self, name, info, ifcond, features, - base, members, branches): - doc = self._cur_doc - if base and base.is_implicit(): - base = None - self._add_doc('Object', - self._nodes_for_members(doc, 'Members', base, branches) - + self._nodes_for_features(doc) - + self._nodes_for_sections(doc) - + self._nodes_for_if_section(ifcond)) - - def visit_alternate_type(self, name, info, ifcond, features, - alternatives): - doc = self._cur_doc - self._add_doc('Alternate', - self._nodes_for_members(doc, 'Members') - + self._nodes_for_features(doc) - + self._nodes_for_sections(doc) - + self._nodes_for_if_section(ifcond)) - - def visit_command(self, name, info, ifcond, features, arg_type, - ret_type, gen, success_response, boxed, allow_oob, - allow_preconfig, coroutine): - doc = self._cur_doc - self._add_doc('Command', - self._nodes_for_arguments(doc, arg_type) - + self._nodes_for_features(doc) - + self._nodes_for_sections(doc) - + self._nodes_for_if_section(ifcond)) - - def visit_event(self, name, info, ifcond, features, arg_type, boxed): - doc = self._cur_doc - self._add_doc('Event', - self._nodes_for_arguments(doc, arg_type) - + self._nodes_for_features(doc) - + self._nodes_for_sections(doc) - + self._nodes_for_if_section(ifcond)) - - def symbol(self, doc, entity): - """Add documentation for one symbol to the document tree - - This is the main entry point which causes us to add documentation - nodes for a symbol (which could be a 'command', 'object', 'event', - etc). We do this by calling 'visit' on the schema entity, which - will then call back into one of our visit_* methods, depending - on what kind of thing this symbol is. - """ - self._cur_doc = doc - entity.visit(self) - self._cur_doc = None - - def _start_new_heading(self, heading, level): - """Start a new heading at the specified heading level - - Create a new section whose title is 'heading' and which is placed - in the docutils node tree as a child of the most recent level-1 - heading. Subsequent document sections (commands, freeform doc chunks, - etc) will be placed as children of this new heading section. - """ - if len(self._active_headings) < level: - raise QAPISemError(self._cur_doc.info, - 'Level %d subheading found outside a ' - 'level %d heading' - % (level, level - 1)) - snode = self._make_section(heading) - self._active_headings[level - 1] += snode - self._active_headings = self._active_headings[:level] - self._active_headings.append(snode) - return snode - - def _add_node_to_current_heading(self, node): - """Add the node to whatever the current active heading is""" - self._active_headings[-1] += node - - def freeform(self, doc): - """Add a piece of 'freeform' documentation to the document tree - - A 'freeform' document chunk doesn't relate to any particular - symbol (for instance, it could be an introduction). - - If the freeform document starts with a line of the form - '= Heading text', this is a section or subsection heading, with - the heading level indicated by the number of '=' signs. - """ - - # QAPIDoc documentation says free-form documentation blocks - # must have only a body section, nothing else. - assert not doc.sections - assert not doc.args - assert not doc.features - self._cur_doc = doc - - text = doc.body.text - if re.match(r'=+ ', text): - # Section/subsection heading (if present, will always be - # the first line of the block) - (heading, _, text) = text.partition('\n') - (leader, _, heading) = heading.partition(' ') - node = self._start_new_heading(heading, len(leader)) - if text == '': - return - else: - node = nodes.container() - - self._parse_text_into_node(text, node) - self._cur_doc = None - - def _parse_text_into_node(self, doctext, node): - """Parse a chunk of QAPI-doc-format text into the node - - The doc comment can contain most inline rST markup, including - bulleted and enumerated lists. - As an extra permitted piece of markup, @var will be turned - into ``var``. - """ - - # Handle the "@var means ``var`` case - doctext = re.sub(r'@([\w-]+)', r'``\1``', doctext) - - rstlist = ViewList() - for line in doctext.splitlines(): - # The reported line number will always be that of the start line - # of the doc comment, rather than the actual location of the error. - # Being more precise would require overhaul of the QAPIDoc class - # to track lines more exactly within all the sub-parts of the doc - # comment, as well as counting lines here. - rstlist.append(line, self._cur_doc.info.fname, - self._cur_doc.info.line) - # Append a blank line -- in some cases rST syntax errors get - # attributed to the line after one with actual text, and if there - # isn't anything in the ViewList corresponding to that then Sphinx - # 1.6's AutodocReporter will then misidentify the source/line location - # in the error message (usually attributing it to the top-level - # .rst file rather than the offending .json file). The extra blank - # line won't affect the rendered output. - rstlist.append("", self._cur_doc.info.fname, self._cur_doc.info.line) - self._sphinx_directive.do_parse(rstlist, node) - - def get_document_node(self): - """Return the root docutils node which makes up the document""" - return self._top_node - - -# Turn the black formatter on for the rest of the file. -# fmt: on - - class QAPISchemaGenDepVisitor(QAPISchemaVisitor): """A QAPI schema visitor which adds Sphinx dependencies each module diff --git a/docs/sphinx/qapidoc_legacy.py b/docs/sphinx/qapidoc_legacy.py new file mode 100644 index 0000000000..679f38356b --- /dev/null +++ b/docs/sphinx/qapidoc_legacy.py @@ -0,0 +1,439 @@ +# coding=utf-8 +# +# QEMU qapidoc QAPI file parsing extension +# +# Copyright (c) 2020 Linaro +# +# This work is licensed under the terms of the GNU GPLv2 or later. +# See the COPYING file in the top-level directory. + +""" +qapidoc is a Sphinx extension that implements the qapi-doc directive + +The purpose of this extension is to read the documentation comments +in QAPI schema files, and insert them all into the current document. + +It implements one new rST directive, "qapi-doc::". +Each qapi-doc:: directive takes one argument, which is the +pathname of the schema file to process, relative to the source tree. + +The docs/conf.py file must set the qapidoc_srctree config value to +the root of the QEMU source tree. + +The Sphinx documentation on writing extensions is at: +https://www.sphinx-doc.org/en/master/development/index.html +""" + +import re +import textwrap + +from docutils import nodes +from docutils.statemachine import ViewList +from qapi.error import QAPISemError +from qapi.gen import QAPISchemaVisitor +from qapi.parser import QAPIDoc + + +def dedent(text: str) -> str: + # Adjust indentation to make description text parse as paragraph. + + lines = text.splitlines(True) + if re.match(r"\s+", lines[0]): + # First line is indented; description started on the line after + # the name. dedent the whole block. + return textwrap.dedent(text) + + # Descr started on same line. Dedent line 2+. + return lines[0] + textwrap.dedent("".join(lines[1:])) + + +class QAPISchemaGenRSTVisitor(QAPISchemaVisitor): + """A QAPI schema visitor which generates docutils/Sphinx nodes + + This class builds up a tree of docutils/Sphinx nodes corresponding + to documentation for the various QAPI objects. To use it, first + create a QAPISchemaGenRSTVisitor object, and call its + visit_begin() method. Then you can call one of the two methods + 'freeform' (to add documentation for a freeform documentation + chunk) or 'symbol' (to add documentation for a QAPI symbol). These + will cause the visitor to build up the tree of document + nodes. Once you've added all the documentation via 'freeform' and + 'symbol' method calls, you can call 'get_document_nodes' to get + the final list of document nodes (in a form suitable for returning + from a Sphinx directive's 'run' method). + """ + def __init__(self, sphinx_directive): + self._cur_doc = None + self._sphinx_directive = sphinx_directive + self._top_node = nodes.section() + self._active_headings = [self._top_node] + + def _make_dlitem(self, term, defn): + """Return a dlitem node with the specified term and definition. + + term should be a list of Text and literal nodes. + defn should be one of: + - a string, which will be handed to _parse_text_into_node + - a list of Text and literal nodes, which will be put into + a paragraph node + """ + dlitem = nodes.definition_list_item() + dlterm = nodes.term('', '', *term) + dlitem += dlterm + if defn: + dldef = nodes.definition() + if isinstance(defn, list): + dldef += nodes.paragraph('', '', *defn) + else: + self._parse_text_into_node(defn, dldef) + dlitem += dldef + return dlitem + + def _make_section(self, title): + """Return a section node with optional title""" + section = nodes.section(ids=[self._sphinx_directive.new_serialno()]) + if title: + section += nodes.title(title, title) + return section + + def _nodes_for_ifcond(self, ifcond, with_if=True): + """Return list of Text, literal nodes for the ifcond + + Return a list which gives text like ' (If: condition)'. + If with_if is False, we don't return the "(If: " and ")". + """ + + doc = ifcond.docgen() + if not doc: + return [] + doc = nodes.literal('', doc) + if not with_if: + return [doc] + + nodelist = [nodes.Text(' ('), nodes.strong('', 'If: ')] + nodelist.append(doc) + nodelist.append(nodes.Text(')')) + return nodelist + + def _nodes_for_one_member(self, member): + """Return list of Text, literal nodes for this member + + Return a list of doctree nodes which give text like + 'name: type (optional) (If: ...)' suitable for use as the + 'term' part of a definition list item. + """ + term = [nodes.literal('', member.name)] + if member.type.doc_type(): + term.append(nodes.Text(': ')) + term.append(nodes.literal('', member.type.doc_type())) + if member.optional: + term.append(nodes.Text(' (optional)')) + if member.ifcond.is_present(): + term.extend(self._nodes_for_ifcond(member.ifcond)) + return term + + def _nodes_for_variant_when(self, branches, variant): + """Return list of Text, literal nodes for variant 'when' clause + + Return a list of doctree nodes which give text like + 'when tagname is variant (If: ...)' suitable for use in + the 'branches' part of a definition list. + """ + term = [nodes.Text(' when '), + nodes.literal('', branches.tag_member.name), + nodes.Text(' is '), + nodes.literal('', '"%s"' % variant.name)] + if variant.ifcond.is_present(): + term.extend(self._nodes_for_ifcond(variant.ifcond)) + return term + + def _nodes_for_members(self, doc, what, base=None, branches=None): + """Return list of doctree nodes for the table of members""" + dlnode = nodes.definition_list() + for section in doc.args.values(): + term = self._nodes_for_one_member(section.member) + # TODO drop fallbacks when undocumented members are outlawed + if section.text: + defn = dedent(section.text) + else: + defn = [nodes.Text('Not documented')] + + dlnode += self._make_dlitem(term, defn) + + if base: + dlnode += self._make_dlitem([nodes.Text('The members of '), + nodes.literal('', base.doc_type())], + None) + + if branches: + for v in branches.variants: + if v.type.name == 'q_empty': + continue + assert not v.type.is_implicit() + term = [nodes.Text('The members of '), + nodes.literal('', v.type.doc_type())] + term.extend(self._nodes_for_variant_when(branches, v)) + dlnode += self._make_dlitem(term, None) + + if not dlnode.children: + return [] + + section = self._make_section(what) + section += dlnode + return [section] + + def _nodes_for_enum_values(self, doc): + """Return list of doctree nodes for the table of enum values""" + seen_item = False + dlnode = nodes.definition_list() + for section in doc.args.values(): + termtext = [nodes.literal('', section.member.name)] + if section.member.ifcond.is_present(): + termtext.extend(self._nodes_for_ifcond(section.member.ifcond)) + # TODO drop fallbacks when undocumented members are outlawed + if section.text: + defn = dedent(section.text) + else: + defn = [nodes.Text('Not documented')] + + dlnode += self._make_dlitem(termtext, defn) + seen_item = True + + if not seen_item: + return [] + + section = self._make_section('Values') + section += dlnode + return [section] + + def _nodes_for_arguments(self, doc, arg_type): + """Return list of doctree nodes for the arguments section""" + if arg_type and not arg_type.is_implicit(): + assert not doc.args + section = self._make_section('Arguments') + dlnode = nodes.definition_list() + dlnode += self._make_dlitem( + [nodes.Text('The members of '), + nodes.literal('', arg_type.name)], + None) + section += dlnode + return [section] + + return self._nodes_for_members(doc, 'Arguments') + + def _nodes_for_features(self, doc): + """Return list of doctree nodes for the table of features""" + seen_item = False + dlnode = nodes.definition_list() + for section in doc.features.values(): + dlnode += self._make_dlitem( + [nodes.literal('', section.member.name)], dedent(section.text)) + seen_item = True + + if not seen_item: + return [] + + section = self._make_section('Features') + section += dlnode + return [section] + + def _nodes_for_sections(self, doc): + """Return list of doctree nodes for additional sections""" + nodelist = [] + for section in doc.sections: + if section.kind == QAPIDoc.Kind.TODO: + # Hide TODO: sections + continue + + if section.kind == QAPIDoc.Kind.PLAIN: + # Sphinx cannot handle sectionless titles; + # Instead, just append the results to the prior section. + container = nodes.container() + self._parse_text_into_node(section.text, container) + nodelist += container.children + continue + + snode = self._make_section(section.kind.name.title()) + self._parse_text_into_node(dedent(section.text), snode) + nodelist.append(snode) + return nodelist + + def _nodes_for_if_section(self, ifcond): + """Return list of doctree nodes for the "If" section""" + nodelist = [] + if ifcond.is_present(): + snode = self._make_section('If') + snode += nodes.paragraph( + '', '', *self._nodes_for_ifcond(ifcond, with_if=False) + ) + nodelist.append(snode) + return nodelist + + def _add_doc(self, typ, sections): + """Add documentation for a command/object/enum... + + We assume we're documenting the thing defined in self._cur_doc. + typ is the type of thing being added ("Command", "Object", etc) + + sections is a list of nodes for sections to add to the definition. + """ + + doc = self._cur_doc + snode = nodes.section(ids=[self._sphinx_directive.new_serialno()]) + snode += nodes.title('', '', *[nodes.literal(doc.symbol, doc.symbol), + nodes.Text(' (' + typ + ')')]) + self._parse_text_into_node(doc.body.text, snode) + for s in sections: + if s is not None: + snode += s + self._add_node_to_current_heading(snode) + + def visit_enum_type(self, name, info, ifcond, features, members, prefix): + doc = self._cur_doc + self._add_doc('Enum', + self._nodes_for_enum_values(doc) + + self._nodes_for_features(doc) + + self._nodes_for_sections(doc) + + self._nodes_for_if_section(ifcond)) + + def visit_object_type(self, name, info, ifcond, features, + base, members, branches): + doc = self._cur_doc + if base and base.is_implicit(): + base = None + self._add_doc('Object', + self._nodes_for_members(doc, 'Members', base, branches) + + self._nodes_for_features(doc) + + self._nodes_for_sections(doc) + + self._nodes_for_if_section(ifcond)) + + def visit_alternate_type(self, name, info, ifcond, features, + alternatives): + doc = self._cur_doc + self._add_doc('Alternate', + self._nodes_for_members(doc, 'Members') + + self._nodes_for_features(doc) + + self._nodes_for_sections(doc) + + self._nodes_for_if_section(ifcond)) + + def visit_command(self, name, info, ifcond, features, arg_type, + ret_type, gen, success_response, boxed, allow_oob, + allow_preconfig, coroutine): + doc = self._cur_doc + self._add_doc('Command', + self._nodes_for_arguments(doc, arg_type) + + self._nodes_for_features(doc) + + self._nodes_for_sections(doc) + + self._nodes_for_if_section(ifcond)) + + def visit_event(self, name, info, ifcond, features, arg_type, boxed): + doc = self._cur_doc + self._add_doc('Event', + self._nodes_for_arguments(doc, arg_type) + + self._nodes_for_features(doc) + + self._nodes_for_sections(doc) + + self._nodes_for_if_section(ifcond)) + + def symbol(self, doc, entity): + """Add documentation for one symbol to the document tree + + This is the main entry point which causes us to add documentation + nodes for a symbol (which could be a 'command', 'object', 'event', + etc). We do this by calling 'visit' on the schema entity, which + will then call back into one of our visit_* methods, depending + on what kind of thing this symbol is. + """ + self._cur_doc = doc + entity.visit(self) + self._cur_doc = None + + def _start_new_heading(self, heading, level): + """Start a new heading at the specified heading level + + Create a new section whose title is 'heading' and which is placed + in the docutils node tree as a child of the most recent level-1 + heading. Subsequent document sections (commands, freeform doc chunks, + etc) will be placed as children of this new heading section. + """ + if len(self._active_headings) < level: + raise QAPISemError(self._cur_doc.info, + 'Level %d subheading found outside a ' + 'level %d heading' + % (level, level - 1)) + snode = self._make_section(heading) + self._active_headings[level - 1] += snode + self._active_headings = self._active_headings[:level] + self._active_headings.append(snode) + return snode + + def _add_node_to_current_heading(self, node): + """Add the node to whatever the current active heading is""" + self._active_headings[-1] += node + + def freeform(self, doc): + """Add a piece of 'freeform' documentation to the document tree + + A 'freeform' document chunk doesn't relate to any particular + symbol (for instance, it could be an introduction). + + If the freeform document starts with a line of the form + '= Heading text', this is a section or subsection heading, with + the heading level indicated by the number of '=' signs. + """ + + # QAPIDoc documentation says free-form documentation blocks + # must have only a body section, nothing else. + assert not doc.sections + assert not doc.args + assert not doc.features + self._cur_doc = doc + + text = doc.body.text + if re.match(r'=+ ', text): + # Section/subsection heading (if present, will always be + # the first line of the block) + (heading, _, text) = text.partition('\n') + (leader, _, heading) = heading.partition(' ') + node = self._start_new_heading(heading, len(leader)) + if text == '': + return + else: + node = nodes.container() + + self._parse_text_into_node(text, node) + self._cur_doc = None + + def _parse_text_into_node(self, doctext, node): + """Parse a chunk of QAPI-doc-format text into the node + + The doc comment can contain most inline rST markup, including + bulleted and enumerated lists. + As an extra permitted piece of markup, @var will be turned + into ``var``. + """ + + # Handle the "@var means ``var`` case + doctext = re.sub(r'@([\w-]+)', r'``\1``', doctext) + + rstlist = ViewList() + for line in doctext.splitlines(): + # The reported line number will always be that of the start line + # of the doc comment, rather than the actual location of the error. + # Being more precise would require overhaul of the QAPIDoc class + # to track lines more exactly within all the sub-parts of the doc + # comment, as well as counting lines here. + rstlist.append(line, self._cur_doc.info.fname, + self._cur_doc.info.line) + # Append a blank line -- in some cases rST syntax errors get + # attributed to the line after one with actual text, and if there + # isn't anything in the ViewList corresponding to that then Sphinx + # 1.6's AutodocReporter will then misidentify the source/line location + # in the error message (usually attributing it to the top-level + # .rst file rather than the offending .json file). The extra blank + # line won't affect the rendered output. + rstlist.append("", self._cur_doc.info.fname, self._cur_doc.info.line) + self._sphinx_directive.do_parse(rstlist, node) + + def get_document_node(self): + """Return the root docutils node which makes up the document""" + return self._top_node From patchwork Tue Mar 11 11:31:11 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011544 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 3494AC28B2E for ; Tue, 11 Mar 2025 11:35:02 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxrB-0003Yz-6C; Tue, 11 Mar 2025 07:33:09 -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 1trxqX-0003E5-Or for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32: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 1trxq9-0006WW-O6 for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:29 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692720; 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=yn3k+UUuSXjboRQTRf7pSKVVJS5tuuCfkZtnyiVis7o=; b=I0RixdaDvGTUjKZxKcAnotz9SPTM4rVwKlCg15WpHAjsJvPK5yanM9Rl/mvRdCEakMmP4H o5ufgKDD7Q1rybrdcDZoAx4GoGW9xO5Dir2dNSbtHZWom6EKZCRRTLQvC33oeb+l3yF6ZA a0PqUWy8C7IoAUWBhY+UdZA993qg9mg= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-455-ibzLsF0iPPKJR4URh4h_gA-1; Tue, 11 Mar 2025 07:31:58 -0400 X-MC-Unique: ibzLsF0iPPKJR4URh4h_gA-1 X-Mimecast-MFC-AGG-ID: ibzLsF0iPPKJR4URh4h_gA_1741692718 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id E4C2E18001F6 for ; Tue, 11 Mar 2025 11:31:57 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 38065180094A for ; Tue, 11 Mar 2025 11:31:57 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 457D421E61B5; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 35/61] docs/qapidoc: Fix static typing on qapidoc.py Date: Tue, 11 Mar 2025 12:31:11 +0100 Message-ID: <20250311113137.1277125-36-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow Now that the legacy code is factored out, fix up the typing on the remaining code in qapidoc.py. Add a type ignore to qapi_legacy.py to prevent the errors there from bleeding out into qapidoc.py. Signed-off-by: John Snow Message-ID: <20250311034303.75779-38-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapidoc.py | 40 ++++++++++++++++++++++------------- docs/sphinx/qapidoc_legacy.py | 1 + 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py index f4abf42e7b..5246832b68 100644 --- a/docs/sphinx/qapidoc.py +++ b/docs/sphinx/qapidoc.py @@ -24,17 +24,18 @@ https://www.sphinx-doc.org/en/master/development/index.html """ +from __future__ import annotations + import os import sys -from typing import List +from typing import TYPE_CHECKING from docutils import nodes from docutils.parsers.rst import Directive, directives from qapi.error import QAPIError -from qapi.gen import QAPISchemaVisitor -from qapi.schema import QAPISchema +from qapi.schema import QAPISchema, QAPISchemaVisitor -from qapidoc_legacy import QAPISchemaGenRSTVisitor +from qapidoc_legacy import QAPISchemaGenRSTVisitor # type: ignore from sphinx import addnodes from sphinx.directives.code import CodeBlock from sphinx.errors import ExtensionError @@ -42,6 +43,15 @@ from sphinx.util.nodes import nested_parse_with_titles +if TYPE_CHECKING: + from typing import Any, List, Sequence + + from docutils.statemachine import StringList + + from sphinx.application import Sphinx + from sphinx.util.typing import ExtensionMetadata + + __version__ = "1.0" @@ -53,11 +63,11 @@ class QAPISchemaGenDepVisitor(QAPISchemaVisitor): schema file associated with each module in the QAPI input. """ - def __init__(self, env, qapidir): + def __init__(self, env: Any, qapidir: str) -> None: self._env = env self._qapidir = qapidir - def visit_module(self, name): + def visit_module(self, name: str) -> None: if name != "./builtin": qapifile = self._qapidir + "/" + name self._env.note_dependency(os.path.abspath(qapifile)) @@ -65,10 +75,10 @@ def visit_module(self, name): class NestedDirective(Directive): - def run(self): + def run(self) -> Sequence[nodes.Node]: raise NotImplementedError - def do_parse(self, rstlist, node): + def do_parse(self, rstlist: StringList, node: nodes.Node) -> None: """ Parse rST source lines and add them to the specified node @@ -93,15 +103,15 @@ class QAPIDocDirective(NestedDirective): } has_content = False - def new_serialno(self): + def new_serialno(self) -> str: """Return a unique new ID string suitable for use as a node's ID""" env = self.state.document.settings.env return "qapidoc-%d" % env.new_serialno("qapidoc") - def transmogrify(self, schema) -> nodes.Element: + def transmogrify(self, schema: QAPISchema) -> nodes.Element: raise NotImplementedError - def legacy(self, schema) -> nodes.Element: + def legacy(self, schema: QAPISchema) -> nodes.Element: vis = QAPISchemaGenRSTVisitor(self) vis.visit_begin(schema) for doc in schema.docs: @@ -109,9 +119,9 @@ def legacy(self, schema) -> nodes.Element: vis.symbol(doc, schema.lookup_entity(doc.symbol)) else: vis.freeform(doc) - return vis.get_document_node() + return vis.get_document_node() # type: ignore - def run(self): + def run(self) -> Sequence[nodes.Node]: env = self.state.document.settings.env qapifile = env.config.qapidoc_srctree + "/" + self.arguments[0] qapidir = os.path.dirname(qapifile) @@ -185,7 +195,7 @@ def _highlightlang(self) -> addnodes.highlightlang: ) return node - def admonition_wrap(self, *content) -> List[nodes.Node]: + def admonition_wrap(self, *content: nodes.Node) -> List[nodes.Node]: title = "Example:" if "title" in self.options: title = f"{title} {self.options['title']}" @@ -231,7 +241,7 @@ def run(self) -> List[nodes.Node]: return self.admonition_wrap(*content_nodes) -def setup(app): +def setup(app: Sphinx) -> ExtensionMetadata: """Register qapi-doc directive with Sphinx""" app.add_config_value("qapidoc_srctree", None, "env") app.add_directive("qapi-doc", QAPIDocDirective) diff --git a/docs/sphinx/qapidoc_legacy.py b/docs/sphinx/qapidoc_legacy.py index 679f38356b..13520f4c26 100644 --- a/docs/sphinx/qapidoc_legacy.py +++ b/docs/sphinx/qapidoc_legacy.py @@ -1,4 +1,5 @@ # coding=utf-8 +# type: ignore # # QEMU qapidoc QAPI file parsing extension # From patchwork Tue Mar 11 11:31:12 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011547 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 1E729C28B2E for ; Tue, 11 Mar 2025 11:36:00 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxrD-0003bf-RB; Tue, 11 Mar 2025 07:33:11 -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 1trxqY-0003ER-SD for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:31 -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 1trxq9-0006WT-Ja for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:30 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692719; 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=LP5sw2f1gov5R484H/AB6Qo7wnA0cFD7EU7BInj2rnE=; b=YVUTfA8TwnFqk9QSHxL2J9R9CB/71IGMq0R6+pkqw00659kCu82zj+Z6sB7F0binBQXZLK REtJ1b6pXi/ExHYCc810f9UVCDMgAgjXxn7FFkW8BKSDb+9SaXt/yfaxoJhYT8L4iWW3Vl z+NsnOklj5lkHKbqtUn7S/G44EY9iuo= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-324-Yh0xqGH3PqWAos6jFn5PFg-1; Tue, 11 Mar 2025 07:31:58 -0400 X-MC-Unique: Yh0xqGH3PqWAos6jFn5PFg-1 X-Mimecast-MFC-AGG-ID: Yh0xqGH3PqWAos6jFn5PFg_1741692718 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (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 mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id E75E11955BC6 for ; Tue, 11 Mar 2025 11:31:57 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 8AD6F195608F for ; Tue, 11 Mar 2025 11:31:57 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 493BD21E61B7; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 36/61] docs/qapidoc: add transmogrifier class stub Date: Tue, 11 Mar 2025 12:31:12 +0100 Message-ID: <20250311113137.1277125-37-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Received-SPF: pass client-ip=170.10.133.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H2=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow Add the beginnings of the Transmogrifier class by adding the rST conversion helpers that will be used to build the virtual rST document. This version of the class does not actually "do anything" yet; each individual feature is added one-at-a-time in the forthcoming commits. Signed-off-by: John Snow Message-ID: <20250311034303.75779-40-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapidoc.py | 73 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 3 deletions(-) diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py index 5246832b68..c243bb6faa 100644 --- a/docs/sphinx/qapidoc.py +++ b/docs/sphinx/qapidoc.py @@ -26,14 +26,17 @@ from __future__ import annotations +from contextlib import contextmanager import os import sys from typing import TYPE_CHECKING from docutils import nodes from docutils.parsers.rst import Directive, directives +from docutils.statemachine import StringList from qapi.error import QAPIError from qapi.schema import QAPISchema, QAPISchemaVisitor +from qapi.source import QAPISourceInfo from qapidoc_legacy import QAPISchemaGenRSTVisitor # type: ignore from sphinx import addnodes @@ -44,9 +47,12 @@ if TYPE_CHECKING: - from typing import Any, List, Sequence - - from docutils.statemachine import StringList + from typing import ( + Any, + Generator, + List, + Sequence, + ) from sphinx.application import Sphinx from sphinx.util.typing import ExtensionMetadata @@ -55,6 +61,67 @@ __version__ = "1.0" +class Transmogrifier: + def __init__(self) -> None: + self._result = StringList() + self.indent = 0 + + # General-purpose rST generation functions + + def get_indent(self) -> str: + return " " * self.indent + + @contextmanager + def indented(self) -> Generator[None]: + self.indent += 1 + try: + yield + finally: + self.indent -= 1 + + def add_line_raw(self, line: str, source: str, *lineno: int) -> None: + """Append one line of generated reST to the output.""" + + # NB: Sphinx uses zero-indexed lines; subtract one. + lineno = tuple((n - 1 for n in lineno)) + + if line.strip(): + # not a blank line + self._result.append( + self.get_indent() + line.rstrip("\n"), source, *lineno + ) + else: + self._result.append("", source, *lineno) + + def add_line(self, content: str, info: QAPISourceInfo) -> None: + # NB: We *require* an info object; this works out OK because we + # don't document built-in objects that don't have + # one. Everything else should. + self.add_line_raw(content, info.fname, info.line) + + def add_lines( + self, + content: str, + info: QAPISourceInfo, + ) -> None: + lines = content.splitlines(True) + for i, line in enumerate(lines): + self.add_line_raw(line, info.fname, info.line + i) + + def ensure_blank_line(self) -> None: + # Empty document -- no blank line required. + if not self._result: + return + + # Last line isn't blank, add one. + if self._result[-1].strip(): # pylint: disable=no-member + fname, line = self._result.info(-1) + assert isinstance(line, int) + # New blank line is credited to one-after the current last line. + # +2: correct for zero/one index, then increment by one. + self.add_line_raw("", fname, line + 2) + + class QAPISchemaGenDepVisitor(QAPISchemaVisitor): """A QAPI schema visitor which adds Sphinx dependencies each module From patchwork Tue Mar 11 11:31:13 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011616 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 4F97DC35FF1 for ; Tue, 11 Mar 2025 11:52:23 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxsX-0007UW-Vz; Tue, 11 Mar 2025 07:34: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 1trxr0-0003PK-HC for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:33:02 -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 1trxqB-0006Wc-Gw for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:54 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692720; 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=GZbL5p1/16UwD56katIHAcwMx1G5loZdXPWmDkfZoAw=; b=WMrRzdZC5wQDtix5QBky2KRB9z8njFK055zI/kNS+WDPFAtspm0IPdcEgMCsHllu0pzpgu 28YgdfqKhG0N+Pk26iKjWj+NyTyat9wWYwP7qxNUMcmHRpQzdbAgngnJ2LNoB1trXBq9UL 9DppIQQCHDUX1o9cVeCAXki9kBQrwAk= Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-218-UcEK4lV2N56bZhO21Fvz0Q-1; Tue, 11 Mar 2025 07:31:58 -0400 X-MC-Unique: UcEK4lV2N56bZhO21Fvz0Q-1 X-Mimecast-MFC-AGG-ID: UcEK4lV2N56bZhO21Fvz0Q_1741692718 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (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 mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id D8A7219560A3 for ; Tue, 11 Mar 2025 11:31:57 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 724323001D14 for ; Tue, 11 Mar 2025 11:31:57 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 4CFB121E61B8; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 37/61] docs/qapidoc: add visit_module() method Date: Tue, 11 Mar 2025 12:31:13 +0100 Message-ID: <20250311113137.1277125-38-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Received-SPF: pass client-ip=170.10.133.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H2=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow This method annotates the start of a new module, crediting the source location to the first line of the module file. Signed-off-by: John Snow Message-ID: <20250311034303.75779-41-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapidoc.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py index c243bb6faa..6de8c90054 100644 --- a/docs/sphinx/qapidoc.py +++ b/docs/sphinx/qapidoc.py @@ -28,6 +28,7 @@ from contextlib import contextmanager import os +from pathlib import Path import sys from typing import TYPE_CHECKING @@ -121,6 +122,14 @@ def ensure_blank_line(self) -> None: # +2: correct for zero/one index, then increment by one. self.add_line_raw("", fname, line + 2) + # Transmogrification core methods + + def visit_module(self, path: str) -> None: + name = Path(path).stem + # module directives are credited to the first line of a module file. + self.add_line_raw(f".. qapi:module:: {name}", path, 1) + self.ensure_blank_line() + class QAPISchemaGenDepVisitor(QAPISchemaVisitor): """A QAPI schema visitor which adds Sphinx dependencies each module From patchwork Tue Mar 11 11:31:14 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011604 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 09116C28B2E for ; Tue, 11 Mar 2025 11:50:42 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxrI-0003fJ-F5; Tue, 11 Mar 2025 07:33:18 -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 1trxqt-0003OK-Bw for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:58 -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 1trxqC-0006WS-0R for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:51 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692719; 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=tIz5D146hfHkf+gYrn3NUb8y77ROWgAaRiF8ghz04Zc=; b=JowILy14ev/hRoIb3X5LFg2wq03giG2iY9x4cy3rkuJ4zamoE1szB/gSALLHM0t1CY6hnl fd5J0t080VnCvX0rO6p9vNBpJLMo8H9UO0nDc33Vb1dS1t0oBnmiUs0V94ykGKci34f13W zKbB0ij+oTZTze4PW5pwJVGRa2i8dVA= Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-202-KVQxNFDrP3Od3N6a27Pzpg-1; Tue, 11 Mar 2025 07:31:58 -0400 X-MC-Unique: KVQxNFDrP3Od3N6a27Pzpg-1 X-Mimecast-MFC-AGG-ID: KVQxNFDrP3Od3N6a27Pzpg_1741692717 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 76E4619560B4 for ; Tue, 11 Mar 2025 11:31:57 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 2AEF21801752 for ; Tue, 11 Mar 2025 11:31:57 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 50A8521E61BB; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 38/61] qapi/source: allow multi-line QAPISourceInfo advancing Date: Tue, 11 Mar 2025 12:31:14 +0100 Message-ID: <20250311113137.1277125-39-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass client-ip=170.10.133.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H2=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow This is for the sake of the new rST generator (the "transmogrifier") so we can advance multiple lines on occasion while keeping the generated<-->source mappings accurate. next_line now simply takes an optional n parameter which chooses the number of lines to advance. The next patch will use this when converting section syntax in free-form documentation to more traditional rST section header syntax, which does not always line up 1:1 for line counts. For example: ``` ## # = Section <-- Info is pointing here, "L1" # # Lorem Ipsum ## ``` would be transformed to rST as: ``` ======= <-- L1 Section <-- L1 ======= <-- L1 <-- L2 Lorem Ipsum <-- L3 ``` After consuming the single "Section" line from the source, we want to advance the source pointer to the next non-empty line which requires jumping by more than one line. Signed-off-by: John Snow Reviewed-by: Markus Armbruster Message-ID: <20250311034303.75779-42-jsnow@redhat.com> Signed-off-by: Markus Armbruster --- scripts/qapi/source.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/qapi/source.py b/scripts/qapi/source.py index 7b379fdc92..ffdc3f482a 100644 --- a/scripts/qapi/source.py +++ b/scripts/qapi/source.py @@ -47,9 +47,9 @@ def set_defn(self, meta: str, name: str) -> None: self.defn_meta = meta self.defn_name = name - def next_line(self: T) -> T: + def next_line(self: T, n: int = 1) -> T: info = copy.copy(self) - info.line += 1 + info.line += n return info def loc(self) -> str: From patchwork Tue Mar 11 11:31:15 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011592 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 29ECDC282EC for ; Tue, 11 Mar 2025 11:46:08 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxrC-0003Wt-1P; Tue, 11 Mar 2025 07:33:10 -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 1trxqW-0003Cx-7M for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:28 -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 1trxq9-0006Wz-Mp for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:27 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692720; 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=IHpn6RM60iN5008DmLJtF3vc+uN0LyK9v2tygWdAa+s=; b=VWQhv3bggyPMt1qNRDo6TvWm6CDhT8pFUtMXcW05FZxNO7/PsWqL9TmOWfu7OCUozw2IlT 3pW+aT9OTSC/o8m2B3tE04ZVtaHShWPpQ8GF92IAsOeMgsOH6tro06gbCIOgKmJzq3me5i WsukI/oXFGnH4BRqOitZ048/P6AudPw= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-459-kofgPJx5OIu94Pf_wR0DWw-1; Tue, 11 Mar 2025 07:31:59 -0400 X-MC-Unique: kofgPJx5OIu94Pf_wR0DWw-1 X-Mimecast-MFC-AGG-ID: kofgPJx5OIu94Pf_wR0DWw_1741692718 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (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 mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 3FD23180035E for ; Tue, 11 Mar 2025 11:31:58 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id B8C183001D15 for ; Tue, 11 Mar 2025 11:31:57 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 548AF21E61BD; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 39/61] docs/qapidoc: add visit_freeform() method Date: Tue, 11 Mar 2025 12:31:15 +0100 Message-ID: <20250311113137.1277125-40-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow Add the transmogrifier implementation for converting freeform doc blocks to rST. Signed-off-by: John Snow Message-ID: <20250311034303.75779-43-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapidoc.py | 44 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py index 6de8c90054..ddad604145 100644 --- a/docs/sphinx/qapidoc.py +++ b/docs/sphinx/qapidoc.py @@ -29,6 +29,7 @@ from contextlib import contextmanager import os from pathlib import Path +import re import sys from typing import TYPE_CHECKING @@ -55,6 +56,8 @@ Sequence, ) + from qapi.parser import QAPIDoc + from sphinx.application import Sphinx from sphinx.util.typing import ExtensionMetadata @@ -130,6 +133,47 @@ def visit_module(self, path: str) -> None: self.add_line_raw(f".. qapi:module:: {name}", path, 1) self.ensure_blank_line() + def visit_freeform(self, doc: QAPIDoc) -> None: + # TODO: Once the old qapidoc transformer is deprecated, freeform + # sections can be updated to pure rST, and this transformed removed. + # + # For now, translate our micro-format into rST. Code adapted + # from Peter Maydell's freeform(). + + assert len(doc.all_sections) == 1, doc.all_sections + body = doc.all_sections[0] + text = body.text + info = doc.info + + if re.match(r"=+ ", text): + # Section/subsection heading (if present, will always be the + # first line of the block) + (heading, _, text) = text.partition("\n") + (leader, _, heading) = heading.partition(" ") + # Implicit +1 for heading in the containing .rst doc + level = len(leader) + 1 + + # https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html#sections + markers = ' #*=_^"' + overline = level <= 2 + marker = markers[level] + + self.ensure_blank_line() + # This credits all 2 or 3 lines to the single source line. + if overline: + self.add_line(marker * len(heading), info) + self.add_line(heading, info) + self.add_line(marker * len(heading), info) + self.ensure_blank_line() + + # Eat blank line(s) and advance info + trimmed = text.lstrip("\n") + text = trimmed + info = info.next_line(len(text) - len(trimmed) + 1) + + self.add_lines(text, info) + self.ensure_blank_line() + class QAPISchemaGenDepVisitor(QAPISchemaVisitor): """A QAPI schema visitor which adds Sphinx dependencies each module From patchwork Tue Mar 11 11:31:16 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011601 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 1711FC282EC for ; Tue, 11 Mar 2025 11:48:15 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxsQ-0006dI-7W; Tue, 11 Mar 2025 07:34:27 -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 1trxqo-0003N1-UE for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:49 -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 1trxqB-0006XO-4j for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:46 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692721; 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=kELx4R5nyjgFkpx05YRwXMpWdxrB+seHv2cdVN50orQ=; b=J5uoiFscNDHzSLAo+wUMgFeYVYmYuC4+JcgBslOk1OCz/HSJ92Hnw7kLl9GxHLgBCgjQFi n30EgGvZ8hlsWHfl6ksCFqFCpO1Su0EM2BlDymNa8d9FBsCvDUKlAlMYJCoOk6/AkMXCUc +oZ70O06BxjkxsRK9/xU0yzyd4KyLlQ= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-457-bV3tZdAQNL-OWJVrn6YygA-1; Tue, 11 Mar 2025 07:31:58 -0400 X-MC-Unique: bV3tZdAQNL-OWJVrn6YygA-1 X-Mimecast-MFC-AGG-ID: bV3tZdAQNL-OWJVrn6YygA_1741692718 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (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 mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 10F8B1955BC9 for ; Tue, 11 Mar 2025 11:31:58 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 8B03C1828A95 for ; Tue, 11 Mar 2025 11:31:57 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 586ED21E614A; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 40/61] docs/qapidoc: add preamble() method Date: Tue, 11 Mar 2025 12:31:16 +0100 Message-ID: <20250311113137.1277125-41-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, T_SPF_TEMPERROR=0.01 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: John Snow This method adds the options/preamble to each definition block. Notably, :since: and :ifcond: are added, as are any "special features" such as :deprecated: and :unstable:. If conditionals, if attached to special features, are currently unhandled in this patch and will be addressed at a future date. We currently do not have any if conditionals attached to special features. Signed-off-by: John Snow Message-ID: <20250311034303.75779-44-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapidoc.py | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py index ddad604145..f56aa6d1fd 100644 --- a/docs/sphinx/qapidoc.py +++ b/docs/sphinx/qapidoc.py @@ -37,7 +37,12 @@ from docutils.parsers.rst import Directive, directives from docutils.statemachine import StringList from qapi.error import QAPIError -from qapi.schema import QAPISchema, QAPISchemaVisitor +from qapi.parser import QAPIDoc +from qapi.schema import ( + QAPISchema, + QAPISchemaDefinition, + QAPISchemaVisitor, +) from qapi.source import QAPISourceInfo from qapidoc_legacy import QAPISchemaGenRSTVisitor # type: ignore @@ -56,8 +61,6 @@ Sequence, ) - from qapi.parser import QAPIDoc - from sphinx.application import Sphinx from sphinx.util.typing import ExtensionMetadata @@ -125,6 +128,38 @@ def ensure_blank_line(self) -> None: # +2: correct for zero/one index, then increment by one. self.add_line_raw("", fname, line + 2) + # Transmogrification helpers + + def preamble(self, ent: QAPISchemaDefinition) -> None: + """ + Generate option lines for QAPI entity directives. + """ + if ent.doc and ent.doc.since: + assert ent.doc.since.kind == QAPIDoc.Kind.SINCE + # Generated from the entity's docblock; info location is exact. + self.add_line(f":since: {ent.doc.since.text}", ent.doc.since.info) + + if ent.ifcond.is_present(): + doc = ent.ifcond.docgen() + assert ent.info + # Generated from entity definition; info location is approximate. + self.add_line(f":ifcond: {doc}", ent.info) + + # Hoist special features such as :deprecated: and :unstable: + # into the options block for the entity. If, in the future, new + # special features are added, qapi-domain will chirp about + # unrecognized options and fail until they are handled in + # qapi-domain. + for feat in ent.features: + if feat.is_special(): + # FIXME: handle ifcond if present. How to display that + # information is TBD. + # Generated from entity def; info location is approximate. + assert feat.info + self.add_line(f":{feat.name}:", feat.info) + + self.ensure_blank_line() + # Transmogrification core methods def visit_module(self, path: str) -> None: From patchwork Tue Mar 11 11:31:17 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011588 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 A625AC282EC for ; Tue, 11 Mar 2025 11:45:13 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxsU-00077Y-AT; Tue, 11 Mar 2025 07:34:32 -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 1trxqw-0003OW-9j for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:33:02 -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 1trxqC-0006Wj-1W for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:53 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692720; 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=oOUXF8IxwgmgX6fTo2moYWziG/XhiwEkli3EW8pyNHY=; b=ad0IpY4LpFB9H1ABvlhhS+U9pT/4wPULgu7AN9CByGztp9k3XKf+eF0Y7xy+XWgCX5jLHM hZbPCzrDzh66gUmyc47oMHq4A2B9IZc9DUTxrG0gopJhdFu4Fn20hPdzSxOjcul+CM6dVk SN6+bAwxYL8TaFwhGV7jSV0+lOoFmEU= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-290-SsyzxlPCNZ6PgVhrT2ILag-1; Tue, 11 Mar 2025 07:31:58 -0400 X-MC-Unique: SsyzxlPCNZ6PgVhrT2ILag-1 X-Mimecast-MFC-AGG-ID: SsyzxlPCNZ6PgVhrT2ILag_1741692717 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id BDD971955D4B for ; Tue, 11 Mar 2025 11:31:57 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 615C11800268 for ; Tue, 11 Mar 2025 11:31:57 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 5C3BE21E6152; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 41/61] docs/qapidoc: add visit_paragraph() method Date: Tue, 11 Mar 2025 12:31:17 +0100 Message-ID: <20250311113137.1277125-42-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass client-ip=170.10.133.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow This transforms "formerly known as untagged sections" into our pure intermediate rST format. These sections are already pure rST, so this method doesn't do a whole lot except ensure appropriate newlines. Signed-off-by: John Snow Message-ID: <20250311034303.75779-45-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapidoc.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py index f56aa6d1fd..a9f98d4657 100644 --- a/docs/sphinx/qapidoc.py +++ b/docs/sphinx/qapidoc.py @@ -130,6 +130,15 @@ def ensure_blank_line(self) -> None: # Transmogrification helpers + def visit_paragraph(self, section: QAPIDoc.Section) -> None: + # Squelch empty paragraphs. + if not section.text: + return + + self.ensure_blank_line() + self.add_lines(section.text, section.info) + self.ensure_blank_line() + def preamble(self, ent: QAPISchemaDefinition) -> None: """ Generate option lines for QAPI entity directives. From patchwork Tue Mar 11 11:31:18 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011600 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 5862AC282EC for ; Tue, 11 Mar 2025 11:47:28 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxrE-0003d0-E9; Tue, 11 Mar 2025 07:33:12 -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 1trxqn-0003Mw-JZ for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:49 -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 1trxqB-0006Wg-7p for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:45 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692720; 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=tb5UQ0VP50LYJ3MuJmz889CIek+mre9DCNVkdLMnpjw=; b=fx90VNuI0MbYzP3mnG3+XP8MeeEFysMvJFE22BW6s+MkoNkSAoPxH8FD/Pj5O88W4Vuzvr d1a1i+eyfxEt0AkARjXJUJS91wKNFYhXSP6g0ZpthmuUKrq79ocA8Iv8LWPdgQxARkTYmf qbrxpQVNYQzbmqY8JKrgram5v43rmwg= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-455-obCW30fzOeCxfcOca8zuzQ-1; Tue, 11 Mar 2025 07:31:58 -0400 X-MC-Unique: obCW30fzOeCxfcOca8zuzQ-1 X-Mimecast-MFC-AGG-ID: obCW30fzOeCxfcOca8zuzQ_1741692718 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (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 mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id E62AA195608F for ; Tue, 11 Mar 2025 11:31:57 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 8B9791955BCB for ; Tue, 11 Mar 2025 11:31:57 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 6009F21E60C1; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 42/61] docs/qapidoc: add visit_errors() method Date: Tue, 11 Mar 2025 12:31:18 +0100 Message-ID: <20250311113137.1277125-43-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow Notably, this method does not currently address the formatting issues present with the "errors" section in QAPIDoc and just vomits the text verbatim into the rST doc, with somewhat inconsistent results. To be addressed in a future patch. Signed-off-by: John Snow Message-ID: <20250311034303.75779-46-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapidoc.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py index a9f98d4657..c17cb9f9b1 100644 --- a/docs/sphinx/qapidoc.py +++ b/docs/sphinx/qapidoc.py @@ -139,6 +139,12 @@ def visit_paragraph(self, section: QAPIDoc.Section) -> None: self.add_lines(section.text, section.info) self.ensure_blank_line() + def visit_errors(self, section: QAPIDoc.Section) -> None: + # FIXME: the formatting for errors may be inconsistent and may + # or may not require different newline placement to ensure + # proper rendering as a nested list. + self.add_lines(f":error:\n{section.text}", section.info) + def preamble(self, ent: QAPISchemaDefinition) -> None: """ Generate option lines for QAPI entity directives. From patchwork Tue Mar 11 11:31:19 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011545 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 B2C1AC282EC for ; Tue, 11 Mar 2025 11:35:09 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxsk-0008NH-Jy; Tue, 11 Mar 2025 07:34: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 1trxqq-0003NK-Gt for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:58 -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 1trxqB-0006XF-W3 for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:48 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692721; 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=1F28YX+b+T8t9txdlT/VfEgEStcWIgsSvBN7m7XAr5E=; b=NEonN0yWYn44634e+u8rbWMCMdfy4K3VGv6PkXeS2m8RjchgvZy20VRfvxjT/V5M59j4Tt 6ybtHHHwWMDnRyCzIl5HX/N3nEAvcnhSlDSXodDqpV9aAXQzd3CHEDly3zvZbnwFoMUgBd O/tA+fIMDqJFaOuxzujpAXYBoebi6M4= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-218-dCE3e4a-O3KS4_3C7UcbvA-1; Tue, 11 Mar 2025 07:31:58 -0400 X-MC-Unique: dCE3e4a-O3KS4_3C7UcbvA-1 X-Mimecast-MFC-AGG-ID: dCE3e4a-O3KS4_3C7UcbvA_1741692718 Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (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 mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 1103E180AF52 for ; Tue, 11 Mar 2025 11:31:58 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id B653F1956094 for ; Tue, 11 Mar 2025 11:31:57 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 63DAA21E60C3; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 43/61] docs/qapidoc: add format_type() method Date: Tue, 11 Mar 2025 12:31:19 +0100 Message-ID: <20250311113137.1277125-44-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 Received-SPF: pass client-ip=170.10.133.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow This method is responsible for generating a type name for a given member with the correct annotations for the QAPI domain. Features and enums do not *have* types, so they return None. Everything else returns the type name with a "?" suffix if that type is optional, and ensconced in [brackets] if it's an array type. Signed-off-by: John Snow Message-ID: <20250311034303.75779-47-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapidoc.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py index c17cb9f9b1..5144bb965a 100644 --- a/docs/sphinx/qapidoc.py +++ b/docs/sphinx/qapidoc.py @@ -40,7 +40,13 @@ from qapi.parser import QAPIDoc from qapi.schema import ( QAPISchema, + QAPISchemaArrayType, QAPISchemaDefinition, + QAPISchemaEnumMember, + QAPISchemaFeature, + QAPISchemaMember, + QAPISchemaObjectTypeMember, + QAPISchemaType, QAPISchemaVisitor, ) from qapi.source import QAPISourceInfo @@ -58,7 +64,9 @@ Any, Generator, List, + Optional, Sequence, + Union, ) from sphinx.application import Sphinx @@ -128,6 +136,30 @@ def ensure_blank_line(self) -> None: # +2: correct for zero/one index, then increment by one. self.add_line_raw("", fname, line + 2) + def format_type( + self, ent: Union[QAPISchemaDefinition | QAPISchemaMember] + ) -> Optional[str]: + if isinstance(ent, (QAPISchemaEnumMember, QAPISchemaFeature)): + return None + + qapi_type = ent + optional = False + if isinstance(ent, QAPISchemaObjectTypeMember): + qapi_type = ent.type + optional = ent.optional + + if isinstance(qapi_type, QAPISchemaArrayType): + ret = f"[{qapi_type.element_type.doc_type()}]" + else: + assert isinstance(qapi_type, QAPISchemaType) + tmp = qapi_type.doc_type() + assert tmp + ret = tmp + if optional: + ret += "?" + + return ret + # Transmogrification helpers def visit_paragraph(self, section: QAPIDoc.Section) -> None: From patchwork Tue Mar 11 11:31:20 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011565 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 BF641C28B2E for ; Tue, 11 Mar 2025 11:37:20 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxsB-0005dD-Ij; Tue, 11 Mar 2025 07:34:11 -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 1trxqi-0003Lq-EC for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32: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 1trxqA-0006XY-EA for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:40 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692721; 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=EAf2i0hV0dGAUER9w8yksaBuR3xTab25CepDSDoORlo=; b=e2QZw2hh57tfliz+f4gMRt98zBkrNJhZg/oxY9QsxBVYsQ2VOmkWOqfkFNyfckO18B/c4Z sr6QnYEECHfOC5QAe4pVHlQ7TwdrRNXv50QPGuwRzJwLl8znaZmD80jFksthveuIwkZ2h/ YQ2gFuNhBcLJ+sRzOuOqDIGcOV8f7sM= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-157-I8t8FhVdO4meyRQ5mu4pkA-1; Tue, 11 Mar 2025 07:31:58 -0400 X-MC-Unique: I8t8FhVdO4meyRQ5mu4pkA-1 X-Mimecast-MFC-AGG-ID: I8t8FhVdO4meyRQ5mu4pkA_1741692718 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (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 mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id E581D180AF4C for ; Tue, 11 Mar 2025 11:31:57 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 722263001D13 for ; Tue, 11 Mar 2025 11:31:57 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 6821421E60C7; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 44/61] docs/qapidoc: add add_field() and generate_field() helper methods Date: Tue, 11 Mar 2025 12:31:20 +0100 Message-ID: <20250311113137.1277125-45-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow These are simple rST generation methods that assist in getting the types and formatting correct for a field list entry. add_field() is a more raw, direct call while generate_field() is intended to be used for generating the correct field from a member object. Signed-off-by: John Snow Message-ID: <20250311034303.75779-48-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapidoc.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py index 5144bb965a..2f85fe0bc3 100644 --- a/docs/sphinx/qapidoc.py +++ b/docs/sphinx/qapidoc.py @@ -136,6 +136,20 @@ def ensure_blank_line(self) -> None: # +2: correct for zero/one index, then increment by one. self.add_line_raw("", fname, line + 2) + def add_field( + self, + kind: str, + name: str, + body: str, + info: QAPISourceInfo, + typ: Optional[str] = None, + ) -> None: + if typ: + text = f":{kind} {typ} {name}: {body}" + else: + text = f":{kind} {name}: {body}" + self.add_lines(text, info) + def format_type( self, ent: Union[QAPISchemaDefinition | QAPISchemaMember] ) -> Optional[str]: @@ -160,6 +174,16 @@ def format_type( return ret + def generate_field( + self, + kind: str, + member: QAPISchemaMember, + body: str, + info: QAPISourceInfo, + ) -> None: + typ = self.format_type(member) + self.add_field(kind, member.name, body, info, typ) + # Transmogrification helpers def visit_paragraph(self, section: QAPIDoc.Section) -> None: From patchwork Tue Mar 11 11:31:21 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011571 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 8CB6AC282EC for ; Tue, 11 Mar 2025 11:39:26 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxrT-00044b-3l; Tue, 11 Mar 2025 07:33:27 -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 1trxqj-0003M2-Q2 for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32: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 1trxqA-0006Wa-W0 for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:41 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692720; 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=o2AWJO5QP5nZv/3JfYIJv60N3K5K6U4zvCKcJJeAgmU=; b=HfPrYqflvIOv4TkjRPguks9g4wiSvSt4wcA4/CLu9Jy0S30QQAbI66mQcOC1Z3dnsBv9Cu ZQ8xjwALKUsmfA35qXGLpIen2oTGjGNUJBkqScBoOsyWjDe5hLesfu7RRxI2HrdJ3hdhLv hE24ZQYeucD+5wNmgMWLmQ7uVH+K+9k= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-455-GK0xtc1POreEeBwmzxB3Lg-1; Tue, 11 Mar 2025 07:31:58 -0400 X-MC-Unique: GK0xtc1POreEeBwmzxB3Lg-1 X-Mimecast-MFC-AGG-ID: GK0xtc1POreEeBwmzxB3Lg_1741692718 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (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 mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id E668B18001F7 for ; Tue, 11 Mar 2025 11:31:57 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 8B41919560AB for ; Tue, 11 Mar 2025 11:31:57 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 6BC3321E60C9; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 45/61] docs/qapidoc: add visit_feature() method Date: Tue, 11 Mar 2025 12:31:21 +0100 Message-ID: <20250311113137.1277125-46-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow This adds a simple ":feat name: lorem ipsum ..." line to the generated rST document, so at the moment it's only for "top level" features. Features not attached directly to a QAPI definition are not currently handled! This is a small regression over the prior documentation generator that will be addressed in a future patch. Signed-off-by: John Snow Message-ID: <20250311034303.75779-49-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapidoc.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py index 2f85fe0bc3..208d7ca144 100644 --- a/docs/sphinx/qapidoc.py +++ b/docs/sphinx/qapidoc.py @@ -195,6 +195,15 @@ def visit_paragraph(self, section: QAPIDoc.Section) -> None: self.add_lines(section.text, section.info) self.ensure_blank_line() + def visit_feature(self, section: QAPIDoc.ArgSection) -> None: + # FIXME - ifcond for features is not handled at all yet! + # Proposal: decorate the right-hand column with some graphical + # element to indicate conditional availability? + assert section.text # Guaranteed by parser.py + assert section.member + + self.generate_field("feat", section.member, section.text, section.info) + def visit_errors(self, section: QAPIDoc.Section) -> None: # FIXME: the formatting for errors may be inconsistent and may # or may not require different newline placement to ensure From patchwork Tue Mar 11 11:31:22 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011591 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 042DAC28B2E for ; Tue, 11 Mar 2025 11:46:03 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxrE-0003d5-GK; Tue, 11 Mar 2025 07:33:12 -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 1trxqW-0003Cy-7L for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:28 -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 1trxq9-0006Wl-GN for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:24 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692720; 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=VI8Nx/JoaH5T/reNAEPb5jnrg9k/fQdamezD5Ij9+vI=; b=Bmy61a2lNroqDbpm7TZb0bF78DRXgskGvwd4Zj6f4GLc90a5EB0pTnM7GPLggfso5ARAZn HKyD/pDIlZGIrXznMdZYgOwmcN1ZZD01yTMnqGMI1Eh+Cv5NrIsgNjYD46IdkLWndG1n5Y c/GD07x53b0PkjgpTHobuVJJvDP6iFQ= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-272-BI3LoIHjNiWD-r_lds3fOg-1; Tue, 11 Mar 2025 07:31:59 -0400 X-MC-Unique: BI3LoIHjNiWD-r_lds3fOg-1 X-Mimecast-MFC-AGG-ID: BI3LoIHjNiWD-r_lds3fOg_1741692718 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (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 mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 37CD819560B0 for ; Tue, 11 Mar 2025 11:31:58 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id DD9E118001E9 for ; Tue, 11 Mar 2025 11:31:57 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 6FB3B21E60CD; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 46/61] docs/qapidoc: prepare to record entity being transmogrified Date: Tue, 11 Mar 2025 12:31:22 +0100 Message-ID: <20250311113137.1277125-47-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass client-ip=170.10.133.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H2=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow Prepare to keep a record of which entity we're working on documenting for the purposes of being able to change certain generative features conditionally and create stronger assertions. If you find yourself asking: "Wait, but where does the current entity actually get recorded?!", you're right! That part comes with the visit_entity() implementation, which gets added later. This patch is front-loaded for the sake of type checking in the forthcoming commits before visit_entity() is ready to be added. Signed-off-by: John Snow Message-ID: <20250311034303.75779-50-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapidoc.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py index 208d7ca144..47c2eeef87 100644 --- a/docs/sphinx/qapidoc.py +++ b/docs/sphinx/qapidoc.py @@ -78,9 +78,15 @@ class Transmogrifier: def __init__(self) -> None: + self._curr_ent: Optional[QAPISchemaDefinition] = None self._result = StringList() self.indent = 0 + @property + def entity(self) -> QAPISchemaDefinition: + assert self._curr_ent is not None + return self._curr_ent + # General-purpose rST generation functions def get_indent(self) -> str: From patchwork Tue Mar 11 11:31:23 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011568 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 E8F7DC282EC for ; Tue, 11 Mar 2025 11:38:45 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxrw-0004vo-0i; Tue, 11 Mar 2025 07:33:56 -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 1trxqw-0003OX-FA for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:33:02 -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 1trxqC-0006WU-Bw for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:54 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692719; 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=Qjlzx2MZaR0egoRFAmtCHfA7E8F6U90hY/0cpoQP75A=; b=Av3YvjARUIUcLw93sNlgTfZ/ftnSHj88xN5q/3Ab3websUqnQwkN0tp6zbfvoDZAYDWKwC T61+CF9jeoC/4NMFu0cKobP61240Jqa0fUYFZm8stqRQ9yDo9H/gsfXl44jPowa28iw/cA kfofS6HAhlWlT/4W/uqBRQyqjy5aXUo= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-147-w5_6A3nZO1OqafwodnMg-Q-1; Tue, 11 Mar 2025 07:31:58 -0400 X-MC-Unique: w5_6A3nZO1OqafwodnMg-Q-1 X-Mimecast-MFC-AGG-ID: w5_6A3nZO1OqafwodnMg-Q_1741692717 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (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 mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id BE95D1956080 for ; Tue, 11 Mar 2025 11:31:57 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 713CB1828A98 for ; Tue, 11 Mar 2025 11:31:57 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 7397321E60D6; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 47/61] docs/qapidoc: add visit_returns() method Date: Tue, 11 Mar 2025 12:31:23 +0100 Message-ID: <20250311113137.1277125-48-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow Generates :return: fields for explicit returns statements. Note that this does not presently handle undocumented returns, which is handled in a later commit. Signed-off-by: John Snow Message-ID: <20250311034303.75779-51-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapidoc.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py index 47c2eeef87..eb8841099c 100644 --- a/docs/sphinx/qapidoc.py +++ b/docs/sphinx/qapidoc.py @@ -41,6 +41,7 @@ from qapi.schema import ( QAPISchema, QAPISchemaArrayType, + QAPISchemaCommand, QAPISchemaDefinition, QAPISchemaEnumMember, QAPISchemaFeature, @@ -210,6 +211,20 @@ def visit_feature(self, section: QAPIDoc.ArgSection) -> None: self.generate_field("feat", section.member, section.text, section.info) + def visit_returns(self, section: QAPIDoc.Section) -> None: + assert isinstance(self.entity, QAPISchemaCommand) + rtype = self.entity.ret_type + # q_empty can produce None, but we won't be documenting anything + # without an explicit return statement in the doc block, and we + # should not have any such explicit statements when there is no + # return value. + assert rtype + + typ = self.format_type(rtype) + assert typ + assert section.text + self.add_field("return", typ, section.text, section.info) + def visit_errors(self, section: QAPIDoc.Section) -> None: # FIXME: the formatting for errors may be inconsistent and may # or may not require different newline placement to ensure From patchwork Tue Mar 11 11:31:24 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011572 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 94663C282EC for ; Tue, 11 Mar 2025 11:40:07 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxrT-000411-3k; Tue, 11 Mar 2025 07:33:27 -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 1trxqu-0003ON-2X for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:58 -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 1trxqC-0006XK-1E for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:51 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692721; 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=ADMLW+61PuWpsuphJIvWInfzcdZbDjmCvugW0JTDjWE=; b=fNI4z2PHEvlvy6EzOkJsUwidBJ2tARfJyRmEfB44RO0d0KX/SiNADYixaHZhClq9otsXa2 gdNGgrnSofLSfvL2Zo4vvo4V8H9ZQ6AdNjwIWzEVaL+EfFYxoYLM1Ogtq8qUUh+g9gCaBW r3PYjgYzYfmxDFe3G2mAunJ4riZyhvw= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-362-W4owZr_aPVC6a42gfFPPiA-1; Tue, 11 Mar 2025 07:32:00 -0400 X-MC-Unique: W4owZr_aPVC6a42gfFPPiA-1 X-Mimecast-MFC-AGG-ID: W4owZr_aPVC6a42gfFPPiA_1741692719 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (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 mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 9693C19560A1 for ; Tue, 11 Mar 2025 11:31:58 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 30D4F19560AD for ; Tue, 11 Mar 2025 11:31:58 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 7769D21E60D8; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 48/61] docs/qapidoc: add visit_member() method Date: Tue, 11 Mar 2025 12:31:24 +0100 Message-ID: <20250311113137.1277125-49-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 Received-SPF: pass client-ip=170.10.133.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H2=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=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: John Snow This method is used for generating the "members" of a wide variety of things, including structs, unions, enums, alternates, etc. The field name it uses to do so is dependent on the type of entity the "member" belongs to. Currently, IF conditionals for individual members are not handled or rendered, a small regression from the prior documentation generator. This will be fixed in a future patch. Signed-off-by: John Snow Message-ID: <20250311034303.75779-52-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapidoc.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py index eb8841099c..a8e19487d0 100644 --- a/docs/sphinx/qapidoc.py +++ b/docs/sphinx/qapidoc.py @@ -78,6 +78,16 @@ class Transmogrifier: + # Field names used for different entity types: + field_types = { + "enum": "value", + "struct": "memb", + "union": "memb", + "event": "memb", + "command": "arg", + "alternate": "alt", + } + def __init__(self) -> None: self._curr_ent: Optional[QAPISchemaDefinition] = None self._result = StringList() @@ -88,6 +98,10 @@ def entity(self) -> QAPISchemaDefinition: assert self._curr_ent is not None return self._curr_ent + @property + def member_field_type(self) -> str: + return self.field_types[self.entity.meta] + # General-purpose rST generation functions def get_indent(self) -> str: @@ -202,6 +216,19 @@ def visit_paragraph(self, section: QAPIDoc.Section) -> None: self.add_lines(section.text, section.info) self.ensure_blank_line() + def visit_member(self, section: QAPIDoc.ArgSection) -> None: + # FIXME: ifcond for members + # TODO: features for members (documented at entity-level, + # but sometimes defined per-member. Should we add such + # information to member descriptions when we can?) + assert section.text and section.member + self.generate_field( + self.member_field_type, + section.member, + section.text, + section.info, + ) + def visit_feature(self, section: QAPIDoc.ArgSection) -> None: # FIXME - ifcond for features is not handled at all yet! # Proposal: decorate the right-hand column with some graphical From patchwork Tue Mar 11 11:31:25 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011595 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 4B9F1C282EC for ; Tue, 11 Mar 2025 11:46:12 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxsQ-0006lL-Fu; Tue, 11 Mar 2025 07:34:26 -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 1trxqb-0003FN-8N for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32: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 1trxqA-0006XD-CW for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:31 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692721; 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=52E2Meg0uM+hlv5UQ3Tc1MyKxWQex8OaRjQ9GV3pE9g=; b=eou1Jb/AhCvKDsRPfFSb0OO7vsX1EqZemZu73JElo+Fr4omF/d5dcGN3hRriFQjW4oNCQ9 HESGbuSNrHf+84toGsHnkuIBDH+ZiFp4MvKFgkLusuMww7NCwV/9HJHQAnhHQJ8rwPTOym F1hDf2qdoBWROhJJkWReGmSm+AueL0M= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-308-V9AvJkUkMZS7FvFcJ16uuw-1; Tue, 11 Mar 2025 07:31:59 -0400 X-MC-Unique: V9AvJkUkMZS7FvFcJ16uuw-1 X-Mimecast-MFC-AGG-ID: V9AvJkUkMZS7FvFcJ16uuw_1741692718 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (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 mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 7E21C19560B5 for ; Tue, 11 Mar 2025 11:31:58 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id E13DC30001A2 for ; Tue, 11 Mar 2025 11:31:57 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 7B51721E6143; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 49/61] docs/qapidoc: add visit_sections() method Date: Tue, 11 Mar 2025 12:31:25 +0100 Message-ID: <20250311113137.1277125-50-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Received-SPF: pass client-ip=170.10.133.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H2=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow Implement the actual main dispatch method that processes and handles the list of doc sections for a given QAPI entity. Process doc sections in strict source order. This is good; reordering doc text is undesirable. Improvement over the old doc generator, which can reorder doc comments that don't adhere to (largely unspoken) conventions. Signed-off-by: John Snow Message-ID: <20250311034303.75779-53-jsnow@redhat.com> Acked-by: Markus Armbruster [Commit message extended] Signed-off-by: Markus Armbruster --- docs/sphinx/qapidoc.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py index a8e19487d0..83022b15ca 100644 --- a/docs/sphinx/qapidoc.py +++ b/docs/sphinx/qapidoc.py @@ -288,6 +288,31 @@ def preamble(self, ent: QAPISchemaDefinition) -> None: self.ensure_blank_line() + def visit_sections(self, ent: QAPISchemaDefinition) -> None: + sections = ent.doc.all_sections if ent.doc else [] + + # Add sections in source order: + for section in sections: + if section.kind == QAPIDoc.Kind.PLAIN: + self.visit_paragraph(section) + elif section.kind == QAPIDoc.Kind.MEMBER: + assert isinstance(section, QAPIDoc.ArgSection) + self.visit_member(section) + elif section.kind == QAPIDoc.Kind.FEATURE: + assert isinstance(section, QAPIDoc.ArgSection) + self.visit_feature(section) + elif section.kind in (QAPIDoc.Kind.SINCE, QAPIDoc.Kind.TODO): + # Since is handled in preamble, TODO is skipped intentionally. + pass + elif section.kind == QAPIDoc.Kind.RETURNS: + self.visit_returns(section) + elif section.kind == QAPIDoc.Kind.ERRORS: + self.visit_errors(section) + else: + assert False + + self.ensure_blank_line() + # Transmogrification core methods def visit_module(self, path: str) -> None: From patchwork Tue Mar 11 11:31:26 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011610 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 4D08DC28B2E for ; Tue, 11 Mar 2025 11:51:31 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxrq-0004Ym-1r; Tue, 11 Mar 2025 07:33:50 -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 1trxqp-0003NJ-Sw for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:52 -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 1trxqB-0006Wk-By for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:47 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692720; 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=M4SKO3wWqSCJPzWnTz3pNmJZio7IkMxcrO2K/9QFPcc=; b=RZBT5KOGBPF1HEvA3rnC8vQhQEJfHE5+MeUsCscEixNOWi57+4Z4ErTcvzz/KhNCkQDvJn sHmheV5sJ1pujsWs2+b2fulaxruxXhJr0vA2XfKWHQgxlZHqmZaJklyLL6Fk1cyaXhhfRF Q5JM8e4td/RWJWdd5jLDEDTEJ3rqXT4= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-167-HWD37upJP56UZ4UOa39N5g-1; Tue, 11 Mar 2025 07:31:58 -0400 X-MC-Unique: HWD37upJP56UZ4UOa39N5g-1 X-Mimecast-MFC-AGG-ID: HWD37upJP56UZ4UOa39N5g_1741692718 Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (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 mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 121291800258 for ; Tue, 11 Mar 2025 11:31:58 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id B656519560B9 for ; Tue, 11 Mar 2025 11:31:57 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 7EFE421E60D9; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 50/61] docs/qapidoc: add visit_entity() Date: Tue, 11 Mar 2025 12:31:26 +0100 Message-ID: <20250311113137.1277125-51-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow Finally, the core entry method for a qapi entity. Signed-off-by: John Snow Message-ID: <20250311034303.75779-54-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapidoc.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py index 83022b15ca..aaf5b6e22b 100644 --- a/docs/sphinx/qapidoc.py +++ b/docs/sphinx/qapidoc.py @@ -78,6 +78,8 @@ class Transmogrifier: + # pylint: disable=too-many-public-methods + # Field names used for different entity types: field_types = { "enum": "value", @@ -362,6 +364,25 @@ def visit_freeform(self, doc: QAPIDoc) -> None: self.add_lines(text, info) self.ensure_blank_line() + def visit_entity(self, ent: QAPISchemaDefinition) -> None: + assert ent.info + + try: + self._curr_ent = ent + + # Squish structs and unions together into an "object" directive. + meta = ent.meta + if meta in ("struct", "union"): + meta = "object" + + # This line gets credited to the start of the /definition/. + self.add_line(f".. qapi:{meta}:: {ent.name}", ent.info) + with self.indented(): + self.preamble(ent) + self.visit_sections(ent) + finally: + self._curr_ent = None + class QAPISchemaGenDepVisitor(QAPISchemaVisitor): """A QAPI schema visitor which adds Sphinx dependencies each module From patchwork Tue Mar 11 11:31:27 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011566 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 00046C282EC for ; Tue, 11 Mar 2025 11:37:23 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxqh-0003Kd-Do; Tue, 11 Mar 2025 07:32: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 1trxqb-0003GD-OX for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32: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 1trxq9-0006Xl-O7 for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:32 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692721; 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=pzFyQVQRfH5SjNpXcWSgUQALoCNim2tIphkpsxRmwME=; b=bgnsLbSgZ/pKMmeA0yf+0uzKCQIv60ra5p4jeFxGX3hJM2J46GVT89xRk3ja+UupxWvSmL P+WfeTPRK9nMAH0xKQacW2F0sHOHWHOWzX7pu5ZGfMMebwCWgs6t8yjBnxUzCwrO0aRmkb v9tI5lxhNXRzH4echD6Wjbmo4vR4OLo= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-459-uvpq259IPfmeoyaZFMrYdQ-1; Tue, 11 Mar 2025 07:31:59 -0400 X-MC-Unique: uvpq259IPfmeoyaZFMrYdQ-1 X-Mimecast-MFC-AGG-ID: uvpq259IPfmeoyaZFMrYdQ_1741692718 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (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 mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 6B04519560BB for ; Tue, 11 Mar 2025 11:31:58 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 0AA9C19560AB for ; Tue, 11 Mar 2025 11:31:58 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 82AFA21E60DA; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 51/61] docs/qapidoc: implement transmogrify() method Date: Tue, 11 Mar 2025 12:31:27 +0100 Message-ID: <20250311113137.1277125-52-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow This is the true top-level processor for the new transmogrifier; responsible both for generating the intermediate rST and then running the nested parse on that generated document to produce the final docutils tree that is then - very finally - postprocessed by sphinx for final rendering to HTML &c. Signed-off-by: John Snow Message-ID: <20250311034303.75779-55-jsnow@redhat.com> Acked-by: Markus Armbruster [Use the opportunity to move the __version__ assignment to where PEP 8 wants it] Signed-off-by: Markus Armbruster --- docs/sphinx/qapidoc.py | 49 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py index aaf5b6e22b..a0016f8853 100644 --- a/docs/sphinx/qapidoc.py +++ b/docs/sphinx/qapidoc.py @@ -2,6 +2,7 @@ # # QEMU qapidoc QAPI file parsing extension # +# Copyright (c) 2024-2025 Red Hat # Copyright (c) 2020 Linaro # # This work is licensed under the terms of the GNU GPLv2 or later. @@ -26,6 +27,8 @@ from __future__ import annotations +__version__ = "2.0" + from contextlib import contextmanager import os from pathlib import Path @@ -56,6 +59,7 @@ from sphinx import addnodes from sphinx.directives.code import CodeBlock from sphinx.errors import ExtensionError +from sphinx.util import logging from sphinx.util.docutils import switch_source_input from sphinx.util.nodes import nested_parse_with_titles @@ -74,7 +78,7 @@ from sphinx.util.typing import ExtensionMetadata -__version__ = "1.0" +logger = logging.getLogger(__name__) class Transmogrifier: @@ -95,6 +99,10 @@ def __init__(self) -> None: self._result = StringList() self.indent = 0 + @property + def result(self) -> StringList: + return self._result + @property def entity(self) -> QAPISchemaDefinition: assert self._curr_ent is not None @@ -438,7 +446,43 @@ def new_serialno(self) -> str: return "qapidoc-%d" % env.new_serialno("qapidoc") def transmogrify(self, schema: QAPISchema) -> nodes.Element: - raise NotImplementedError + logger.info("Transmogrifying QAPI to rST ...") + vis = Transmogrifier() + modules = set() + + for doc in schema.docs: + module_source = doc.info.fname + if module_source not in modules: + vis.visit_module(module_source) + modules.add(module_source) + + if doc.symbol: + ent = schema.lookup_entity(doc.symbol) + assert isinstance(ent, QAPISchemaDefinition) + vis.visit_entity(ent) + else: + vis.visit_freeform(doc) + + logger.info("Transmogrification complete.") + + contentnode = nodes.section() + content = vis.result + titles_allowed = True + + logger.info("Transmogrifier running nested parse ...") + with switch_source_input(self.state, content): + if titles_allowed: + node: nodes.Element = nodes.section() + node.document = self.state.document + nested_parse_with_titles(self.state, content, contentnode) + else: + node = nodes.paragraph() + node.document = self.state.document + self.state.nested_parse(content, 0, contentnode) + logger.info("Transmogrifier's nested parse completed.") + sys.stdout.flush() + + return contentnode def legacy(self, schema: QAPISchema) -> nodes.Element: vis = QAPISchemaGenRSTVisitor(self) @@ -572,6 +616,7 @@ def run(self) -> List[nodes.Node]: def setup(app: Sphinx) -> ExtensionMetadata: """Register qapi-doc directive with Sphinx""" + app.setup_extension("qapi_domain") app.add_config_value("qapidoc_srctree", None, "env") app.add_directive("qapi-doc", QAPIDocDirective) app.add_directive("qmp-example", QMPExample) From patchwork Tue Mar 11 11:31:28 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011593 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 72F21C28B30 for ; Tue, 11 Mar 2025 11:46:08 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxs3-0005Od-Vh; Tue, 11 Mar 2025 07:34:04 -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 1trxqf-0003KM-Fa for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:37 -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 1trxqA-0006XR-Oi for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:37 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692721; 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=yneyk3zxXR1pYod810R9d3/2TsM6Ol7FiyeAkB3xc3c=; b=QeAEE+YIUZ9VWehccXCxPCFvx5TkQM+8qcCTNWjAeV85JDK3Y1w2fcPj5QCNUVsVVK4iG4 VovIJzxBGCVdCQgm2Miy3V3m63yk/kYtibi7zgBTyAPDoaoUznAIW8LSKFB7+iJ4Nb+Y7T fXBYxkLaDmq7IQHUxZpTisS/D8gO48o= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-322-Lp61IOanMxOMP945EQgvAQ-1; Tue, 11 Mar 2025 07:31:58 -0400 X-MC-Unique: Lp61IOanMxOMP945EQgvAQ-1 X-Mimecast-MFC-AGG-ID: Lp61IOanMxOMP945EQgvAQ_1741692718 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (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 mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 1938E18001F8 for ; Tue, 11 Mar 2025 11:31:58 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id B87911944F2F for ; Tue, 11 Mar 2025 11:31:57 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 8665521E60DB; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 52/61] docs/qapidoc: process @foo into ``foo`` Date: Tue, 11 Mar 2025 12:31:28 +0100 Message-ID: <20250311113137.1277125-53-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Received-SPF: pass client-ip=170.10.133.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H2=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, T_SPF_TEMPERROR=0.01 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: John Snow Add support for the special QAPI doc syntax to process @references as ``preformatted text``. At the moment, there are no actual cross-references for individual members, so there is nothing to link against. For now, process it identically to how we did in the old qapidoc system. Signed-off-by: John Snow Message-ID: <20250311034303.75779-56-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapidoc.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py index a0016f8853..ebdf709594 100644 --- a/docs/sphinx/qapidoc.py +++ b/docs/sphinx/qapidoc.py @@ -303,6 +303,9 @@ def visit_sections(self, ent: QAPISchemaDefinition) -> None: # Add sections in source order: for section in sections: + # @var is translated to ``var``: + section.text = re.sub(r"@([\w-]+)", r"``\1``", section.text) + if section.kind == QAPIDoc.Kind.PLAIN: self.visit_paragraph(section) elif section.kind == QAPIDoc.Kind.MEMBER: From patchwork Tue Mar 11 11:31:29 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011620 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 889DBC282EC for ; Tue, 11 Mar 2025 11:53:07 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxrA-0003Yl-0M; Tue, 11 Mar 2025 07:33:09 -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 1trxql-0003MF-KR for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:49 -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 1trxqA-0006Ws-Is for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:43 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692720; 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=wdCg+UoySTQdVH0vu4je4tNL8ddS1AXyxvzLsqmoOZw=; b=ap4GuyYaxb55OYUR3rAGxXCCpED2m0sg/q7h9MTKuu7ppgnKEuLD1LP+Bgts1H39TYN8zz Ve+uTgWYDaiNXSnabi8Owx2BW4vXR48zEWBLmNF6Uu5jdVt6mQra/GJM5gkh7BXw6Yp9oJ f1HbN7vh6NwOPLFzYfhqVSLx1odllpY= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-157-65dVc_BdPxSCSb8RGiXZfQ-1; Tue, 11 Mar 2025 07:31:58 -0400 X-MC-Unique: 65dVc_BdPxSCSb8RGiXZfQ-1 X-Mimecast-MFC-AGG-ID: 65dVc_BdPxSCSb8RGiXZfQ_1741692718 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (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 mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id D643B195608B for ; Tue, 11 Mar 2025 11:31:57 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 7158C1828A99 for ; Tue, 11 Mar 2025 11:31:57 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 8A28A21E60DE; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 53/61] docs/qapidoc: add intermediate output debugger Date: Tue, 11 Mar 2025 12:31:29 +0100 Message-ID: <20250311113137.1277125-54-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow Add debugging output for the qapidoc transmogrifier - setting DEBUG=1 will produce .ir files (one for each qapidoc directive) that write the generated rst file to disk to allow for easy debugging and verification of the generated document. Signed-off-by: John Snow Message-ID: <20250311034303.75779-57-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapidoc.py | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py index ebdf709594..8ddebf73f2 100644 --- a/docs/sphinx/qapidoc.py +++ b/docs/sphinx/qapidoc.py @@ -37,7 +37,7 @@ from typing import TYPE_CHECKING from docutils import nodes -from docutils.parsers.rst import Directive, directives +from docutils.parsers.rst import directives from docutils.statemachine import StringList from qapi.error import QAPIError from qapi.parser import QAPIDoc @@ -60,7 +60,7 @@ from sphinx.directives.code import CodeBlock from sphinx.errors import ExtensionError from sphinx.util import logging -from sphinx.util.docutils import switch_source_input +from sphinx.util.docutils import SphinxDirective, switch_source_input from sphinx.util.nodes import nested_parse_with_titles @@ -414,7 +414,7 @@ def visit_module(self, name: str) -> None: super().visit_module(name) -class NestedDirective(Directive): +class NestedDirective(SphinxDirective): def run(self) -> Sequence[nodes.Node]: raise NotImplementedError @@ -483,10 +483,43 @@ def transmogrify(self, schema: QAPISchema) -> nodes.Element: node.document = self.state.document self.state.nested_parse(content, 0, contentnode) logger.info("Transmogrifier's nested parse completed.") - sys.stdout.flush() + if self.env.app.verbosity >= 2 or os.environ.get("DEBUG"): + argname = "_".join(Path(self.arguments[0]).parts) + name = Path(argname).stem + ".ir" + self.write_intermediate(content, name) + + sys.stdout.flush() return contentnode + def write_intermediate(self, content: StringList, filename: str) -> None: + logger.info( + "writing intermediate rST for '%s' to '%s'", + self.arguments[0], + filename, + ) + + srctree = Path(self.env.app.config.qapidoc_srctree).resolve() + outlines = [] + lcol_width = 0 + + for i, line in enumerate(content): + src, lineno = content.info(i) + srcpath = Path(src).resolve() + srcpath = srcpath.relative_to(srctree) + + lcol = f"{srcpath}:{lineno:04d}" + lcol_width = max(lcol_width, len(lcol)) + outlines.append((lcol, line)) + + with open(filename, "w", encoding="UTF-8") as outfile: + for lcol, rcol in outlines: + outfile.write(lcol.rjust(lcol_width)) + outfile.write(" |") + if rcol: + outfile.write(f" {rcol}") + outfile.write("\n") + def legacy(self, schema: QAPISchema) -> nodes.Element: vis = QAPISchemaGenRSTVisitor(self) vis.visit_begin(schema) From patchwork Tue Mar 11 11:31:30 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011589 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 63576C282EC for ; Tue, 11 Mar 2025 11:45:34 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxsa-0007jO-Ix; Tue, 11 Mar 2025 07:34:36 -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 1trxr0-0003PJ-Gu for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:33:02 -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 1trxqD-0006Yu-18 for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:57 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692725; 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=PZbNEhutn+nEOuSiSUhkofv97rwjm/SeOq61uAc+ny4=; b=HMHFE5VYq4AohQZ5oiWZyDpt3HAxwHKpzsTm67y84s++fdoF5HQsaicstx+5hvxaK33qlu 9TRXNxvmydMFZXQjTlRxcqix7zsyMEEq67BhgJp/5mmHJYOqRWA+M6TkWxm3pM1pp3mpOU +8NFeUouMCtu1+TYykG3YVCOLHjuhgk= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-323-jp4M-S_xOlqnFO7GzFZ9gw-1; Tue, 11 Mar 2025 07:32:04 -0400 X-MC-Unique: jp4M-S_xOlqnFO7GzFZ9gw-1 X-Mimecast-MFC-AGG-ID: jp4M-S_xOlqnFO7GzFZ9gw_1741692723 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (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 mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 6041C19560BB for ; Tue, 11 Mar 2025 11:32:03 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 7552F30001A2 for ; Tue, 11 Mar 2025 11:32:02 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 8DF8721E60DF; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 54/61] docs/qapidoc: Add "the members of" pointers Date: Tue, 11 Mar 2025 12:31:30 +0100 Message-ID: <20250311113137.1277125-55-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -4 X-Spam_score: -0.5 X-Spam_bar: / X-Spam_report: (-0.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, URIBL_SBL=1.623 autolearn=no 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: John Snow Add "the members of ..." pointers to Members and Arguments lists where appropriate, with clickable cross-references - so it's a slight improvement over the old system :) This patch is meant to be a temporary solution until we can review and merge the inliner. The implementation of this patch is a little bit of a hack: Sphinx is not designed to allow you to mix fields of different "type"; i.e. mixing member descriptions and free-form text under the same heading. To accomplish this with a minimum of hackery, we technically document a "dummy field" and then just strip off the documentation for that dummy field in a post-processing step. We use the "q_dummy" variable for this purpose, then strip it back out before final processing. If this processing step should fail, you'll see warnings for a bad cross-reference. (So if you don't see any, it must be working!) Signed-off-by: John Snow Message-ID: <20250311034303.75779-58-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/sphinx/qapi_domain.py | 22 +++++++++++++-- docs/sphinx/qapidoc.py | 58 +++++++++++++++++++++++++++++++++++++- 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py index ca3f3a7e2d..7ff618d8cd 100644 --- a/docs/sphinx/qapi_domain.py +++ b/docs/sphinx/qapi_domain.py @@ -433,6 +433,24 @@ def transform_content(self, content_node: addnodes.desc_content) -> None: self._validate_field(field) +class SpecialTypedField(CompatTypedField): + def make_field(self, *args: Any, **kwargs: Any) -> nodes.field: + ret = super().make_field(*args, **kwargs) + + # Look for the characteristic " -- " text node that Sphinx + # inserts for each TypedField entry ... + for node in ret.traverse(lambda n: str(n) == " -- "): + par = node.parent + if par.children[0].astext() != "q_dummy": + continue + + # If the first node's text is q_dummy, this is a dummy + # field we want to strip down to just its contents. + del par.children[:-1] + + return ret + + class QAPICommand(QAPIObject): """Description of a QAPI Command.""" @@ -440,7 +458,7 @@ class QAPICommand(QAPIObject): doc_field_types.extend( [ # :arg TypeName ArgName: descr - CompatTypedField( + SpecialTypedField( "argument", label=_("Arguments"), names=("arg",), @@ -508,7 +526,7 @@ class QAPIObjectWithMembers(QAPIObject): doc_field_types.extend( [ # :member type name: descr - CompatTypedField( + SpecialTypedField( "member", label=_("Members"), names=("memb",), diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py index 8ddebf73f2..a2d6f648a2 100644 --- a/docs/sphinx/qapidoc.py +++ b/docs/sphinx/qapidoc.py @@ -47,8 +47,10 @@ QAPISchemaCommand, QAPISchemaDefinition, QAPISchemaEnumMember, + QAPISchemaEvent, QAPISchemaFeature, QAPISchemaMember, + QAPISchemaObjectType, QAPISchemaObjectTypeMember, QAPISchemaType, QAPISchemaVisitor, @@ -298,11 +300,61 @@ def preamble(self, ent: QAPISchemaDefinition) -> None: self.ensure_blank_line() + def _insert_member_pointer(self, ent: QAPISchemaDefinition) -> None: + + def _get_target( + ent: QAPISchemaDefinition, + ) -> Optional[QAPISchemaDefinition]: + if isinstance(ent, (QAPISchemaCommand, QAPISchemaEvent)): + return ent.arg_type + if isinstance(ent, QAPISchemaObjectType): + return ent.base + return None + + target = _get_target(ent) + if target is not None and not target.is_implicit(): + assert ent.info + self.add_field( + self.member_field_type, + "q_dummy", + f"The members of :qapi:type:`{target.name}`.", + ent.info, + "q_dummy", + ) + + if isinstance(ent, QAPISchemaObjectType) and ent.branches is not None: + for variant in ent.branches.variants: + if variant.type.name == "q_empty": + continue + assert ent.info + self.add_field( + self.member_field_type, + "q_dummy", + f" When ``{ent.branches.tag_member.name}`` is " + f"``{variant.name}``: " + f"The members of :qapi:type:`{variant.type.name}`.", + ent.info, + "q_dummy", + ) + def visit_sections(self, ent: QAPISchemaDefinition) -> None: sections = ent.doc.all_sections if ent.doc else [] + # Determine the index location at which we should generate + # documentation for "The members of ..." pointers. This should + # go at the end of the members section(s) if any. Note that + # index 0 is assumed to be a plain intro section, even if it is + # empty; and that a members section if present will always + # immediately follow the opening PLAIN section. + gen_index = 1 + if len(sections) > 1: + while sections[gen_index].kind == QAPIDoc.Kind.MEMBER: + gen_index += 1 + if gen_index >= len(sections): + break + # Add sections in source order: - for section in sections: + for i, section in enumerate(sections): # @var is translated to ``var``: section.text = re.sub(r"@([\w-]+)", r"``\1``", section.text) @@ -324,6 +376,10 @@ def visit_sections(self, ent: QAPISchemaDefinition) -> None: else: assert False + # Generate "The members of ..." entries if necessary: + if i == gen_index - 1: + self._insert_member_pointer(ent) + self.ensure_blank_line() # Transmogrification core methods From patchwork Tue Mar 11 11:31:31 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011621 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 CDA5EC28B2E for ; Tue, 11 Mar 2025 11:53:12 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxrH-0003e7-Ev; Tue, 11 Mar 2025 07:33:15 -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 1trxqa-0003FR-9n for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32: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 1trxqA-0006YN-CA for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:31 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692724; 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=QWkuDCPzbZFxRLHuq8fODnWk4KA/4K4c8PccPKnfj6E=; b=Ie56fKIVQIy8F3XK4Nhv3W9dtGiWgcO5ZvX1PW4Y9Hj126+o8iM2CZF99mjkjifP4t8vGz sregKK+GVltuwA3we+OK1OTd1aRPkpzaDHKSZ/IHfAb3nG6mPvJl8aEsfXUAwCLNl+UkrQ trHhHCmWi06GoQEIaCN+02N8UDnJgyw= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-591-vAk-3CYoNlCr78h1TLdRLg-1; Tue, 11 Mar 2025 07:32:03 -0400 X-MC-Unique: vAk-3CYoNlCr78h1TLdRLg-1 X-Mimecast-MFC-AGG-ID: vAk-3CYoNlCr78h1TLdRLg_1741692722 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (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 mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 7B0751800258 for ; Tue, 11 Mar 2025 11:32:02 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 21CA81828A96 for ; Tue, 11 Mar 2025 11:32:02 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 919A121E60E0; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 55/61] docs/qapidoc: generate entries for undocumented members Date: Tue, 11 Mar 2025 12:31:31 +0100 Message-ID: <20250311113137.1277125-56-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow Presently, we never have any empty text entries for members. The next patch will explicitly generate such sections, so enable support for it in advance. The parser will generate placeholder sections to indicate undocumented members, but it's the qapidoc generator that's responsible for deciding what to do with that stub section. Signed-off-by: John Snow Message-ID: <20250311034303.75779-59-jsnow@redhat.com> Acked-by: Markus Armbruster [Tweak the stub section text] Signed-off-by: Markus Armbruster --- docs/sphinx/qapidoc.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py index a2d6f648a2..432fef04b0 100644 --- a/docs/sphinx/qapidoc.py +++ b/docs/sphinx/qapidoc.py @@ -233,11 +233,12 @@ def visit_member(self, section: QAPIDoc.ArgSection) -> None: # TODO: features for members (documented at entity-level, # but sometimes defined per-member. Should we add such # information to member descriptions when we can?) - assert section.text and section.member + assert section.member self.generate_field( self.member_field_type, section.member, - section.text, + # TODO drop fallbacks when undocumented members are outlawed + section.text if section.text else "Not documented", section.info, ) From patchwork Tue Mar 11 11:31:32 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011559 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 D0CF3C282EC for ; Tue, 11 Mar 2025 11:36:42 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxsG-0005qi-7N; Tue, 11 Mar 2025 07:34:16 -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 1trxqd-0003IS-6l for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:35 -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 1trxq9-0006YI-Oe for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:34 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692724; 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=oXRhyny7T9Bf4bTFkXqMBiMcYNuJGRxrIwHw5pJ/Gmk=; b=UEP1f2gz/WYwZKyltUjKWp0IqNsTl0zgZYfpmhu5UeLHTaAdoq0HdvAlcnLMrE0133DFVU z7SxFwhDX1aBaFRxX6VtsYfNZIGWL0sBAO5WVpaEmeJc7VMOsqPDyVT+fbYxQyGkJXblvM PprwSmiaxc+Pq3l4sZfnO3WFIDNjuUo= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-26-LtZw2NtGN7eZC47HlWu4Ew-1; Tue, 11 Mar 2025 07:32:03 -0400 X-MC-Unique: LtZw2NtGN7eZC47HlWu4Ew-1 X-Mimecast-MFC-AGG-ID: LtZw2NtGN7eZC47HlWu4Ew_1741692722 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (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 mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 79F08180AF57 for ; Tue, 11 Mar 2025 11:32:02 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 21C891828A95 for ; Tue, 11 Mar 2025 11:32:02 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 9540E21E60E2; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 56/61] qapi/parser: add undocumented stub members to all_sections Date: Tue, 11 Mar 2025 12:31:32 +0100 Message-ID: <20250311113137.1277125-57-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass client-ip=170.10.133.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, T_SPF_TEMPERROR=0.01 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: John Snow Parser and doc generator cooperate on generating stub documentation for undocumented members. The parser makes up an ArgSection with an empty description, and the doc generator makes up a description. Right now, the made-up ArgSections go into doc.args. However, the new doc generator uses .all_sections, not .args. So put them into .all_sections, too. Insert them right after existing 'member' sections. If there are none, insert directly after the leading section. Doesn't affect the old generator, because that one doesn't use .all_sections. Signed-off-by: John Snow Message-ID: <20250311034303.75779-60-jsnow@redhat.com> Reviewed-by: Markus Armbruster [Commit message rewritten] Signed-off-by: Markus Armbruster --- scripts/qapi/parser.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py index 11c11bb09e..949d9e8bff 100644 --- a/scripts/qapi/parser.py +++ b/scripts/qapi/parser.py @@ -789,8 +789,23 @@ def connect_member(self, member: 'QAPISchemaMember') -> None: raise QAPISemError(member.info, "%s '%s' lacks documentation" % (member.role, member.name)) - self.args[member.name] = QAPIDoc.ArgSection( + # Insert stub documentation section for missing member docs. + # TODO: drop when undocumented members are outlawed + + section = QAPIDoc.ArgSection( self.info, QAPIDoc.Kind.MEMBER, member.name) + self.args[member.name] = section + + # Determine where to insert stub doc - it should go at the + # end of the members section(s), if any. Note that index 0 + # is assumed to be an untagged intro section, even if it is + # empty. + index = 1 + if len(self.all_sections) > 1: + while self.all_sections[index].kind == QAPIDoc.Kind.MEMBER: + index += 1 + self.all_sections.insert(index, section) + self.args[member.name].connect(member) def connect_feature(self, feature: 'QAPISchemaFeature') -> None: From patchwork Tue Mar 11 11:31:33 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011619 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 A4EABC28B30 for ; Tue, 11 Mar 2025 11:52:50 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxrI-0003f1-2H; Tue, 11 Mar 2025 07:33:16 -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 1trxqf-0003Kc-VF for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:39 -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 1trxqA-0006YF-VO for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:37 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692724; 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=flO+mLezwqffdgGJp6T3uxQumA1quEGBxSePL44H6K8=; b=aDTfJ3KyVYgKThn8TJ/oeKELoTl6Xyd9pSjXT1dyrxxmQjZ3a8qxFrqTXPryzyd5iliek3 JtC54XR1ozECuZ1Pv6smxMH7+bOHq2E8KvKrCu9IPYceb+fOIJ0Qp33nE6YLijlxpLteW1 dOsg8EBvGNCDtUr90FCgI3D0HP8qw0w= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-145-815TWPPoNjCDSsTWSIMtJQ-1; Tue, 11 Mar 2025 07:32:03 -0400 X-MC-Unique: 815TWPPoNjCDSsTWSIMtJQ-1 X-Mimecast-MFC-AGG-ID: 815TWPPoNjCDSsTWSIMtJQ_1741692722 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 5323D180025A for ; Tue, 11 Mar 2025 11:32:02 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C32601800268 for ; Tue, 11 Mar 2025 11:32:01 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 98F1A21E60E3; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 57/61] docs: disambiguate cross-references Date: Tue, 11 Mar 2025 12:31:33 +0100 Message-ID: <20250311113137.1277125-58-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, T_SPF_TEMPERROR=0.01 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: John Snow The next patch will engage the qapidoc transmogrifier, which creates a lot of cross-reference targets. Some of the existing targets ("migration", "qom", "replay") will become ambiguous as a result. Nail them down more explicitly to prevent ambiguous cross-reference warnings. Signed-off-by: John Snow Message-ID: <20250311034303.75779-61-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/devel/codebase.rst | 6 +++--- docs/glossary.rst | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/devel/codebase.rst b/docs/devel/codebase.rst index 4039875ee0..1b09953197 100644 --- a/docs/devel/codebase.rst +++ b/docs/devel/codebase.rst @@ -23,7 +23,7 @@ Some of the main QEMU subsystems are: - `Devices` & Board models - `Documentation ` - `GDB support` -- `Migration` +- :ref:`Migration` - `Monitor` - :ref:`QOM (QEMU Object Model)` - `System mode` @@ -112,7 +112,7 @@ yet, so sometimes the source code is all you have. * `libdecnumber `_: Import of gcc library, used to implement decimal number arithmetic. * `migration `__: - `Migration framework `. + :ref:`Migration framework `. * `monitor `_: `Monitor ` implementation (HMP & QMP). * `nbd `_: @@ -193,7 +193,7 @@ yet, so sometimes the source code is all you have. - `lcitool `_: Generate dockerfiles for CI containers. - `migration `_: - Test scripts and data for `Migration framework `. + Test scripts and data for :ref:`Migration framework `. - `multiboot `_: Test multiboot functionality for x86_64/i386. - `qapi-schema `_: diff --git a/docs/glossary.rst b/docs/glossary.rst index 693d9855dd..4fa044bfb6 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -120,7 +120,7 @@ Migration --------- QEMU can save and restore the execution of a virtual machine between different -host systems. This is provided by the `Migration framework`. +host systems. This is provided by the :ref:`Migration framework`. NBD --- @@ -212,14 +212,14 @@ machine emulator and virtualizer. QOM --- -`QEMU Object Model ` is an object oriented API used to define various -devices and hardware in the QEMU codebase. +:ref:`QEMU Object Model ` is an object oriented API used to define +various devices and hardware in the QEMU codebase. Record/replay ------------- -`Record/replay ` is a feature of QEMU allowing to have a deterministic -and reproducible execution of a virtual machine. +:ref:`Record/replay ` is a feature of QEMU allowing to have a +deterministic and reproducible execution of a virtual machine. Rust ---- From patchwork Tue Mar 11 11:31:34 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011570 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 4573EC282EC for ; Tue, 11 Mar 2025 11:39:11 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxsh-0008Bx-1z; Tue, 11 Mar 2025 07:34:44 -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 1trxsE-0005oG-Ed for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:34:14 -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 1trxs6-0006v8-PS for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:34:12 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692844; 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=4+Z+s4Wlk9e7DaBkaSE8WMgOr8VXb4ioRLRxiSoSozA=; b=HKOKIdcvQN1Jds3cbgXVCEy659/nLxzyAlN/GM8pW8cmF4AAdOBxIZnd/lXHwPEFv27wQj ov3KTL4AkE5ZCA3bHHW6LDdomjYVzfzP+k0W2vIkIzzbp1rppkFc+wcpJ5ulFoEVhIPKRw 4758j/lPQZ/terjyxKFwrwFRqQUtDGo= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-592-N_IogstGNsaulcYw-5nQlQ-1; Tue, 11 Mar 2025 07:32:03 -0400 X-MC-Unique: N_IogstGNsaulcYw-5nQlQ-1 X-Mimecast-MFC-AGG-ID: N_IogstGNsaulcYw-5nQlQ_1741692722 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (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 mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C32DB18001E2 for ; Tue, 11 Mar 2025 11:32:02 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 747CD19560AB for ; Tue, 11 Mar 2025 11:32:02 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 9CA0B21E60E4; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 58/61] docs: enable qapidoc transmogrifier for QEMU QMP Reference Date: Tue, 11 Mar 2025 12:31:34 +0100 Message-ID: <20250311113137.1277125-59-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 Received-SPF: pass client-ip=170.10.133.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H2=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow We are not enabling the transmogrifier for QSD or QGA yet because we don't (yet) have a way to create separate indices, and all of the definitions will bleed together, which isn't so nice. For now, QMP is better than nothing at all! Signed-off-by: John Snow Message-ID: <20250311034303.75779-62-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/interop/qemu-qmp-ref.rst | 1 + qapi/qapi-schema.json | 2 ++ 2 files changed, 3 insertions(+) diff --git a/docs/interop/qemu-qmp-ref.rst b/docs/interop/qemu-qmp-ref.rst index f94614a0b2..e95eeac45e 100644 --- a/docs/interop/qemu-qmp-ref.rst +++ b/docs/interop/qemu-qmp-ref.rst @@ -7,3 +7,4 @@ QEMU QMP Reference Manual :depth: 3 .. qapi-doc:: qapi/qapi-schema.json + :transmogrify: diff --git a/qapi/qapi-schema.json b/qapi/qapi-schema.json index 2877aff73d..4475e81cc3 100644 --- a/qapi/qapi-schema.json +++ b/qapi/qapi-schema.json @@ -5,6 +5,8 @@ # # This document describes all commands currently supported by QMP. # +# For locating a particular item, please see the `qapi-index`. +# # Most of the time their usage is exactly the same as in the user # Monitor, this means that any other document which also describe # commands (the manpage, QEMU's manual, etc) can and should be From patchwork Tue Mar 11 11:31:35 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011608 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 D13D1C28B2E for ; Tue, 11 Mar 2025 11:51:20 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxsq-0000IZ-13; Tue, 11 Mar 2025 07:34:52 -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 1trxr3-0003SP-Jv for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:33:02 -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 1trxqE-0006YL-60 for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:59 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692724; 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=8eCWReU6bUM5pOJMVwkYiN6cPZRJruZljXLIq66RMAc=; b=IgAyWubopLFul8qt0bAh0bT4WSfTKfofZbc9xBC/4W3eEIkSniJg4oNmtNXtn6Rkd+M7uq +mJkqqszGZXf/5tEFUCfIhXe+qbaPt43pk+L4DQW/QwnUMUpo50TLtr0HExcsTvo7V3w6r q/q+W2jMk5EQNH8gzkzvvwPo578Vjtg= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-256-ugtc8FH-Nqq8n5zF_jP2RA-1; Tue, 11 Mar 2025 07:32:03 -0400 X-MC-Unique: ugtc8FH-Nqq8n5zF_jP2RA-1 X-Mimecast-MFC-AGG-ID: ugtc8FH-Nqq8n5zF_jP2RA_1741692722 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (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 mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C4E6A19560B0 for ; Tue, 11 Mar 2025 11:32:02 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 228C21955BCB for ; Tue, 11 Mar 2025 11:32:02 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id A0A6021E60E5; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 59/61] docs: add qapi-domain syntax documentation Date: Tue, 11 Mar 2025 12:31:35 +0100 Message-ID: <20250311113137.1277125-60-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Received-SPF: pass client-ip=170.10.133.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow Who documents the documentation? Me, I guess. Signed-off-by: John Snow Message-ID: <20250311034303.75779-63-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- docs/devel/index-build.rst | 1 + docs/devel/qapi-domain.rst | 670 +++++++++++++++++++++++++++++++++++++ 2 files changed, 671 insertions(+) create mode 100644 docs/devel/qapi-domain.rst diff --git a/docs/devel/index-build.rst b/docs/devel/index-build.rst index 0745c81a26..3f3cb21b9b 100644 --- a/docs/devel/index-build.rst +++ b/docs/devel/index-build.rst @@ -12,4 +12,5 @@ some of the basics if you are adding new files and targets to the build. kconfig docs qapi-code-gen + qapi-domain control-flow-integrity diff --git a/docs/devel/qapi-domain.rst b/docs/devel/qapi-domain.rst new file mode 100644 index 0000000000..1475870ca6 --- /dev/null +++ b/docs/devel/qapi-domain.rst @@ -0,0 +1,670 @@ +====================== +The Sphinx QAPI Domain +====================== + +An extension to the `rST syntax +`_ +in Sphinx is provided by the QAPI Domain, located in +``docs/sphinx/qapi_domain.py``. This extension is analogous to the +`Python Domain +`_ +included with Sphinx, but provides special directives and roles +speciically for annotating and documenting QAPI definitions +specifically. + +A `Domain +`_ +provides a set of special rST directives and cross-referencing roles to +Sphinx for understanding rST markup written to document a specific +language. By itself, this QAPI extension is only sufficient to parse rST +markup written by hand; the `autodoc +`_ +functionality is provided elsewhere, in ``docs/sphinx/qapidoc.py``, by +the "Transmogrifier". + +It is not expected that any developer nor documentation writer would +never need to write *nor* read these special rST forms. However, in the +event that something needs to be debugged, knowing the syntax of the +domain is quite handy. This reference may also be useful as a guide for +understanding the QAPI Domain extension code itself. Although most of +these forms will not be needed for documentation writing purposes, +understanding the cross-referencing syntax *will* be helpful when +writing rST documentation elsewhere, or for enriching the body of +QAPIDoc blocks themselves. + + +Concepts +======== + +The QAPI Domain itself provides no mechanisms for reading the QAPI +Schema or generating documentation from code that exists. It is merely +the rST syntax used to describe things. For instance, the Sphinx Python +domain adds syntax like ``:py:func:`` for describing Python functions in +documentation, but it's the autodoc module that is responsible for +reading python code and generating such syntax. QAPI is analagous here: +qapidoc.py is responsible for reading the QAPI Schema and generating rST +syntax, and qapi_domain.py is responsible for translating that special +syntax and providing APIs for Sphinx internals. + +In other words: + +qapi_domain.py adds syntax like ``.. qapi:command::`` to Sphinx, and +qapidoc.py transforms the documentation in ``qapi/*.json`` into rST +using directives defined by the domain. + +Or even shorter: + +``:py:`` is to ``:qapi:`` as *autodoc* is to *qapidoc*. + + +Info Field Lists +================ + +`Field lists +`_ +are a standard syntax in reStructuredText. Sphinx `extends that syntax +`_ +to give certain field list entries special meaning and parsing to, for +example, add cross-references. The QAPI Domain takes advantage of this +field list extension to document things like Arguments, Members, Values, +and so on. + +The special parsing and handling of info field lists in Sphinx is provided by +three main classes; Field, GroupedField, and TypedField. The behavior +and formatting for each configured field list entry in the domain +changes depending on which class is used. + +Field: + * Creates an ungrouped field: i.e., each entry will create its own + section and they will not be combined. + * May *optionally* support an argument. + * May apply cross-reference roles to *either* the argument *or* the + content body, both, or neither. + +This is used primarily for entries which are not expected to be +repeated, i.e., items that may only show up at most once. The QAPI +domain uses this class for "Errors" section. + +GroupedField: + * Creates a grouped field: i.e. multiple adjacent entries will be + merged into one section, and the content will form a bulleted list. + * *Must* take an argument. + * May optionally apply a cross-reference role to the argument, but not + the body. + * Can be configured to remove the bulleted list if there is only a + single entry. + * All items will be generated with the form: "argument -- body" + +This is used for entries which are expected to be repeated, but aren't +expected to have two arguments, i.e. types without names, or names +without types. The QAPI domain uses this class for features, returns, +and enum values. + +TypedField: + * Creates a grouped, typed field. Multiple adjacent entres will be + merged into one section, and the content will form a bulleted list. + * *Must* take at least one argument, but supports up to two - + nominally, a name and a type. + * May optionally apply a cross-reference role to the type or the name + argument, but not the body. + * Can be configured to remove the bulleted list if there is only a + single entry. + * All items will be generated with the form "name (type) -- body" + +This is used for entries that are expected to be repeated and will have +a name, a type, and a description. The QAPI domain uses this class for +arguments, alternatives, and members. Wherever type names are referenced +below, They must be a valid, documented type that will be +cross-referenced in the HTML output; or one of the built-in JSON types +(string, number, int, boolean, null, value, q_empty). + + +``:feat:`` +---------- + +Document a feature attached to a QAPI definition. + +:availability: This field list is available in the body of Command, + Event, Enum, Object and Alternate directives. +:syntax: ``:feat name: Lorem ipsum, dolor sit amet...`` +:type: `sphinx.util.docfields.GroupedField + `_ + +Example:: + + .. qapi:object:: BlockdevOptionsVirtioBlkVhostVdpa + :since: 7.2 + :ifcond: CONFIG_BLKIO + + Driver specific block device options for the virtio-blk-vhost-vdpa + backend. + + :memb string path: path to the vhost-vdpa character device. + :feat fdset: Member ``path`` supports the special "/dev/fdset/N" path + (since 8.1) + + +``:arg:`` +--------- + +Document an argument to a QAPI command. + +:availability: This field list is only available in the body of the + Command directive. +:syntax: ``:arg type name: description`` +:type: `sphinx.util.docfields.TypedField + `_ + + +Example:: + + .. qapi:command:: job-pause + :since: 3.0 + + Pause an active job. + + This command returns immediately after marking the active job for + pausing. Pausing an already paused job is an error. + + The job will pause as soon as possible, which means transitioning + into the PAUSED state if it was RUNNING, or into STANDBY if it was + READY. The corresponding JOB_STATUS_CHANGE event will be emitted. + + Cancelling a paused job automatically resumes it. + + :arg string id: The job identifier. + + +``:error:`` +----------- + +Document the error condition(s) of a QAPI command. + +:availability: This field list is only available in the body of the + Command directive. +:syntax: ``:error: Lorem ipsum dolor sit amet ...`` +:type: `sphinx.util.docfields.Field + `_ + +The format of the :errors: field list description is free-form rST. The +alternative spelling ":errors:" is also permitted, but strictly +analogous. + +Example:: + + .. qapi:command:: block-job-set-speed + :since: 1.1 + + Set maximum speed for a background block operation. + + This command can only be issued when there is an active block job. + + Throttling can be disabled by setting the speed to 0. + + :arg string device: The job identifier. This used to be a device + name (hence the name of the parameter), but since QEMU 2.7 it + can have other values. + :arg int speed: the maximum speed, in bytes per second, or 0 for + unlimited. Defaults to 0. + :error: + - If no background operation is active on this device, + DeviceNotActive + + +``:return:`` +------------- + +Document the return type(s) and value(s) of a QAPI command. + +:availability: This field list is only available in the body of the + Command directive. +:syntax: ``:return type: Lorem ipsum dolor sit amet ...`` +:type: `sphinx.util.docfields.GroupedField + `_ + + +Example:: + + .. qapi:command:: query-replay + :since: 5.2 + + Retrieve the record/replay information. It includes current + instruction count which may be used for ``replay-break`` and + ``replay-seek`` commands. + + :return ReplayInfo: record/replay information. + + .. qmp-example:: + + -> { "execute": "query-replay" } + <- { "return": { + "mode": "play", "filename": "log.rr", "icount": 220414 } + } + + +``:value:`` +----------- + +Document a possible value for a QAPI enum. + +:availability: This field list is only available in the body of the Enum + directive. +:syntax: ``:value name: Lorem ipsum, dolor sit amet ...`` +:type: `sphinx.util.docfields.GroupedField + `_ + +Example:: + + .. qapi:enum:: QapiErrorClass + :since: 1.2 + + QEMU error classes + + :value GenericError: this is used for errors that don't require a specific + error class. This should be the default case for most errors + :value CommandNotFound: the requested command has not been found + :value DeviceNotActive: a device has failed to be become active + :value DeviceNotFound: the requested device has not been found + :value KVMMissingCap: the requested operation can't be fulfilled because a + required KVM capability is missing + + +``:alt:`` +------------ + +Document a possible branch for a QAPI alternate. + +:availability: This field list is only available in the body of the + Alternate directive. +:syntax: ``:alt type name: Lorem ipsum, dolor sit amet ...`` +:type: `sphinx.util.docfields.TypedField + `_ + +As a limitation of Sphinx, we must document the "name" of the branch in +addition to the type, even though this information is not visible on the +wire in the QMP protocol format. This limitation *may* be lifted at a +future date. + +Example:: + + .. qapi:alternate:: StrOrNull + :since: 2.10 + + This is a string value or the explicit lack of a string (null + pointer in C). Intended for cases when 'optional absent' already + has a different meaning. + + :alt string s: the string value + :alt null n: no string value + + +``:memb:`` +---------- + +Document a member of an Event or Object. + +:availability: This field list is available in the body of Event or + Object directives. +:syntax: ``:memb type name: Lorem ipsum, dolor sit amet ...`` +:type: `sphinx.util.docfields.TypedField + `_ + +This is fundamentally the same as ``:arg:`` and ``:alt:``, but uses the +"Members" phrasing for Events and Objects (Structs and Unions). + +Example:: + + .. qapi:event:: JOB_STATUS_CHANGE + :since: 3.0 + + Emitted when a job transitions to a different status. + + :memb string id: The job identifier + :memb JobStatus status: The new job status + + +Arbitrary field lists +--------------------- + +Other field list names, while valid rST syntax, are prohibited inside of +QAPI directives to help prevent accidental misspellings of info field +list names. If you want to add a new arbitrary "non-value-added" field +list to QAPI documentation, you must add the field name to the allow +list in ``docs/conf.py`` + +For example:: + + qapi_allowed_fields = { + "see also", + } + +Will allow you to add arbitrary field lists in QAPI directives:: + + .. qapi:command:: x-fake-command + + :see also: Lorem ipsum, dolor sit amet ... + + +Cross-references +================ + +Cross-reference `roles +`_ +in the QAPI domain are modeled closely after the `Python +cross-referencing syntax +`_. + +QAPI definitions can be referenced using the standard `any +`_ +role cross-reference syntax, such as with ```query-blockstats```. In +the event that disambiguation is needed, cross-references can also be +written using a number of explicit cross-reference roles: + +* ``:qapi:mod:`block-core``` -- Reference a QAPI module. The link will + take you to the beginning of that section in the documentation. +* ``:qapi:cmd:`query-block``` -- Reference a QAPI command. +* ``:qapi:event:`JOB_STATUS_CHANGE``` -- Reference a QAPI event. +* ``:qapi:enum:`QapiErrorClass``` -- Reference a QAPI enum. +* ``:qapi:obj:`BlockdevOptionsVirtioBlkVhostVdpa`` -- Reference a QAPI + object (struct or union) +* ``:qapi:alt:`StrOrNull``` -- Reference a QAPI alternate. +* ``:qapi:type:`BlockDirtyInfo``` -- Reference *any* QAPI type; this + excludes modules, commands, and events. +* ``:qapi:any:`block-job-set-speed``` -- Reference absolutely any QAPI entity. + +Type arguments in info field lists are converted into references as if +you had used the ``:qapi:type:`` role. All of the special syntax below +applies to both info field lists and standalone explicit +cross-references. + + +Type decorations +---------------- + +Type names in references can be surrounded by brackets, like +``[typename]``, to indicate an array of that type. The cross-reference +will apply only to the type name between the brackets. For example; +``:qapi:type:`[Qcow2BitmapInfoFlags]``` renders to: +:qapi:type:`[Qcow2BitmapInfoFlags]` + +To indicate an optional argument/member in a field list, the type name +can be suffixed with ``?``. The cross-reference will be transformed to +"type, Optional" with the link applying only to the type name. For +example; ``:qapi:type:`BitmapSyncMode?``` renders to: +:qapi:type:`BitmapSyncMode?` + + +Namespaces +---------- + +Mimicking the `Python domain target specification syntax +`_, +QAPI allows you to specify the fully qualified path for a data +type. QAPI enforces globally unique names, so it's unlikely you'll need +this specific feature, but it may be extended in the near future to +allow referencing identically named commands and data types from +different utilities; i.e. QEMU Storage Daemon vs QMP. + +* A module can be explicitly provided; + ``:qapi:type:`block-core.BitmapSyncMode``` will render to: + :qapi:type:`block-core.BitmapSyncMode` +* If you don't want to display the "fully qualified" name, it can be + prefixed with a tilde; ``:qapi:type:`~block-core.BitmapSyncMode``` + will render to: :qapi:type:`~block-core.BitmapSyncMode` + + +Custom link text +---------------- + +The name of a cross-reference link can be explicitly overridden like +`most stock Sphinx references +`_ +using the ``custom text `` syntax. + +For example, ``:qapi:cmd:`Merge dirty bitmaps +``` will render as: :qapi:cmd:`Merge dirty +bitmaps ` + + +Directives +========== + +The QAPI domain adds a number of custom directives for documenting +various QAPI/QMP entities. The syntax is plain rST, and follows this +general format:: + + .. qapi:directive:: argument + :option: + :another-option: with an argument + + Content body, arbitrary rST is allowed here. + + +Sphinx standard options +----------------------- + +All QAPI directives inherit a number of `standard options +`_ +from Sphinx's ObjectDescription class. + +The dashed spellings of the below options were added in Sphinx 7.2, the +undashed spellings are currently retained as aliases, but will be +removed in a future version. + +* ``:no-index:`` and ``:noindex:`` -- Do not add this item into the + Index, and do not make it available for cross-referencing. +* ``no-index-entry:`` and ``:noindexentry:`` -- Do not add this item + into the Index, but allow it to be cross-referenced. +* ``no-contents-entry`` and ``:nocontentsentry:`` -- Exclude this item + from the Table of Contents. +* ``no-typesetting`` -- Create TOC, Index and cross-referencing + entities, but don't actually display the content. + + +QAPI standard options +--------------------- + +All QAPI directives -- *except* for module -- support these common options. + +* ``:module: modname`` -- Borrowed from the Python domain, this option allows + you to override the module association of a given definition. +* ``:since: x.y`` -- Allows the documenting of "Since" information, which is + displayed in the signature bar. +* ``:ifcond: CONDITION`` -- Allows the documenting of conditional availability + information, which is displayed in an eyecatch just below the + signature bar. +* ``:deprecated:`` -- Adds an eyecatch just below the signature bar that + advertises that this definition is deprecated and should be avoided. +* ``:unstable:`` -- Adds an eyecatch just below the signature bar that + advertises that this definition is unstable and should not be used in + production code. + + +qapi:module +----------- + +The ``qapi:module`` directive marks the start of a QAPI module. It may have +a content body, but it can be omitted. All subsequent QAPI directives +are associated with the most recent module; this effects their "fully +qualified" name, but has no other effect. + +Example:: + + .. qapi:module:: block-core + + Welcome to the block-core module! + +Will be rendered as: + +.. qapi:module:: block-core + :noindex: + + Welcome to the block-core module! + + +qapi:command +------------ + +This directive documents a QMP command. It may use any of the standard +Sphinx or QAPI options, and the documentation body may contain +``:arg:``, ``:feat:``, ``:error:``, or ``:return:`` info field list +entries. + +Example:: + + .. qapi:command:: x-fake-command + :since: 42.0 + :unstable: + + This command is fake, so it can't hurt you! + + :arg int foo: Your favorite number. + :arg string? bar: Your favorite season. + :return [string]: A lovely computer-written poem for you. + + +Will be rendered as: + + .. qapi:command:: x-fake-command + :noindex: + :since: 42.0 + :unstable: + + This command is fake, so it can't hurt you! + + :arg int foo: Your favorite number. + :arg string? bar: Your favorite season. + :return [string]: A lovely computer-written poem for you. + + +qapi:event +---------- + +This directive documents a QMP event. It may use any of the standard +Sphinx or QAPI options, and the documentation body may contain +``:memb:`` or ``:feat:`` info field list entries. + +Example:: + + .. qapi:event:: COMPUTER_IS_RUINED + :since: 0.1 + :deprecated: + + This event is emitted when your computer is *extremely* ruined. + + :memb string reason: Diagnostics as to what caused your computer to + be ruined. + :feat sadness: When present, the diagnostic message will also + explain how sad the computer is as a result of your wrongdoings. + +Will be rendered as: + +.. qapi:event:: COMPUTER_IS_RUINED + :noindex: + :since: 0.1 + :deprecated: + + This event is emitted when your computer is *extremely* ruined. + + :memb string reason: Diagnostics as to what caused your computer to + be ruined. + :feat sadness: When present, the diagnostic message will also explain + how sad the computer is as a result of your wrongdoings. + + +qapi:enum +--------- + +This directive documents a QAPI enum. It may use any of the standard +Sphinx or QAPI options, and the documentation body may contain +``:value:`` or ``:feat:`` info field list entries. + +Example:: + + .. qapi:enum:: Mood + :ifcond: LIB_PERSONALITY + + This enum represents your virtual machine's current mood! + + :value Happy: Your VM is content and well-fed. + :value Hungry: Your VM needs food. + :value Melancholic: Your VM is experiencing existential angst. + :value Petulant: Your VM is throwing a temper tantrum. + +Will be rendered as: + +.. qapi:enum:: Mood + :noindex: + :ifcond: LIB_PERSONALITY + + This enum represents your virtual machine's current mood! + + :value Happy: Your VM is content and well-fed. + :value Hungry: Your VM needs food. + :value Melancholic: Your VM is experiencing existential angst. + :value Petulant: Your VM is throwing a temper tantrum. + + +qapi:object +----------- + +This directive documents a QAPI structure or union and represents a QMP +object. It may use any of the standard Sphinx or QAPI options, and the +documentation body may contain ``:memb:`` or ``:feat:`` info field list +entries. + +Example:: + + .. qapi:object:: BigBlobOfStuff + + This object has a bunch of disparate and unrelated things in it. + + :memb int Birthday: Your birthday, represented in seconds since the + UNIX epoch. + :memb [string] Fav-Foods: A list of your favorite foods. + :memb boolean? Bizarre-Docs: True if the documentation reference + should be strange. + +Will be rendered as: + +.. qapi:object:: BigBlobOfStuff + :noindex: + + This object has a bunch of disparate and unrelated things in it. + + :memb int Birthday: Your birthday, represented in seconds since the + UNIX epoch. + :memb [string] Fav-Foods: A list of your favorite foods. + :memb boolean? Bizarre-Docs: True if the documentation reference + should be strange. + + +qapi:alternate +-------------- + +This directive documents a QAPI alternate. It may use any of the +standard Sphinx or QAPI options, and the documentation body may contain +``:alt:`` or ``:feat:`` info field list entries. + +Example:: + + .. qapi:alternate:: ErrorCode + + This alternate represents an Error Code from the VM. + + :alt int ec: An error code, like the type you're used to. + :alt string em: An expletive-laced error message, if your + computer is feeling particularly cranky and tired of your + antics. + +Will be rendered as: + +.. qapi:alternate:: ErrorCode + :noindex: + + This alternate represents an Error Code from the VM. + + :alt int ec: An error code, like the type you're used to. + :alt string em: An expletive-laced error message, if your + computer is feeling particularly cranky and tired of your + antics. From patchwork Tue Mar 11 11:31:36 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011543 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 06EB3C282EC for ; Tue, 11 Mar 2025 11:34:46 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxrn-0004Mm-SR; Tue, 11 Mar 2025 07:33: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 1trxqq-0003NO-Ko for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:58 -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 1trxqB-0006YO-Uf for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:48 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692724; 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=lAjS1Tl9qBsqP2PI4VKsVSX3kswXXTodNKXBjdAlF/I=; b=I6MBbHB082bjx/bThtDnv5U/+LoKpPdghR8PfcKXG62yfRx723Sqk4ZZIAI/CMFwJp9FDZ YpsYjx+LGW0306HKMk0ZE4NVGkirGEBfhM9LN/raA3rvaVEq0hzkIzsKyYyTKKhj9IlSee sS/qPG8INQ+oosKz0BUUDolsG1yy2GM= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-597-6TN92yDZP3ClPdz9aIid5g-1; Tue, 11 Mar 2025 07:32:03 -0400 X-MC-Unique: 6TN92yDZP3ClPdz9aIid5g-1 X-Mimecast-MFC-AGG-ID: 6TN92yDZP3ClPdz9aIid5g_1741692722 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (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 mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C583C18001E3 for ; Tue, 11 Mar 2025 11:32:02 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 755CC3001D0E for ; Tue, 11 Mar 2025 11:32:02 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id A455321E60E6; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 60/61] MAINTAINERS: Add jsnow as maintainer for Sphinx documentation Date: Tue, 11 Mar 2025 12:31:36 +0100 Message-ID: <20250311113137.1277125-61-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Received-SPF: pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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: John Snow Since I've just about rewritten the entirety of the QAPI documentation system, it's probably fair that I be the contact point for if it goes awry. Signed-off-by: John Snow Message-ID: <20250311034303.75779-64-jsnow@redhat.com> Acked-by: Markus Armbruster Signed-off-by: Markus Armbruster --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 0e5db7a574..55af2f8d17 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4325,6 +4325,7 @@ S: Orphan F: po/*.po Sphinx documentation configuration and build machinery +M: John Snow M: Peter Maydell S: Maintained F: docs/conf.py From patchwork Tue Mar 11 11:31:37 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 14011564 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 2E1B9C28B30 for ; Tue, 11 Mar 2025 11:37:13 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1trxsK-00069t-5Y; Tue, 11 Mar 2025 07:34:20 -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 1trxr0-0003PI-GQ for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:33:02 -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 1trxqC-0006ZB-F6 for qemu-devel@nongnu.org; Tue, 11 Mar 2025 07:32:55 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741692726; 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=lvzilbMVC26ZLEFny5voCKgpvDjZL2sGhHBzGtQ+8ig=; b=IyrSjYrerLZhYi+lCiy/lQpOvauPjlhgaggBEG3pOEtfdXPqwBfd8cZOuCg6hNpXtK/gnc DJrjiGsRnH5GUBbJR0rJOr88lmq/eND4wGibM/cdvbPjhLMhmgbidrEvqtWBUYNAuWOaLc uZd3ZhQpn6u1MM4I5M5iHFmcEQ0AXkM= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-26-gAWVg1BpPj-4Mw8ftEKtxA-1; Tue, 11 Mar 2025 07:32:03 -0400 X-MC-Unique: gAWVg1BpPj-4Mw8ftEKtxA-1 X-Mimecast-MFC-AGG-ID: gAWVg1BpPj-4Mw8ftEKtxA_1741692722 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (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 mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 7B7F01955BCD; Tue, 11 Mar 2025 11:32:02 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.22.74.4]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 2849F1828A98; Tue, 11 Mar 2025 11:32:02 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id A7E4621E60E7; Tue, 11 Mar 2025 12:31:38 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= Subject: [PULL 61/61] scripts/qapi/backend: Clean up create_backend()'s failure mode Date: Tue, 11 Mar 2025 12:31:37 +0100 Message-ID: <20250311113137.1277125-62-armbru@redhat.com> In-Reply-To: <20250311113137.1277125-1-armbru@redhat.com> References: <20250311113137.1277125-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass client-ip=170.10.133.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H2=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=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 create_backend()'s caller catches QAPIError, and returns non-zero exit code on catch. The caller's caller passes the exit code to sys.exit(). create_backend() doesn't care: it reports errors to stderr and sys.exit()s. Change it to raise QAPIError instead. Signed-off-by: Markus Armbruster Message-ID: <20250311065352.992307-1-armbru@redhat.com> Reviewed-by: Philippe Mathieu-Daudé --- scripts/qapi/main.py | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/scripts/qapi/main.py b/scripts/qapi/main.py index 5b4679abcf..0e2a6ae3f0 100644 --- a/scripts/qapi/main.py +++ b/scripts/qapi/main.py @@ -31,34 +31,28 @@ def create_backend(path: str) -> QAPIBackend: module_path, dot, class_name = path.rpartition('.') if not dot: - print("argument of -B must be of the form MODULE.CLASS", - file=sys.stderr) - sys.exit(1) + raise QAPIError("argument of -B must be of the form MODULE.CLASS") try: mod = import_module(module_path) except Exception as ex: - print(f"unable to import '{module_path}': {ex}", file=sys.stderr) - sys.exit(1) + raise QAPIError(f"unable to import '{module_path}': {ex}") from ex try: klass = getattr(mod, class_name) - except AttributeError: - print(f"module '{module_path}' has no class '{class_name}'", - file=sys.stderr) - sys.exit(1) + except AttributeError as ex: + raise QAPIError( + f"module '{module_path}' has no class '{class_name}'") from ex try: backend = klass() except Exception as ex: - print(f"backend '{path}' cannot be instantiated: {ex}", - file=sys.stderr) - sys.exit(1) + raise QAPIError( + f"backend '{path}' cannot be instantiated: {ex}") from ex if not isinstance(backend, QAPIBackend): - print(f"backend '{path}' must be an instance of QAPIBackend", - file=sys.stderr) - sys.exit(1) + raise QAPIError( + f"backend '{path}' must be an instance of QAPIBackend") return backend