From: Markus Armbruster <armbru@redhat.com>
To: qemu-devel@nongnu.org
Cc: jsnow@redhat.com, peter.maydell@linaro.org, michael.roth@amd.com
Subject: [PATCH 7/7] qapi: Simplify QAPISchemaVariants @tag_member
Date: Wed, 20 Mar 2024 08:43:15 +0100 [thread overview]
Message-ID: <20240320074315.23167-8-armbru@redhat.com> (raw)
In-Reply-To: <20240320074315.23167-1-armbru@redhat.com>
For union types, the tag member is known only after .check().
We used to code this in a simple way: QAPISchemaVariants attribute
.tag_member was None for union types until .check().
Since this complicated typing, recent commit "qapi/schema: fix typing
for QAPISchemaVariants.tag_member" hid it behind a property.
The previous commit lets us treat .tag_member just like the other
attributes that become known only in .check(): declare, but don't
initialize it in .__init__().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
scripts/qapi/schema.py | 44 +++++++++++++++++-------------------------
1 file changed, 18 insertions(+), 26 deletions(-)
diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
index c5b824f1fd..721c470d2b 100644
--- a/scripts/qapi/schema.py
+++ b/scripts/qapi/schema.py
@@ -723,18 +723,9 @@ def __init__(
variants: List[QAPISchemaVariant],
):
self.info = info
- self._tag_member: Optional[QAPISchemaObjectTypeMember] = None
+ self.tag_member: QAPISchemaObjectTypeMember
self.variants = variants
- @property
- def tag_member(self) -> QAPISchemaObjectTypeMember:
- if self._tag_member is None:
- raise RuntimeError(
- "QAPISchemaVariants has no tag_member property until "
- "after check() has been run."
- )
- return self._tag_member
-
def set_defined_in(self, name: str) -> None:
for v in self.variants:
v.set_defined_in(name)
@@ -758,47 +749,48 @@ def check(
self, schema: QAPISchema, seen: Dict[str, QAPISchemaMember]
) -> None:
# We need to narrow the member type:
- tmp = seen.get(c_name(self._tag_name))
- assert tmp is None or isinstance(tmp, QAPISchemaObjectTypeMember)
- self._tag_member = tmp
+ tag_member = seen.get(c_name(self._tag_name))
+ assert (tag_member is None
+ or isinstance(tag_member, QAPISchemaObjectTypeMember))
base = "'base'"
# Pointing to the base type when not implicit would be
# nice, but we don't know it here
- if not self._tag_member or self._tag_name != self._tag_member.name:
+ if not tag_member or self._tag_name != tag_member.name:
raise QAPISemError(
self.info,
"discriminator '%s' is not a member of %s"
% (self._tag_name, base))
+ self.tag_member = tag_member
# Here we do:
- assert self.tag_member.defined_in
- base_type = schema.lookup_type(self.tag_member.defined_in)
+ assert tag_member.defined_in
+ base_type = schema.lookup_type(tag_member.defined_in)
assert base_type
if not base_type.is_implicit():
- base = "base type '%s'" % self.tag_member.defined_in
- if not isinstance(self.tag_member.type, QAPISchemaEnumType):
+ base = "base type '%s'" % tag_member.defined_in
+ if not isinstance(tag_member.type, QAPISchemaEnumType):
raise QAPISemError(
self.info,
"discriminator member '%s' of %s must be of enum type"
% (self._tag_name, base))
- if self.tag_member.optional:
+ if tag_member.optional:
raise QAPISemError(
self.info,
"discriminator member '%s' of %s must not be optional"
% (self._tag_name, base))
- if self.tag_member.ifcond.is_present():
+ if tag_member.ifcond.is_present():
raise QAPISemError(
self.info,
"discriminator member '%s' of %s must not be conditional"
% (self._tag_name, base))
# branches that are not explicitly covered get an empty type
- assert self.tag_member.defined_in
+ assert tag_member.defined_in
cases = {v.name for v in self.variants}
- for m in self.tag_member.type.members:
+ for m in tag_member.type.members:
if m.name not in cases:
v = QAPISchemaVariant(m.name, self.info,
'q_empty', m.ifcond)
- v.set_defined_in(self.tag_member.defined_in)
+ v.set_defined_in(tag_member.defined_in)
self.variants.append(v)
if not self.variants:
raise QAPISemError(self.info, "union has no branches")
@@ -807,11 +799,11 @@ def check(
# Union names must match enum values; alternate names are
# checked separately. Use 'seen' to tell the two apart.
if seen:
- if v.name not in self.tag_member.type.member_names():
+ if v.name not in tag_member.type.member_names():
raise QAPISemError(
self.info,
"branch '%s' is not a value of %s"
- % (v.name, self.tag_member.type.describe()))
+ % (v.name, tag_member.type.describe()))
if not isinstance(v.type, QAPISchemaObjectType):
raise QAPISemError(
self.info,
@@ -839,7 +831,7 @@ def __init__(self,
variants: List[QAPISchemaVariant],
tag_member: QAPISchemaObjectTypeMember):
super().__init__(info, variants)
- self._tag_member = tag_member
+ self.tag_member = tag_member
def check(
self, schema: QAPISchema, seen: Dict[str, QAPISchemaMember]
--
2.44.0
prev parent reply other threads:[~2024-03-20 7:44 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-03-20 7:43 [PATCH 0/7] qapi: Refactor QAPISchemaVariants Markus Armbruster
2024-03-20 7:43 ` [PATCH 1/7] qapi: New QAPISchemaBranches, QAPISchemaAlternatives Markus Armbruster
2024-03-20 7:43 ` [PATCH 2/7] qapi: Rename visitor parameter @variants to @branches Markus Armbruster
2024-03-20 7:43 ` [PATCH 3/7] qapi: Rename visitor parameter @variants to @alternatives Markus Armbruster
2024-03-20 7:43 ` [PATCH 4/7] qapi: Rename QAPISchemaObjectType.variants to .branches Markus Armbruster
2024-03-20 7:43 ` [PATCH 5/7] qapi: Rename QAPISchemaAlternateType.variants to .alternatives Markus Armbruster
2024-03-20 7:43 ` [PATCH 6/7] qapi: Move conditional code from QAPISchemaVariants to its subtypes Markus Armbruster
2024-03-20 7:43 ` Markus Armbruster [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240320074315.23167-8-armbru@redhat.com \
--to=armbru@redhat.com \
--cc=jsnow@redhat.com \
--cc=michael.roth@amd.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).