get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/1.1/patches/2221040/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2221040,
    "url": "http://patchwork.ozlabs.org/api/1.1/patches/2221040/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260408045531.3006678-3-jsnow@redhat.com/",
    "project": {
        "id": 14,
        "url": "http://patchwork.ozlabs.org/api/1.1/projects/14/?format=api",
        "name": "QEMU Development",
        "link_name": "qemu-devel",
        "list_id": "qemu-devel.nongnu.org",
        "list_email": "qemu-devel@nongnu.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": ""
    },
    "msgid": "<20260408045531.3006678-3-jsnow@redhat.com>",
    "date": "2026-04-08T04:55:23",
    "name": "[v2,02/10] qapi: prohibit 'details' sections between tagged sections",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "6be69cbbaa48e14ac194991ab9017f47c3d67797",
    "submitter": {
        "id": 64343,
        "url": "http://patchwork.ozlabs.org/api/1.1/people/64343/?format=api",
        "name": "John Snow",
        "email": "jsnow@redhat.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260408045531.3006678-3-jsnow@redhat.com/mbox/",
    "series": [
        {
            "id": 499174,
            "url": "http://patchwork.ozlabs.org/api/1.1/series/499174/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=499174",
            "date": "2026-04-08T04:55:23",
            "name": "qapi: enforce section ordering",
            "version": 2,
            "mbox": "http://patchwork.ozlabs.org/series/499174/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2221040/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2221040/checks/",
    "tags": {},
    "headers": {
        "Return-Path": "<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>",
        "X-Original-To": "incoming@patchwork.ozlabs.org",
        "Delivered-To": "patchwork-incoming@legolas.ozlabs.org",
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=VuS8q6z3;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)"
        ],
        "Received": [
            "from lists.gnu.org (unknown [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4frWnw1tM5z1yD6\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 09 Apr 2026 04:30:11 +1000 (AEST)",
            "from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1wAXep-00056S-4Z; Wed, 08 Apr 2026 14:29:43 -0400",
            "from eggs.gnu.org ([2001:470:142:3::10])\n by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <jsnow@redhat.com>) id 1wAXen-000556-RO\n for qemu-devel@nongnu.org; Wed, 08 Apr 2026 14:29:41 -0400",
            "from us-smtp-delivery-124.mimecast.com ([170.10.129.124])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <jsnow@redhat.com>) id 1wAKxT-0005UH-Qx\n for qemu-devel@nongnu.org; Wed, 08 Apr 2026 00:56:10 -0400",
            "from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com\n (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by\n relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n cipher=TLS_AES_256_GCM_SHA384) id us-mta-329-lOT0K19TPK6DqGxGM7vQLw-1; Wed,\n 08 Apr 2026 00:56:03 -0400",
            "from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n (No client certificate requested)\n by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id 1ADD41800281; Wed,  8 Apr 2026 04:56:01 +0000 (UTC)",
            "from jsnow-thinkpadp16vgen1.westford.csb (unknown [10.22.88.7])\n by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP\n id EFD7F19560A6; Wed,  8 Apr 2026 04:55:52 +0000 (UTC)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1775624167;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:\n content-transfer-encoding:content-transfer-encoding:\n in-reply-to:in-reply-to:references:references;\n bh=eN1Lr5jD4lirMRmReH/dTqZHRqKW+Gj5QMyDxvzEpUg=;\n b=VuS8q6z3CJ6R9zYXZg00tSzNOJrMA9UZdaFz6rJU9NPO3JejBP3N1nQsVgSep2lwat3/lv\n ND6oVkw7cxuWHMaR4eWwIPIB6lCYuRdVh7B8vrePiSO1ZbaLApPOZCR5Fhhzz/9ZU9LkDb\n iFfijaig2t/NmS4P51pzlr3zgsLej1Y=",
        "X-MC-Unique": "lOT0K19TPK6DqGxGM7vQLw-1",
        "X-Mimecast-MFC-AGG-ID": "lOT0K19TPK6DqGxGM7vQLw_1775624161",
        "From": "John Snow <jsnow@redhat.com>",
        "To": "qemu-devel@nongnu.org",
        "Cc": "Kashyap Chamarthy <kchamart@redhat.com>,\n Stefan Berger <stefanb@linux.vnet.ibm.com>,\n Mauro Carvalho Chehab <mchehab+huawei@kernel.org>,\n Michael Roth <michael.roth@amd.com>,\n =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= <philmd@linaro.org>,\n qemu-block@nongnu.org, Pierrick Bouvier <pierrick.bouvier@linaro.org>,\n Yanan Wang <wangyanan55@huawei.com>, Hanna Reitz <hreitz@redhat.com>,\n Peter Xu <peterx@redhat.com>, Igor Mammedov <imammedo@redhat.com>,\n \"Michael S. Tsirkin\" <mst@redhat.com>, Kevin Wolf <kwolf@redhat.com>,\n\t=?utf-8?q?Marc-Andr=C3=A9_Lureau?= <marcandre.lureau@redhat.com>,\n Stefano Garzarella <sgarzare@redhat.com>, =?utf-8?q?Daniel_P=2E_Berrang?=\n\t=?utf-8?q?=C3=A9?= <berrange@redhat.com>, Lukas Straub <lukasstraub2@web.de>,\n Jason Wang <jasowang@redhat.com>, Alex Williamson <alex@shazbot.org>,\n Paolo Bonzini <pbonzini@redhat.com>, Fabiano Rosas <farosas@suse.de>,\n Zhao Liu <zhao1.liu@intel.com>,\n Richard Henderson <richard.henderson@linaro.org>, =?utf-8?q?C=C3=A9dric_Le_?=\n\t=?utf-8?q?Goater?= <clg@redhat.com>, Stefan Hajnoczi <stefanha@redhat.com>,\n Peter Maydell <peter.maydell@linaro.org>, Eric Blake <eblake@redhat.com>,\n\t=?utf-8?q?Alex_Benn=C3=A9e?= <alex.bennee@linaro.org>,\n Kostiantyn Kostiuk <kkostiuk@redhat.com>, Jiri Pirko <jiri@resnulli.us>,\n Markus Armbruster <armbru@redhat.com>, John Snow <jsnow@redhat.com>,\n Ani Sinha <anisinha@redhat.com>,\n Marcel Apfelbaum <marcel.apfelbaum@gmail.com>",
        "Subject": "[PATCH v2 02/10] qapi: prohibit 'details' sections between tagged\n sections",
        "Date": "Wed,  8 Apr 2026 00:55:23 -0400",
        "Message-ID": "<20260408045531.3006678-3-jsnow@redhat.com>",
        "In-Reply-To": "<20260408045531.3006678-1-jsnow@redhat.com>",
        "References": "<20260408045531.3006678-1-jsnow@redhat.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "X-Scanned-By": "MIMEDefang 3.0 on 10.30.177.12",
        "Received-SPF": "pass client-ip=170.10.129.124; envelope-from=jsnow@redhat.com;\n helo=us-smtp-delivery-124.mimecast.com",
        "X-Spam_score_int": "-25",
        "X-Spam_score": "-2.6",
        "X-Spam_bar": "--",
        "X-Spam_report": "(-2.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.54,\n DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1,\n RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001,\n RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001,\n SPF_HELO_PASS=-0.001,\n SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no",
        "X-Spam_action": "no action",
        "X-BeenThere": "qemu-devel@nongnu.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "qemu development <qemu-devel.nongnu.org>",
        "List-Unsubscribe": "<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>",
        "List-Archive": "<https://lists.nongnu.org/archive/html/qemu-devel>",
        "List-Post": "<mailto:qemu-devel@nongnu.org>",
        "List-Help": "<mailto:qemu-devel-request@nongnu.org?subject=help>",
        "List-Subscribe": "<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>",
        "Errors-To": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org",
        "Sender": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org"
    },
    "content": "This patch prohibits plain documentation sections from appearing between\n(most*) tagged/description sections. The two existing uses of this\npattern (One in tests, one in our actual docs) are patched out.\n\nThis is being done for two main reasons:\n\n(1) By limiting the locations where a \"details\" section may occur, it is\neasier to reason about where a details section must be placed when\nmerging two or more documentation blocks together. This eases the logic\nin the forthcoming inliner significantly.\n\n(2) It improves visual consistency in the rendered HTML output. Tagged\nsections and descriptions are all presented in a tabular format, so\nprohibiting free-form text from interleaving the table looks better.\n\n(*\"most\": As of this patch, TODO and Since sections may still occur\nbefore, after, or between detail sections. These sections are removed\nfrom the flow of the document when rendered to HTML, so in effect even\nthough we may have multiple details sections, they will be contiguous in\nrendered HTML output.)\n\nSigned-off-by: John Snow <jsnow@redhat.com>\n\n---\n\n[Review note: the output of *.ir files changes slightly, but\nintentionally, with this patch; the two distinct changes correlate with\nthe edits made to the qapi .json files modified explicitly by this\npatch. --js]\n\nSigned-off-by: John Snow <jsnow@redhat.com>\n---\n docs/devel/qapi-code-gen.rst                 | 15 +++++++++++----\n qapi/qom.json                                |  4 ++--\n scripts/qapi/parser.py                       | 19 +++++++++++++++++++\n tests/qapi-schema/doc-good.json              |  4 ++--\n tests/qapi-schema/doc-good.out               |  4 ++--\n tests/qapi-schema/doc-good.txt               |  8 ++++----\n tests/qapi-schema/doc-misplaced-details.err  |  0\n tests/qapi-schema/doc-misplaced-details.json |  3 +++\n tests/qapi-schema/doc-misplaced-details.out  | 11 +++++++++++\n tests/qapi-schema/meson.build                |  1 +\n 10 files changed, 55 insertions(+), 14 deletions(-)\n create mode 100644 tests/qapi-schema/doc-misplaced-details.err\n create mode 100644 tests/qapi-schema/doc-misplaced-details.json\n create mode 100644 tests/qapi-schema/doc-misplaced-details.out",
    "diff": "diff --git a/docs/devel/qapi-code-gen.rst b/docs/devel/qapi-code-gen.rst\nindex 3a632b4a648..06ab3547fdc 100644\n--- a/docs/devel/qapi-code-gen.rst\n+++ b/docs/devel/qapi-code-gen.rst\n@@ -985,10 +985,17 @@ When documentation is required (see pragma_ 'doc-required'), every\n definition must have documentation.\n \n Definition documentation starts with a line naming the definition,\n-followed by an optional overview, a description of each argument (for\n-commands and events), member (for structs and unions), branch (for\n-alternates), or value (for enums), a description of each feature (if\n-any), and finally optional tagged sections.\n+followed by an optional overview (the \"intro\"), a description of each\n+argument (for commands and events), member (for structs and unions),\n+branch (for alternates), or value (for enums), a description of each\n+feature (if any), most optional tagged sections, plaintext detail\n+paragraphs, and finally the optional \"Since\" tagged section.\n+\n+Paragraphs following the optional overview (the \"intro\") may not appear\n+between any description or tagged section as described above. These\n+sections are \"detail\" sections and must appear at the end of the\n+documentation block, with the exception of \"Since\" or \"TODO\" sections\n+which may appear after.\n \n Descriptions start with '\\@name:'.  The description text must be\n indented like this::\ndiff --git a/qapi/qom.json b/qapi/qom.json\nindex c653248f85d..1b47abd44e9 100644\n--- a/qapi/qom.json\n+++ b/qapi/qom.json\n@@ -243,12 +243,12 @@\n #\n # @typename: the type name of an object\n #\n+# Returns: a list describing object properties\n+#\n # .. note:: Objects can create properties at runtime, for example to\n #    describe links between different devices and/or objects.  These\n #    properties are not included in the output of this command.\n #\n-# Returns: a list describing object properties\n-#\n # Since: 2.12\n ##\n { 'command': 'qom-list-properties',\ndiff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py\nindex da0ac32ad89..8a21e9e8b56 100644\n--- a/scripts/qapi/parser.py\n+++ b/scripts/qapi/parser.py\n@@ -545,6 +545,21 @@ def get_doc(self) -> 'QAPIDoc':\n             self.accept(False)\n             line = self.get_doc_line()\n             have_tagged = False\n+            no_more_tags = False\n+\n+            def _tag_check(this: Union['QAPIDoc.Kind', str]) -> None:\n+                if isinstance(this, str):\n+                    this = QAPIDoc.Kind.from_string(this)\n+                if this in (QAPIDoc.Kind.TODO, QAPIDoc.Kind.SINCE):\n+                    return\n+\n+                if no_more_tags:\n+                    raise QAPIParseError(\n+                        self,\n+                        f\"'{this}' section cannot appear after plain \"\n+                        \"paragraphs that follow other tagged sections\\n\"\n+                        \"Move this section up above the plain paragraph(s).\"\n+                    )\n \n             while line is not None:\n                 # Blank lines\n@@ -558,6 +573,7 @@ def get_doc(self) -> 'QAPIDoc':\n                     if doc.features:\n                         raise QAPIParseError(\n                             self, \"duplicated 'Features:' line\")\n+                    _tag_check(QAPIDoc.Kind.FEATURE)\n                     self.accept(False)\n                     line = self.get_doc_line()\n                     while line == '':\n@@ -621,6 +637,7 @@ def get_doc(self) -> 'QAPIDoc':\n                         )\n                         raise QAPIParseError(self, emsg)\n \n+                    _tag_check(match.group(1))\n                     doc.new_tagged_section(\n                         self.info,\n                         QAPIDoc.Kind.from_string(match.group(1))\n@@ -632,6 +649,8 @@ def get_doc(self) -> 'QAPIDoc':\n                     have_tagged = True\n                 else:\n                     # plain paragraph\n+                    if have_tagged:\n+                        no_more_tags = True\n \n                     # Paragraphs before tagged sections are \"intro\" paragraphs.\n                     # Any appearing after are \"detail\" paragraphs.\ndiff --git a/tests/qapi-schema/doc-good.json b/tests/qapi-schema/doc-good.json\nindex fac13425b72..9103fed472e 100644\n--- a/tests/qapi-schema/doc-good.json\n+++ b/tests/qapi-schema/doc-good.json\n@@ -165,12 +165,12 @@\n # @cmd-feat1: a feature\n # @cmd-feat2: another feature\n #\n-# .. note:: @arg3 is undocumented\n-#\n # Returns: @Object\n #\n # Errors: some\n #\n+# .. note:: @arg3 is undocumented\n+#\n # TODO: frobnicate\n #\n # .. admonition:: Notes\ndiff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out\nindex 04e29e8d50f..6a0167ad580 100644\n--- a/tests/qapi-schema/doc-good.out\n+++ b/tests/qapi-schema/doc-good.out\n@@ -175,12 +175,12 @@ description starts on the same line\n a feature\n     feature=cmd-feat2\n another feature\n-    section=Details\n-.. note:: @arg3 is undocumented\n     section=Returns\n @Object\n     section=Errors\n some\n+    section=Details\n+.. note:: @arg3 is undocumented\n     section=Todo\n frobnicate\n     section=Details\ndiff --git a/tests/qapi-schema/doc-good.txt b/tests/qapi-schema/doc-good.txt\nindex 74b73681d32..ded699dd596 100644\n--- a/tests/qapi-schema/doc-good.txt\n+++ b/tests/qapi-schema/doc-good.txt\n@@ -120,16 +120,16 @@ Command cmd (Since: 2.10)\n \n       * **cmd-feat2** -- another feature\n \n-   Note:\n-\n-     \"arg3\" is undocumented\n-\n    Return:\n       \"Object\" -- \"Object\"\n \n    Errors:\n       some\n \n+   Note:\n+\n+     \"arg3\" is undocumented\n+\n    Notes:\n \n    * Lorem ipsum dolor sit amet\ndiff --git a/tests/qapi-schema/doc-misplaced-details.err b/tests/qapi-schema/doc-misplaced-details.err\nnew file mode 100644\nindex 00000000000..e69de29bb2d\ndiff --git a/tests/qapi-schema/doc-misplaced-details.json b/tests/qapi-schema/doc-misplaced-details.json\nnew file mode 100644\nindex 00000000000..de593ab0f69\n--- /dev/null\n+++ b/tests/qapi-schema/doc-misplaced-details.json\n@@ -0,0 +1,3 @@\n+# FIXME / TODO\n+# This test should test for the error message when we misplace details\n+# sections interleaved between descriptions/tagged sections.\ndiff --git a/tests/qapi-schema/doc-misplaced-details.out b/tests/qapi-schema/doc-misplaced-details.out\nnew file mode 100644\nindex 00000000000..3c602d2592c\n--- /dev/null\n+++ b/tests/qapi-schema/doc-misplaced-details.out\n@@ -0,0 +1,11 @@\n+module ./builtin\n+object q_empty\n+enum QType\n+    member none\n+    member qnull\n+    member qnum\n+    member qstring\n+    member qdict\n+    member qlist\n+    member qbool\n+module doc-misplaced-details.json\ndiff --git a/tests/qapi-schema/meson.build b/tests/qapi-schema/meson.build\nindex debff633ac1..c233d77ab78 100644\n--- a/tests/qapi-schema/meson.build\n+++ b/tests/qapi-schema/meson.build\n@@ -83,6 +83,7 @@ schemas = [\n   'doc-invalid-section.json',\n   'doc-invalid-start.json',\n   'doc-long-line.json',\n+  'doc-misplaced-details.json',\n   'doc-missing-colon.json',\n   'doc-missing-expr.json',\n   'doc-missing-space.json',\n",
    "prefixes": [
        "v2",
        "02/10"
    ]
}