From 2b7d2145369f2ca55ded9045393bb860ee3f6745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 4 Aug 2021 12:31:04 +0400 Subject: qapi: add 'not' condition operation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For the sake of completeness, introduce the 'not' condition. Signed-off-by: Marc-André Lureau Message-Id: <20210804083105.97531-10-marcandre.lureau@redhat.com> Reviewed-by: Markus Armbruster [Long line broken in tests/qapi-schema/qapi-schema-test.json] Signed-off-by: Markus Armbruster --- scripts/qapi/common.py | 4 ++++ scripts/qapi/expr.py | 7 +++++-- tests/qapi-schema/bad-if-key.err | 2 +- tests/qapi-schema/bad-if-keys.err | 2 +- tests/qapi-schema/doc-good.json | 3 ++- tests/qapi-schema/doc-good.out | 1 + tests/qapi-schema/doc-good.txt | 6 ++++++ tests/qapi-schema/enum-if-invalid.err | 2 +- tests/qapi-schema/qapi-schema-test.json | 3 ++- tests/qapi-schema/qapi-schema-test.out | 4 ++-- 10 files changed, 25 insertions(+), 9 deletions(-) diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index 63a2e50..3fb2fbe 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -207,6 +207,8 @@ def cgen_ifcond(ifcond: Union[str, Dict[str, Any]]) -> str: return ifcond oper, operands = next(iter(ifcond.items())) + if oper == 'not': + return '!' + cgen_ifcond(operands) oper = {'all': '&&', 'any': '||'}[oper] operands = [cgen_ifcond(o) for o in operands] return '(' + (') ' + oper + ' (').join(operands) + ')' @@ -220,6 +222,8 @@ def docgen_ifcond(ifcond: Union[str, Dict[str, Any]]) -> str: return ifcond oper, operands = next(iter(ifcond.items())) + if oper == 'not': + return '!' + docgen_ifcond(operands) oper = {'all': ' and ', 'any': ' or '}[oper] operands = [docgen_ifcond(o) for o in operands] return '(' + oper.join(operands) + ')' diff --git a/scripts/qapi/expr.py b/scripts/qapi/expr.py index f3ce10f..120b310 100644 --- a/scripts/qapi/expr.py +++ b/scripts/qapi/expr.py @@ -290,15 +290,18 @@ def check_if(expr: _JSONObject, info: QAPISourceInfo, source: str) -> None: raise QAPISemError( info, "'if' condition dict of %s must have one key: " - "'all' or 'any'" % source) + "'all', 'any' or 'not'" % source) check_keys(cond, info, "'if' condition", [], - ["all", "any"]) + ["all", "any", "not"]) oper, operands = next(iter(cond.items())) if not operands: raise QAPISemError( info, "'if' condition [] of %s is useless" % source) + if oper == "not": + _check_if(operands) + return if oper in ("all", "any") and not isinstance(operands, list): raise QAPISemError( info, "'%s' condition of %s must be an array" % (oper, source)) diff --git a/tests/qapi-schema/bad-if-key.err b/tests/qapi-schema/bad-if-key.err index 7236f46..a69dc9e 100644 --- a/tests/qapi-schema/bad-if-key.err +++ b/tests/qapi-schema/bad-if-key.err @@ -1,3 +1,3 @@ bad-if-key.json: In struct 'TestIfStruct': bad-if-key.json:2: 'if' condition has unknown key 'value' -Valid keys are 'all', 'any'. +Valid keys are 'all', 'any', 'not'. diff --git a/tests/qapi-schema/bad-if-keys.err b/tests/qapi-schema/bad-if-keys.err index db6d019..aceb31d 100644 --- a/tests/qapi-schema/bad-if-keys.err +++ b/tests/qapi-schema/bad-if-keys.err @@ -1,2 +1,2 @@ bad-if-keys.json: In struct 'TestIfStruct': -bad-if-keys.json:2: 'if' condition dict of struct must have one key: 'all' or 'any' +bad-if-keys.json:2: 'if' condition dict of struct must have one key: 'all', 'any' or 'not' diff --git a/tests/qapi-schema/doc-good.json b/tests/qapi-schema/doc-good.json index e253d89..2a35c67 100644 --- a/tests/qapi-schema/doc-good.json +++ b/tests/qapi-schema/doc-good.json @@ -126,7 +126,8 @@ ## { 'alternate': 'Alternate', 'features': [ 'alt-feat' ], - 'data': { 'i': 'int', 'b': 'bool' } } + 'data': { 'i': 'int', 'b': 'bool' }, + 'if': { 'not': 'IFNOT' } } ## # == Another subsection diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out index c44c346..a8871e8 100644 --- a/tests/qapi-schema/doc-good.out +++ b/tests/qapi-schema/doc-good.out @@ -51,6 +51,7 @@ alternate Alternate tag type case i: int case b: bool + if OrderedDict([('not', 'IFNOT')]) feature alt-feat object q_obj_cmd-arg member arg1: int optional=False diff --git a/tests/qapi-schema/doc-good.txt b/tests/qapi-schema/doc-good.txt index 251e9b7..03c98c4 100644 --- a/tests/qapi-schema/doc-good.txt +++ b/tests/qapi-schema/doc-good.txt @@ -171,6 +171,12 @@ Features a feature +If +~~ + +"!IFNOT" + + Another subsection ================== diff --git a/tests/qapi-schema/enum-if-invalid.err b/tests/qapi-schema/enum-if-invalid.err index b96d94c..3bb8407 100644 --- a/tests/qapi-schema/enum-if-invalid.err +++ b/tests/qapi-schema/enum-if-invalid.err @@ -1,3 +1,3 @@ enum-if-invalid.json: In enum 'TestIfEnum': enum-if-invalid.json:2: 'if' condition has unknown key 'val' -Valid keys are 'all', 'any'. +Valid keys are 'all', 'any', 'not'. diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json index 7737b32..a700f25 100644 --- a/tests/qapi-schema/qapi-schema-test.json +++ b/tests/qapi-schema/qapi-schema-test.json @@ -245,7 +245,8 @@ { 'command': 'test-if-alternate-cmd', 'data': { 'alt-cmd-arg': 'TestIfAlternate' }, - 'if': { 'all': ['defined(TEST_IF_ALT)'] } } + 'if': { 'all': ['defined(TEST_IF_ALT)', + {'not': 'defined(TEST_IF_NOT_ALT)'}] } } { 'command': 'test-if-cmd', 'data': { diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out index 2f067d5..53e12f3 100644 --- a/tests/qapi-schema/qapi-schema-test.out +++ b/tests/qapi-schema/qapi-schema-test.out @@ -333,10 +333,10 @@ alternate TestIfAlternate if OrderedDict([('all', ['defined(TEST_IF_ALT)', 'defined(TEST_IF_STRUCT)'])]) object q_obj_test-if-alternate-cmd-arg member alt-cmd-arg: TestIfAlternate optional=False - if OrderedDict([('all', ['defined(TEST_IF_ALT)'])]) + if OrderedDict([('all', ['defined(TEST_IF_ALT)', OrderedDict([('not', 'defined(TEST_IF_NOT_ALT)')])])]) command test-if-alternate-cmd q_obj_test-if-alternate-cmd-arg -> None gen=True success_response=True boxed=False oob=False preconfig=False - if OrderedDict([('all', ['defined(TEST_IF_ALT)'])]) + if OrderedDict([('all', ['defined(TEST_IF_ALT)', OrderedDict([('not', 'defined(TEST_IF_NOT_ALT)')])])]) object q_obj_test-if-cmd-arg member foo: TestIfStruct optional=False member bar: TestIfEnum optional=False -- cgit v1.1