From nobody Thu Nov 13 23:24:12 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 207.211.31.81 as permitted sender) client-ip=207.211.31.81; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-1.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 207.211.31.81 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1583253360; cv=none; d=zohomail.com; s=zohoarc; b=Q6pMfUR5FPpl9oLIqb/0QIXg28X53+M2iKC3/e3coTBmx5q84M3+R4XYwQ+7AjN9JkwanY0AB6OhQDu0KmER/1+1XeO0idx7g0qEf4k0OeJQ/KLcwLxyImzL0gczCKXYHR7rX/J/OjDIBEfk16iHttl+6R0v+n7SnGfCwJqibYE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1583253360; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=Bp5EbH/Kp4MBinsdHTQ0U4PgrwTqvS1mCzI/+Vn0cXU=; b=NtXgv/9AHEeCXVuc1HIPRzLJwmVJdzE9v9RsFuj4LwZuLCltJHDprqtX02EpcalP+m+GKTcEak+oxdvzLpxCFaULj5J7qrlI47XNbMP9OD1apw1c/omuHpODdBH7bcxfqtHZ4cIaUeGwXVNKl0jvr9j258OYkYb5nNLFyeeeGcg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 207.211.31.81 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-delivery-1.mimecast.com (us-smtp-1.mimecast.com [207.211.31.81]) by mx.zohomail.com with SMTPS id 1583253360587721.4898787286515; Tue, 3 Mar 2020 08:36:00 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-209-rTlFJzaFNxCEmMpTrCl-lw-1; Tue, 03 Mar 2020 11:35:56 -0500 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id B720C80257F; Tue, 3 Mar 2020 16:35:49 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 8734619C7F; Tue, 3 Mar 2020 16:35:49 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 204DF86A0E; Tue, 3 Mar 2020 16:35:49 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 023GZEHk001242 for ; Tue, 3 Mar 2020 11:35:14 -0500 Received: by smtp.corp.redhat.com (Postfix) id 619655DA7C; Tue, 3 Mar 2020 16:35:14 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-129.ams2.redhat.com [10.36.116.129]) by smtp.corp.redhat.com (Postfix) with ESMTPS id CC7C95D9C9; Tue, 3 Mar 2020 16:35:13 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id F294B11329C3; Tue, 3 Mar 2020 17:35:05 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1583253359; h=from:from:sender:sender: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:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=Bp5EbH/Kp4MBinsdHTQ0U4PgrwTqvS1mCzI/+Vn0cXU=; b=SgxP/LpQVizDYh2YeMDoB92kEkyGTb+pcm0ZBqOUG7ak5ajZ0JKdPhzSvqsZXYI6RxMfbv DShjg7llsx/4Gb82zqFbld/wYnpnrgnSkp10Cib2ENs6yvQHW63HjpaO47ynd6cZ6/OkNy ZO13ixhAw3BatuvkGkbGRLQFfZ/KL6o= X-MC-Unique: rTlFJzaFNxCEmMpTrCl-lw-1 From: Markus Armbruster To: qemu-devel@nongnu.org Subject: [PATCH v2 20/30] qapi: Add feature flags to struct members Date: Tue, 3 Mar 2020 17:34:55 +0100 Message-Id: <20200303163505.32041-21-armbru@redhat.com> In-Reply-To: <20200303163505.32041-1-armbru@redhat.com> References: <20200303163505.32041-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-loop: libvir-list@redhat.com Cc: libvir-list@redhat.com X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" Signed-off-by: Markus Armbruster --- docs/devel/qapi-code-gen.txt | 4 +++- tests/qapi-schema/doc-good.texi | 2 ++ qapi/introspect.json | 6 +++++- scripts/qapi/expr.py | 3 ++- scripts/qapi/introspect.py | 2 +- scripts/qapi/schema.py | 25 ++++++++++++++++++++----- tests/qapi-schema/doc-good.json | 5 ++++- tests/qapi-schema/doc-good.out | 3 +++ tests/qapi-schema/qapi-schema-test.json | 2 +- tests/qapi-schema/qapi-schema-test.out | 1 + tests/qapi-schema/test-qapi.py | 7 ++++--- 11 files changed, 46 insertions(+), 14 deletions(-) diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt index 9fce78dcad..a1ef1cfd61 100644 --- a/docs/devel/qapi-code-gen.txt +++ b/docs/devel/qapi-code-gen.txt @@ -234,7 +234,9 @@ Syntax: '*features': FEATURES } MEMBERS =3D { MEMBER, ... } MEMBER =3D STRING : TYPE-REF - | STRING : { 'type': TYPE-REF, '*if': COND } + | STRING : { 'type': TYPE-REF, + '*if': COND, + '*features': FEATURES } =20 Member 'struct' names the struct type. =20 diff --git a/tests/qapi-schema/doc-good.texi b/tests/qapi-schema/doc-good.t= exi index 76b396dae6..7f28fb7a0f 100644 --- a/tests/qapi-schema/doc-good.texi +++ b/tests/qapi-schema/doc-good.texi @@ -132,6 +132,8 @@ Not documented @table @asis @item @code{variant1-feat} a feature +@item @code{member-feat} +a member feature @end table =20 @end deftp diff --git a/qapi/introspect.json b/qapi/introspect.json index da3e176899..b1aabd4cfd 100644 --- a/qapi/introspect.json +++ b/qapi/introspect.json @@ -206,11 +206,15 @@ # Future extension: if present and non-null, the parameter # is optional, and defaults to this value. # +# @features: names of features associated with the member, in no +# particular order. (since 5.0) +# # Since: 2.5 ## { 'struct': 'SchemaInfoObjectMember', - 'data': { 'name': 'str', 'type': 'str', '*default': 'any' } } + 'data': { 'name': 'str', 'type': 'str', '*default': 'any', # @default's type must be null or match @type + '*features': [ 'str' ] } } =20 ## # @SchemaInfoObjectVariant: diff --git a/scripts/qapi/expr.py b/scripts/qapi/expr.py index f9c4448980..2942520399 100644 --- a/scripts/qapi/expr.py +++ b/scripts/qapi/expr.py @@ -167,8 +167,9 @@ def check_type(value, info, source, allow_optional=3DTrue, permit_upper=3Dpermit_upper) if c_name(key, False) =3D=3D 'u' or c_name(key, False).startswith(= 'has_'): raise QAPISemError(info, "%s uses reserved name" % key_source) - check_keys(arg, info, key_source, ['type'], ['if']) + check_keys(arg, info, key_source, ['type'], ['if', 'features']) check_if(arg, info, key_source) + check_features(arg.get('features'), info) check_type(arg['type'], info, key_source, allow_array=3DTrue) =20 =20 diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py index a3fa9865db..23652be810 100644 --- a/scripts/qapi/introspect.py +++ b/scripts/qapi/introspect.py @@ -173,7 +173,7 @@ const QLitObject %(c_name)s =3D %(c_string)s; obj =3D {'name': member.name, 'type': self._use_type(member.type)} if member.optional: obj['default'] =3D None - return _make_tree(obj, member.ifcond, None) + return _make_tree(obj, member.ifcond, member.features) =20 def _gen_variants(self, tag_name, variants): return {'tag': tag_name, diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py index 8368745a3e..2fb845303b 100644 --- a/scripts/qapi/schema.py +++ b/scripts/qapi/schema.py @@ -668,18 +668,31 @@ class QAPISchemaFeature(QAPISchemaMember): =20 =20 class QAPISchemaObjectTypeMember(QAPISchemaMember): - def __init__(self, name, info, typ, optional, ifcond=3DNone): + def __init__(self, name, info, typ, optional, ifcond=3DNone, features= =3DNone): super().__init__(name, info, ifcond) assert isinstance(typ, str) assert isinstance(optional, bool) + for f in features or []: + assert isinstance(f, QAPISchemaFeature) + f.set_defined_in(name) self._type_name =3D typ self.type =3D None self.optional =3D optional + self.features =3D features or [] =20 def check(self, schema): assert self.defined_in self.type =3D schema.resolve_type(self._type_name, self.info, self.describe) + seen =3D {} + for f in self.features: + f.check_clash(self.info, seen) + + def connect_doc(self, doc): + super().connect_doc(doc) + if doc: + for f in self.features: + doc.connect_feature(f) =20 =20 class QAPISchemaVariant(QAPISchemaObjectTypeMember): @@ -963,7 +976,7 @@ class QAPISchema: name, info, doc, ifcond, features, self._make_enum_members(data, info), prefix)) =20 - def _make_member(self, name, typ, ifcond, info): + def _make_member(self, name, typ, ifcond, features, info): optional =3D False if name.startswith('*'): name =3D name[1:] @@ -971,10 +984,12 @@ class QAPISchema: if isinstance(typ, list): assert len(typ) =3D=3D 1 typ =3D self._make_array_type(typ[0], info) - return QAPISchemaObjectTypeMember(name, info, typ, optional, ifcon= d) + return QAPISchemaObjectTypeMember(name, info, typ, optional, ifcon= d, + self._make_features(features, in= fo)) =20 def _make_members(self, data, info): - return [self._make_member(key, value['type'], value.get('if'), inf= o) + return [self._make_member(key, value['type'], value.get('if'), + value.get('features'), info) for (key, value) in data.items()] =20 def _def_struct_type(self, expr, info, doc): @@ -997,7 +1012,7 @@ class QAPISchema: typ =3D self._make_array_type(typ[0], info) typ =3D self._make_implicit_object_type( typ, info, self.lookup_type(typ), - 'wrapper', [self._make_member('data', typ, None, info)]) + 'wrapper', [self._make_member('data', typ, None, None, info)]) return QAPISchemaVariant(case, info, typ, ifcond) =20 def _def_union_type(self, expr, info, doc): diff --git a/tests/qapi-schema/doc-good.json b/tests/qapi-schema/doc-good.j= son index 457b8b2cdf..ddd89d1233 100644 --- a/tests/qapi-schema/doc-good.json +++ b/tests/qapi-schema/doc-good.json @@ -78,10 +78,13 @@ # # Features: # @variant1-feat: a feature +# @member-feat: a member feature ## { 'struct': 'Variant1', 'features': [ 'variant1-feat' ], - 'data': { 'var1': { 'type': 'str', 'if': 'defined(IFSTR)' } } } + 'data': { 'var1': { 'type': 'str', + 'features': [ 'member-feat' ], + 'if': 'defined(IFSTR)' } } } =20 ## # @Variant2: diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out index 9bcb2b3e91..6757dd26a2 100644 --- a/tests/qapi-schema/doc-good.out +++ b/tests/qapi-schema/doc-good.out @@ -21,6 +21,7 @@ object Base object Variant1 member var1: str optional=3DFalse if ['defined(IFSTR)'] + feature member-feat feature variant1-feat object Variant2 object Object @@ -135,6 +136,8 @@ Another paragraph (but no @var: line) =20 feature=3Dvariant1-feat a feature + feature=3Dmember-feat +a member feature doc symbol=3DVariant2 body=3D =20 diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qa= pi-schema-test.json index fa4f3a15da..f576c337af 100644 --- a/tests/qapi-schema/qapi-schema-test.json +++ b/tests/qapi-schema/qapi-schema-test.json @@ -258,7 +258,7 @@ 'data': { 'foo': 'int' }, 'features': [] } { 'struct': 'FeatureStruct1', - 'data': { 'foo': 'int' }, + 'data': { 'foo': { 'type': 'int', 'features': [ 'member-feature1' ] } }, 'features': [ 'feature1' ] } { 'struct': 'FeatureStruct2', 'data': { 'foo': 'int' }, diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qap= i-schema-test.out index 1cbd0802b3..cd863ae966 100644 --- a/tests/qapi-schema/qapi-schema-test.out +++ b/tests/qapi-schema/qapi-schema-test.out @@ -359,6 +359,7 @@ object FeatureStruct0 member foo: int optional=3DFalse object FeatureStruct1 member foo: int optional=3DFalse + feature member-feature1 feature feature1 object FeatureStruct2 member foo: int optional=3DFalse diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py index 8e09e54edb..f396b471eb 100755 --- a/tests/qapi-schema/test-qapi.py +++ b/tests/qapi-schema/test-qapi.py @@ -55,6 +55,7 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor): print(' member %s: %s optional=3D%s' % (m.name, m.type.name, m.optional)) self._print_if(m.ifcond, 8) + self._print_features(m.features, indent=3D8) self._print_variants(variants) self._print_if(ifcond) self._print_features(features) @@ -96,11 +97,11 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor): print('%sif %s' % (' ' * indent, ifcond)) =20 @classmethod - def _print_features(cls, features): + def _print_features(cls, features, indent=3D4): if features: for f in features: - print(' feature %s' % f.name) - cls._print_if(f.ifcond, 8) + print('%sfeature %s' % (' ' * indent, f.name)) + cls._print_if(f.ifcond, indent + 4) =20 =20 def test_frontend(fname): --=20 2.21.1