@@ -739,6 +739,10 @@ def check_event(expr, info):
allow_metas=meta)
+def enum_get_names(expr):
+ return [e['name'] for e in expr['data']]
+
+
def check_union(expr, info):
name = expr['union']
base = expr.get('base')
@@ -798,7 +802,7 @@ def check_union(expr, info):
# If the discriminator names an enum type, then all members
# of 'data' must also be members of the enum type.
if enum_define:
- if key not in enum_define['data']:
+ if key not in enum_get_names(enum_define):
raise QAPISemError(info,
"Discriminator value '%s' is not found in "
"enum '%s'"
@@ -806,7 +810,7 @@ def check_union(expr, info):
# If discriminator is user-defined, ensure all values are covered
if enum_define:
- for value in enum_define['data']:
+ for value in enum_get_names(enum_define):
if value not in members.keys():
raise QAPISemError(info, "Union '%s' data missing '%s' branch"
% (name, value))
@@ -837,10 +841,10 @@ def check_alternate(expr, info):
if qtype == 'QTYPE_QSTRING':
enum_expr = enum_types.get(value)
if enum_expr:
- for v in enum_expr['data']:
+ for v in enum_get_names(enum_expr):
if v in ['on', 'off']:
conflicting.add('QTYPE_QBOOL')
- if re.match(r'[-+0-9.]', v): # lazy, could be tightened
+ if re.match(r'[-+0-9.]', v): # lazy, could be tightened
conflicting.add('QTYPE_QNUM')
else:
conflicting.add('QTYPE_QNUM')
@@ -853,19 +857,34 @@ def check_alternate(expr, info):
types_seen[qt] = key
-def check_enum(expr, info):
+def normalize_enum(expr, info):
name = expr['enum']
members = expr.get('data')
- prefix = expr.get('prefix')
if not isinstance(members, list):
raise QAPISemError(info,
"Enum '%s' requires an array for 'data'" % name)
+
+ # translate short member form to dict form
+ for i, member in enumerate(members):
+ if not isinstance(member, dict):
+ member = {'name': member}
+ members[i] = member
+
+
+def check_enum(expr, info):
+ name = expr['enum']
+ members = expr.get('data')
+ prefix = expr.get('prefix')
+
if prefix is not None and not isinstance(prefix, str):
raise QAPISemError(info,
"Enum '%s' requires a string for 'prefix'" % name)
+
for member in members:
- check_name(info, "Member of enum '%s'" % name, member,
+ source = "Dictionary member of enum '%s'" % name
+ check_known_keys(info, source, member, ['name'], [])
+ check_name(info, "Member of enum '%s'" % name, member['name'],
enum_member=True)
@@ -926,6 +945,13 @@ def check_exprs(exprs):
for builtin in builtin_types.keys():
all_names[builtin] = 'built-in'
+ # Normalize exprs
+ for expr_elem in exprs:
+ expr = expr_elem['expr']
+ info = expr_elem['info']
+ if 'enum' in expr:
+ normalize_enum(expr, info)
+
# Learn the types and check for valid expression keys
for expr_elem in exprs:
expr = expr_elem['expr']
@@ -1631,7 +1657,14 @@ class QAPISchema(object):
qtype_values, 'QTYPE'))
def _make_enum_members(self, values):
- return [QAPISchemaMember(v) for v in values]
+ enum = []
+ for v in values:
+ if isinstance(v, dict):
+ name = v['name']
+ else:
+ name = v
+ enum.append(QAPISchemaMember(name))
+ return enum
def _make_implicit_enum_type(self, name, info, ifcond, values):
# See also QAPISchemaObjectTypeMember._pretty_owner()
@@ -476,10 +476,11 @@ qapi-schema += double-data.json
qapi-schema += double-type.json
qapi-schema += duplicate-key.json
qapi-schema += empty.json
+qapi-schema += enum-bad-member.json
qapi-schema += enum-bad-name.json
qapi-schema += enum-bad-prefix.json
qapi-schema += enum-clash-member.json
-qapi-schema += enum-dict-member.json
+qapi-schema += enum-dict-member-unknown.json
qapi-schema += enum-int-member.json
qapi-schema += enum-member-case.json
qapi-schema += enum-missing-data.json
new file mode 100644
@@ -0,0 +1 @@
+tests/qapi-schema/enum-bad-member.json:2: Member of enum 'MyEnum' requires a string name
similarity index 100%
rename from tests/qapi-schema/enum-dict-member.exit
rename to tests/qapi-schema/enum-bad-member.exit
new file mode 100644
@@ -0,0 +1,2 @@
+# we reject any enum member that is not a string
+{ 'enum': 'MyEnum', 'data': [ [ ] ] }
similarity index 100%
rename from tests/qapi-schema/enum-dict-member.out
rename to tests/qapi-schema/enum-bad-member.out
new file mode 100644
@@ -0,0 +1 @@
+tests/qapi-schema/enum-dict-member-unknown.json:2: Dictionary member of enum 'MyEnum' has unknown key 'bad-key' (allowed: 'name')
new file mode 100644
@@ -0,0 +1 @@
+1
new file mode 100644
@@ -0,0 +1,2 @@
+# we reject any enum member that is not a string or a dict with 'name'
+{ 'enum': 'MyEnum', 'data': [ { 'name': 'foo', 'bad-key': 'str' } ] }
new file mode 100644
deleted file mode 100644
@@ -1 +0,0 @@
-tests/qapi-schema/enum-dict-member.json:2: Member of enum 'MyEnum' requires a string name
deleted file mode 100644
@@ -1,2 +0,0 @@
-# we reject any enum member that is not a string
-{ 'enum': 'MyEnum', 'data': [ { 'value': 'str' } ] }
@@ -1 +1 @@
-tests/qapi-schema/enum-missing-data.json:2: enum 'MyEnum' must have 'data' key
+tests/qapi-schema/enum-missing-data.json:2: Enum 'MyEnum' requires an array for 'data'
Desugar the enum NAME form to { 'name': NAME }. This will allow to add new enum members, such as 'if' in the following patch. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- scripts/qapi/common.py | 49 ++++++++++++++++--- tests/Makefile.include | 3 +- tests/qapi-schema/enum-bad-member.err | 1 + ...-dict-member.exit => enum-bad-member.exit} | 0 tests/qapi-schema/enum-bad-member.json | 2 + ...um-dict-member.out => enum-bad-member.out} | 0 .../qapi-schema/enum-dict-member-unknown.err | 1 + .../qapi-schema/enum-dict-member-unknown.exit | 1 + .../qapi-schema/enum-dict-member-unknown.json | 2 + .../qapi-schema/enum-dict-member-unknown.out | 0 tests/qapi-schema/enum-dict-member.err | 1 - tests/qapi-schema/enum-dict-member.json | 2 - tests/qapi-schema/enum-missing-data.err | 2 +- 13 files changed, 51 insertions(+), 13 deletions(-) create mode 100644 tests/qapi-schema/enum-bad-member.err rename tests/qapi-schema/{enum-dict-member.exit => enum-bad-member.exit} (100%) create mode 100644 tests/qapi-schema/enum-bad-member.json rename tests/qapi-schema/{enum-dict-member.out => enum-bad-member.out} (100%) create mode 100644 tests/qapi-schema/enum-dict-member-unknown.err create mode 100644 tests/qapi-schema/enum-dict-member-unknown.exit create mode 100644 tests/qapi-schema/enum-dict-member-unknown.json create mode 100644 tests/qapi-schema/enum-dict-member-unknown.out delete mode 100644 tests/qapi-schema/enum-dict-member.err delete mode 100644 tests/qapi-schema/enum-dict-member.json