qapi: add 'any' condition

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20210804083105.97531-8-marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
This commit is contained in:
Marc-André Lureau 2021-08-04 12:31:02 +04:00 committed by Markus Armbruster
parent 5d83b9a130
commit 3ad64edfad
11 changed files with 27 additions and 12 deletions

View file

@ -207,7 +207,7 @@ def cgen_ifcond(ifcond: Union[str, Dict[str, Any]]) -> str:
return ifcond return ifcond
oper, operands = next(iter(ifcond.items())) oper, operands = next(iter(ifcond.items()))
oper = {'all': '&&'}[oper] oper = {'all': '&&', 'any': '||'}[oper]
operands = [cgen_ifcond(o) for o in operands] operands = [cgen_ifcond(o) for o in operands]
return '(' + (') ' + oper + ' (').join(operands) + ')' return '(' + (') ' + oper + ' (').join(operands) + ')'
@ -220,7 +220,7 @@ def docgen_ifcond(ifcond: Union[str, Dict[str, Any]]) -> str:
return ifcond return ifcond
oper, operands = next(iter(ifcond.items())) oper, operands = next(iter(ifcond.items()))
oper = {'all': ' and '}[oper] oper = {'all': ' and ', 'any': ' or '}[oper]
operands = [docgen_ifcond(o) for o in operands] operands = [docgen_ifcond(o) for o in operands]
return '(' + oper.join(operands) + ')' return '(' + oper.join(operands) + ')'

View file

@ -290,16 +290,16 @@ def check_if(expr: _JSONObject, info: QAPISourceInfo, source: str) -> None:
raise QAPISemError( raise QAPISemError(
info, info,
"'if' condition dict of %s must have one key: " "'if' condition dict of %s must have one key: "
"'all'" % source) "'all' or 'any'" % source)
check_keys(cond, info, "'if' condition", [], check_keys(cond, info, "'if' condition", [],
["all"]) ["all", "any"])
oper, operands = next(iter(cond.items())) oper, operands = next(iter(cond.items()))
if not operands: if not operands:
raise QAPISemError( raise QAPISemError(
info, "'if' condition [] of %s is useless" % source) info, "'if' condition [] of %s is useless" % source)
if oper in ("all") and not isinstance(operands, list): if oper in ("all", "any") and not isinstance(operands, list):
raise QAPISemError( raise QAPISemError(
info, "'%s' condition of %s must be an array" % (oper, source)) info, "'%s' condition of %s must be an array" % (oper, source))
for operand in operands: for operand in operands:

View file

@ -1,3 +1,3 @@
bad-if-key.json: In struct 'TestIfStruct': bad-if-key.json: In struct 'TestIfStruct':
bad-if-key.json:2: 'if' condition has unknown key 'value' bad-if-key.json:2: 'if' condition has unknown key 'value'
Valid keys are 'all'. Valid keys are 'all', 'any'.

View file

@ -1,2 +1,2 @@
bad-if-keys.json: In struct 'TestIfStruct': bad-if-keys.json: In struct 'TestIfStruct':
bad-if-keys.json:2: 'if' condition dict of struct must have one key: 'all' bad-if-keys.json:2: 'if' condition dict of struct must have one key: 'all' or 'any'

View file

@ -103,7 +103,9 @@
'features': [ 'union-feat1' ], 'features': [ 'union-feat1' ],
'base': 'Base', 'base': 'Base',
'discriminator': 'base1', 'discriminator': 'base1',
'data': { 'one': 'Variant1', 'two': { 'type': 'Variant2', 'if': 'IFTWO' } } } 'data': { 'one': 'Variant1',
'two': { 'type': 'Variant2',
'if': { 'any': ['IFONE', 'IFTWO'] } } } }
## ##
# @SugaredUnion: # @SugaredUnion:

View file

@ -30,7 +30,7 @@ object Object
tag base1 tag base1
case one: Variant1 case one: Variant1
case two: Variant2 case two: Variant2
if IFTWO if OrderedDict([('any', ['IFONE', 'IFTWO'])])
feature union-feat1 feature union-feat1
object q_obj_Variant1-wrapper object q_obj_Variant1-wrapper
member data: Variant1 optional=False member data: Variant1 optional=False

View file

@ -120,7 +120,8 @@ Members
The members of "Base" The members of "Base"
The members of "Variant1" when "base1" is ""one"" The members of "Variant1" when "base1" is ""one""
The members of "Variant2" when "base1" is ""two"" (**If: **"IFTWO") The members of "Variant2" when "base1" is ""two"" (**If: **"(IFONE or
IFTWO)")
Features Features
~~~~~~~~ ~~~~~~~~

View file

@ -1,3 +1,3 @@
enum-if-invalid.json: In enum 'TestIfEnum': enum-if-invalid.json: In enum 'TestIfEnum':
enum-if-invalid.json:2: 'if' condition has unknown key 'val' enum-if-invalid.json:2: 'if' condition has unknown key 'val'
Valid keys are 'all'. Valid keys are 'all', 'any'.

View file

@ -291,6 +291,11 @@
'features': [ { 'name': 'feature1', 'features': [ { 'name': 'feature1',
'if': { 'all': [ 'defined(TEST_IF_COND_1)', 'if': { 'all': [ 'defined(TEST_IF_COND_1)',
'defined(TEST_IF_COND_2)'] } } ] } 'defined(TEST_IF_COND_2)'] } } ] }
{ 'struct': 'CondFeatureStruct4',
'data': { 'foo': 'int' },
'features': [ { 'name': 'feature1',
'if': {'any': ['defined(TEST_IF_COND_1)',
'defined(TEST_IF_COND_2)'] } } ] }
{ 'enum': 'FeatureEnum1', { 'enum': 'FeatureEnum1',
'data': [ 'eins', 'zwei', 'drei' ], 'data': [ 'eins', 'zwei', 'drei' ],
@ -314,7 +319,8 @@
'*fs4': 'FeatureStruct4', '*fs4': 'FeatureStruct4',
'*cfs1': 'CondFeatureStruct1', '*cfs1': 'CondFeatureStruct1',
'*cfs2': 'CondFeatureStruct2', '*cfs2': 'CondFeatureStruct2',
'*cfs3': 'CondFeatureStruct3' }, '*cfs3': 'CondFeatureStruct3',
'*cfs4': 'CondFeatureStruct4' },
'returns': 'FeatureStruct1', 'returns': 'FeatureStruct1',
'features': [] } 'features': [] }

View file

@ -390,6 +390,10 @@ object CondFeatureStruct3
member foo: int optional=False member foo: int optional=False
feature feature1 feature feature1
if OrderedDict([('all', ['defined(TEST_IF_COND_1)', 'defined(TEST_IF_COND_2)'])]) if OrderedDict([('all', ['defined(TEST_IF_COND_1)', 'defined(TEST_IF_COND_2)'])])
object CondFeatureStruct4
member foo: int optional=False
feature feature1
if OrderedDict([('any', ['defined(TEST_IF_COND_1)', 'defined(TEST_IF_COND_2)'])])
enum FeatureEnum1 enum FeatureEnum1
member eins member eins
member zwei member zwei
@ -417,6 +421,7 @@ object q_obj_test-features0-arg
member cfs1: CondFeatureStruct1 optional=True member cfs1: CondFeatureStruct1 optional=True
member cfs2: CondFeatureStruct2 optional=True member cfs2: CondFeatureStruct2 optional=True
member cfs3: CondFeatureStruct3 optional=True member cfs3: CondFeatureStruct3 optional=True
member cfs4: CondFeatureStruct4 optional=True
command test-features0 q_obj_test-features0-arg -> FeatureStruct1 command test-features0 q_obj_test-features0-arg -> FeatureStruct1
gen=True success_response=True boxed=False oob=False preconfig=False gen=True success_response=True boxed=False oob=False preconfig=False
command test-command-features1 None -> None command test-command-features1 None -> None

View file

@ -51,6 +51,7 @@ FeatureStruct1 *qmp_test_features0(bool has_fs0, FeatureStruct0 *fs0,
bool has_cfs1, CondFeatureStruct1 *cfs1, bool has_cfs1, CondFeatureStruct1 *cfs1,
bool has_cfs2, CondFeatureStruct2 *cfs2, bool has_cfs2, CondFeatureStruct2 *cfs2,
bool has_cfs3, CondFeatureStruct3 *cfs3, bool has_cfs3, CondFeatureStruct3 *cfs3,
bool has_cfs4, CondFeatureStruct4 *cfs4,
Error **errp) Error **errp)
{ {
return g_new0(FeatureStruct1, 1); return g_new0(FeatureStruct1, 1);