提交 4fca21c1 编写于 作者: M Marc-André Lureau 提交者: Markus Armbruster

qapi: leave the ifcond attribute undefined until check()

We commonly initialize attributes to None in .init(), then set their
real value in .check().  Accessing the attribute before .check()
yields None.  If we're lucky, the code that accesses the attribute
prematurely chokes on None.

It won't for .ifcond, because None is a legitimate value.

Leave the ifcond attribute undefined until check().
Suggested-by: NMarkus Armbruster <armbru@redhat.com>
Signed-off-by: NMarc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: NMarkus Armbruster <armbru@redhat.com>
Message-Id: <20180703155648.11933-4-marcandre.lureau@redhat.com>
Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
上级 2cbc9437
...@@ -1021,13 +1021,19 @@ class QAPISchemaEntity(object): ...@@ -1021,13 +1021,19 @@ class QAPISchemaEntity(object):
# such place). # such place).
self.info = info self.info = info
self.doc = doc self.doc = doc
self.ifcond = listify_cond(ifcond) self._ifcond = ifcond # self.ifcond is set only after .check()
def c_name(self): def c_name(self):
return c_name(self.name) return c_name(self.name)
def check(self, schema): def check(self, schema):
pass if isinstance(self._ifcond, QAPISchemaType):
# inherit the condition from a type
typ = self._ifcond
typ.check(schema)
self.ifcond = typ.ifcond
else:
self.ifcond = listify_cond(self._ifcond)
def is_implicit(self): def is_implicit(self):
return not self.info return not self.info
...@@ -1164,6 +1170,7 @@ class QAPISchemaEnumType(QAPISchemaType): ...@@ -1164,6 +1170,7 @@ class QAPISchemaEnumType(QAPISchemaType):
self.prefix = prefix self.prefix = prefix
def check(self, schema): def check(self, schema):
QAPISchemaType.check(self, schema)
seen = {} seen = {}
for v in self.values: for v in self.values:
v.check_clash(self.info, seen) v.check_clash(self.info, seen)
...@@ -1196,8 +1203,10 @@ class QAPISchemaArrayType(QAPISchemaType): ...@@ -1196,8 +1203,10 @@ class QAPISchemaArrayType(QAPISchemaType):
self.element_type = None self.element_type = None
def check(self, schema): def check(self, schema):
QAPISchemaType.check(self, schema)
self.element_type = schema.lookup_type(self._element_type_name) self.element_type = schema.lookup_type(self._element_type_name)
assert self.element_type assert self.element_type
self.element_type.check(schema)
self.ifcond = self.element_type.ifcond self.ifcond = self.element_type.ifcond
def is_implicit(self): def is_implicit(self):
...@@ -1240,6 +1249,7 @@ class QAPISchemaObjectType(QAPISchemaType): ...@@ -1240,6 +1249,7 @@ class QAPISchemaObjectType(QAPISchemaType):
self.members = None self.members = None
def check(self, schema): def check(self, schema):
QAPISchemaType.check(self, schema)
if self.members is False: # check for cycles if self.members is False: # check for cycles
raise QAPISemError(self.info, raise QAPISemError(self.info,
"Object %s contains itself" % self.name) "Object %s contains itself" % self.name)
...@@ -1430,6 +1440,7 @@ class QAPISchemaAlternateType(QAPISchemaType): ...@@ -1430,6 +1440,7 @@ class QAPISchemaAlternateType(QAPISchemaType):
self.variants = variants self.variants = variants
def check(self, schema): def check(self, schema):
QAPISchemaType.check(self, schema)
self.variants.tag_member.check(schema) self.variants.tag_member.check(schema)
# Not calling self.variants.check_clash(), because there's nothing # Not calling self.variants.check_clash(), because there's nothing
# to clash with # to clash with
...@@ -1474,6 +1485,7 @@ class QAPISchemaCommand(QAPISchemaEntity): ...@@ -1474,6 +1485,7 @@ class QAPISchemaCommand(QAPISchemaEntity):
self.allow_preconfig = allow_preconfig self.allow_preconfig = allow_preconfig
def check(self, schema): def check(self, schema):
QAPISchemaEntity.check(self, schema)
if self._arg_type_name: if self._arg_type_name:
self.arg_type = schema.lookup_type(self._arg_type_name) self.arg_type = schema.lookup_type(self._arg_type_name)
assert (isinstance(self.arg_type, QAPISchemaObjectType) or assert (isinstance(self.arg_type, QAPISchemaObjectType) or
...@@ -1509,6 +1521,7 @@ class QAPISchemaEvent(QAPISchemaEntity): ...@@ -1509,6 +1521,7 @@ class QAPISchemaEvent(QAPISchemaEntity):
self.boxed = boxed self.boxed = boxed
def check(self, schema): def check(self, schema):
QAPISchemaEntity.check(self, schema)
if self._arg_type_name: if self._arg_type_name:
self.arg_type = schema.lookup_type(self._arg_type_name) self.arg_type = schema.lookup_type(self._arg_type_name)
assert (isinstance(self.arg_type, QAPISchemaObjectType) or assert (isinstance(self.arg_type, QAPISchemaObjectType) or
...@@ -1642,7 +1655,7 @@ class QAPISchema(object): ...@@ -1642,7 +1655,7 @@ class QAPISchema(object):
# But it's not tight: the disjunction need not imply it. We # But it's not tight: the disjunction need not imply it. We
# may end up compiling useless wrapper types. # may end up compiling useless wrapper types.
# TODO kill simple unions or implement the disjunction # TODO kill simple unions or implement the disjunction
assert ifcond == typ.ifcond assert ifcond == typ._ifcond # pylint: disable=protected-access
else: else:
self._def_entity(QAPISchemaObjectType(name, info, doc, ifcond, self._def_entity(QAPISchemaObjectType(name, info, doc, ifcond,
None, members, None)) None, members, None))
...@@ -1688,7 +1701,7 @@ class QAPISchema(object): ...@@ -1688,7 +1701,7 @@ class QAPISchema(object):
assert len(typ) == 1 assert len(typ) == 1
typ = self._make_array_type(typ[0], info) typ = self._make_array_type(typ[0], info)
typ = self._make_implicit_object_type( typ = self._make_implicit_object_type(
typ, info, None, self.lookup_type(typ).ifcond, typ, info, None, self.lookup_type(typ),
'wrapper', [self._make_member('data', typ, info)]) 'wrapper', [self._make_member('data', typ, info)])
return QAPISchemaObjectTypeVariant(case, typ) return QAPISchemaObjectTypeVariant(case, typ)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册