diff mbox

[RFC,v2,44/47] qapi: Pseudo-type '**' is now unused, drop it

Message ID 1435782155-31412-45-git-send-email-armbru@redhat.com
State New
Headers show

Commit Message

Markus Armbruster July 1, 2015, 8:22 p.m. UTC
'gen': false needs to stay for now, because netdev_add is still using
it.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 docs/qapi-code-gen.txt                               | 15 ++++-----------
 scripts/qapi.py                                      | 20 ++++----------------
 tests/Makefile                                       |  4 ++--
 tests/qapi-schema/args-returns-any.err               |  1 +
 ...type-bypass-no-gen.exit => args-returns-any.exit} |  0
 tests/qapi-schema/args-returns-any.json              |  6 ++++++
 .../{type-bypass-no-gen.out => args-returns-any.out} |  0
 tests/qapi-schema/flat-union-base-star.err           |  2 +-
 tests/qapi-schema/flat-union-base-star.json          |  2 +-
 tests/qapi-schema/type-bypass-no-gen.err             |  1 -
 tests/qapi-schema/type-bypass-no-gen.json            |  2 --
 tests/qapi-schema/type-bypass.err                    |  0
 tests/qapi-schema/type-bypass.exit                   |  1 -
 tests/qapi-schema/type-bypass.json                   |  2 --
 tests/qapi-schema/type-bypass.out                    |  4 ----
 15 files changed, 19 insertions(+), 41 deletions(-)
 create mode 100644 tests/qapi-schema/args-returns-any.err
 rename tests/qapi-schema/{type-bypass-no-gen.exit => args-returns-any.exit} (100%)
 create mode 100644 tests/qapi-schema/args-returns-any.json
 rename tests/qapi-schema/{type-bypass-no-gen.out => args-returns-any.out} (100%)
 delete mode 100644 tests/qapi-schema/type-bypass-no-gen.err
 delete mode 100644 tests/qapi-schema/type-bypass-no-gen.json
 delete mode 100644 tests/qapi-schema/type-bypass.err
 delete mode 100644 tests/qapi-schema/type-bypass.exit
 delete mode 100644 tests/qapi-schema/type-bypass.json
 delete mode 100644 tests/qapi-schema/type-bypass.out

Comments

Eric Blake July 23, 2015, 11:20 p.m. UTC | #1
On 07/01/2015 02:22 PM, Markus Armbruster wrote:
> 'gen': false needs to stay for now, because netdev_add is still using
> it.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  docs/qapi-code-gen.txt                               | 15 ++++-----------
>  scripts/qapi.py                                      | 20 ++++----------------
>  tests/Makefile                                       |  4 ++--
>  tests/qapi-schema/args-returns-any.err               |  1 +
>  ...type-bypass-no-gen.exit => args-returns-any.exit} |  0

> 
> diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
> index 2367c66..ca578dd 100644
> --- a/docs/qapi-code-gen.txt
> +++ b/docs/qapi-code-gen.txt

> @@ -457,13 +454,9 @@ which would validate this Client JSON Protocol transaction:
>  
>  In rare cases, QAPI cannot express a type-safe representation of a
>  corresponding Client JSON Protocol command.  In these cases, if the
> -command expression includes the key 'gen' with boolean value false,
> -then the 'data' or 'returns' member that intends to bypass generated
> -type-safety and do its own manual validation should use an inline
> -dictionary definition, with a value of '**' rather than a valid type
> -name for the keys that the generated code will not validate.  Please
> -try to avoid adding new commands that rely on this, and instead use
> -type-safe unions.  For an example of bypass usage:
> +command expression includes the key 'gen' with boolean value false.

Incomplete sentence.  "if the command expression includes... false"
needs "then something...".

> +Please try to avoid adding new commands that rely on this, and instead
> +use type-safe unions.  For an example of bypass usage:

And given my ideas, we may be able to make netdev_add typesafe and
eliminate 'gen' altogether in the future :)

> +++ b/tests/Makefile
> @@ -222,11 +222,11 @@ check-qapi-schema-y := $(addprefix tests/qapi-schema/, \
>  	bad-type-dict.json double-data.json unknown-expr-key.json \
>  	redefined-type.json redefined-command.json redefined-builtin.json \
>  	redefined-event.json command-int.json bad-data.json event-max.json \
> -	type-bypass.json type-bypass-no-gen.json type-bypass-bad-gen.json \
> +	type-bypass-bad-gen.json \

If I understand correctly (git didn't quite guess right),
type-bypass-no-gen.json disappears completely (we no longer have working
'**'), and type-bypass.json...

>  	data-array-empty.json data-array-unknown.json data-int.json \
>  	data-unknown.json data-member-unknown.json data-member-array.json \
>  	data-member-array-bad.json args-union.json args-alternate.json \
> -	returns-array-bad.json returns-int.json \
> +	args-returns-any.json returns-array-bad.json returns-int.json \

...gets renamed args-returns-any.json (because type bypass is now
expressed via 'any'.

> +# built-in type 'any' in arguments and returns
> +# works except for 'data': 'any', because that has to be a struct
> +# note: command name 'qom-get' chosen to avoid "cannot use built-in" error
> +{ 'command': 'qom-get', 'data': { 'arg': 'any' }, 'returns': 'any' }
> +{ 'command': 'foo', 'returns': { 'arg': 'any' } }
> +{ 'command': 'bar', 'data': 'any' }

This shows what the parser accepts and rejects, but doesn't prove it
compiles to C; and the previous patch that touched
test-qmp-input-visitor.c was testing that the low-level interactions
worked but did not map it all the way back to qapi.  I wonder if you
should also enhance qapi-schema-test to use 'any', since that tends to
be the one test that most fully exercises interactions with generated
code based on a valid qapi schema.


On the right track, but I want to make sure the botched documentation is
correct before giving R-b.
Markus Armbruster July 28, 2015, 12:24 p.m. UTC | #2
Eric Blake <eblake@redhat.com> writes:

> On 07/01/2015 02:22 PM, Markus Armbruster wrote:
>> 'gen': false needs to stay for now, because netdev_add is still using
>> it.
>> 
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---
>>  docs/qapi-code-gen.txt                               | 15 ++++-----------
>>  scripts/qapi.py                                      | 20 ++++----------------
>>  tests/Makefile                                       |  4 ++--
>>  tests/qapi-schema/args-returns-any.err               |  1 +
>>  ...type-bypass-no-gen.exit => args-returns-any.exit} |  0
>
>> 
>> diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
>> index 2367c66..ca578dd 100644
>> --- a/docs/qapi-code-gen.txt
>> +++ b/docs/qapi-code-gen.txt
>
>> @@ -457,13 +454,9 @@ which would validate this Client JSON Protocol transaction:
>>  
>>  In rare cases, QAPI cannot express a type-safe representation of a
>>  corresponding Client JSON Protocol command.  In these cases, if the
>> -command expression includes the key 'gen' with boolean value false,
>> -then the 'data' or 'returns' member that intends to bypass generated
>> -type-safety and do its own manual validation should use an inline
>> -dictionary definition, with a value of '**' rather than a valid type
>> -name for the keys that the generated code will not validate.  Please
>> -try to avoid adding new commands that rely on this, and instead use
>> -type-safe unions.  For an example of bypass usage:
>> +command expression includes the key 'gen' with boolean value false.
>
> Incomplete sentence.  "if the command expression includes... false"
> needs "then something...".

Oops.  I'll rephrase.

>> +Please try to avoid adding new commands that rely on this, and instead
>> +use type-safe unions.  For an example of bypass usage:
>
> And given my ideas, we may be able to make netdev_add typesafe and
> eliminate 'gen' altogether in the future :)

The harder problem is qapifying device_add without use of 'gen': false.
It's structurally just like netdev_add, "only" with has many, many more
variants (the device models), which are collected only at run time.

Changing things to define device model properties in the schema seems
unappealing.

We could try to collect them at build time.  Not trivial.

We could collect them at run time, but then the schema becomes dynamic.
Not trivial, either.

The easiest solution is probably something like Python's **kwds
parameter: collect any remaining arguments in a dictionary, and pass
that as argument kwds.  Sadly, QAPI introspection remains useless for
device models then.

>> +++ b/tests/Makefile
>> @@ -222,11 +222,11 @@ check-qapi-schema-y := $(addprefix tests/qapi-schema/, \
>>  	bad-type-dict.json double-data.json unknown-expr-key.json \
>>  	redefined-type.json redefined-command.json redefined-builtin.json \
>>  	redefined-event.json command-int.json bad-data.json event-max.json \
>> -	type-bypass.json type-bypass-no-gen.json type-bypass-bad-gen.json \
>> +	type-bypass-bad-gen.json \
>
> If I understand correctly (git didn't quite guess right),
> type-bypass-no-gen.json disappears completely (we no longer have working
> '**'), and type-bypass.json...
>
>>  	data-array-empty.json data-array-unknown.json data-int.json \
>>  	data-unknown.json data-member-unknown.json data-member-array.json \
>>  	data-member-array-bad.json args-union.json args-alternate.json \
>> -	returns-array-bad.json returns-int.json \
>> +	args-returns-any.json returns-array-bad.json returns-int.json \
>
> ...gets renamed args-returns-any.json (because type bypass is now
> expressed via 'any'.

I'd view args-returns-any.json as new.  But viewing it as a replacement
for type-bypass.json is okay.

>> +# built-in type 'any' in arguments and returns
>> +# works except for 'data': 'any', because that has to be a struct
>> +# note: command name 'qom-get' chosen to avoid "cannot use built-in" error
>> +{ 'command': 'qom-get', 'data': { 'arg': 'any' }, 'returns': 'any' }
>> +{ 'command': 'foo', 'returns': { 'arg': 'any' } }
>> +{ 'command': 'bar', 'data': 'any' }
>
> This shows what the parser accepts and rejects, but doesn't prove it
> compiles to C; and the previous patch that touched
> test-qmp-input-visitor.c was testing that the low-level interactions
> worked but did not map it all the way back to qapi.  I wonder if you
> should also enhance qapi-schema-test to use 'any', since that tends to
> be the one test that most fully exercises interactions with generated
> code based on a valid qapi schema.

I guess I'll have to split args-returns-any.json: move the positive test
cases to qapi-schema-test.json, move the negative test case to its own
test.

> On the right track, but I want to make sure the botched documentation is
> correct before giving R-b.

Thanks!
diff mbox

Patch

diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
index 2367c66..ca578dd 100644
--- a/docs/qapi-code-gen.txt
+++ b/docs/qapi-code-gen.txt
@@ -111,10 +111,7 @@  and field names within a type, should be all lower case with words
 separated by a hyphen.  However, some existing older commands and
 complex types use underscore; when extending such expressions,
 consistency is preferred over blindly avoiding underscore.  Event
-names should be ALL_CAPS with words separated by underscore.  The
-special string '**' appears for some commands that manually perform
-their own type checking rather than relying on the type-safe code
-produced by the qapi code generators.
+names should be ALL_CAPS with words separated by underscore.
 
 Any name (command, event, type, field, or enum value) beginning with
 "x-" is marked experimental, and may be withdrawn or changed
@@ -457,13 +454,9 @@  which would validate this Client JSON Protocol transaction:
 
 In rare cases, QAPI cannot express a type-safe representation of a
 corresponding Client JSON Protocol command.  In these cases, if the
-command expression includes the key 'gen' with boolean value false,
-then the 'data' or 'returns' member that intends to bypass generated
-type-safety and do its own manual validation should use an inline
-dictionary definition, with a value of '**' rather than a valid type
-name for the keys that the generated code will not validate.  Please
-try to avoid adding new commands that rely on this, and instead use
-type-safe unions.  For an example of bypass usage:
+command expression includes the key 'gen' with boolean value false.
+Please try to avoid adding new commands that rely on this, and instead
+use type-safe unions.  For an example of bypass usage:
 
  { 'command': 'netdev_add',
    'data': {'type': 'str', 'id': 'str'},
diff --git a/scripts/qapi.py b/scripts/qapi.py
index df63130..6ddb33e 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -423,16 +423,13 @@  def is_enum(name):
 
 def check_type(expr_info, source, value, allow_array = False,
                allow_dict = False, allow_optional = False,
-               allow_star = False, allow_metas = []):
+               allow_metas = []):
     global all_names
     orig_value = value
 
     if value is None:
         return
 
-    if allow_star and value == '**':
-        return
-
     # Check if array type for value is okay
     if isinstance(value, list):
         if not allow_array:
@@ -447,10 +444,6 @@  def check_type(expr_info, source, value, allow_array = False,
 
     # Check if type name for value is okay
     if isinstance(value, str):
-        if value == '**':
-            raise QAPIExprError(expr_info,
-                                "%s uses '**' but did not request 'gen':false"
-                                % source)
         if not value in all_names:
             raise QAPIExprError(expr_info,
                                 "%s uses unknown type '%s'"
@@ -474,7 +467,7 @@  def check_type(expr_info, source, value, allow_array = False,
         # Todo: allow dictionaries to represent default values of
         # an optional argument.
         check_type(expr_info, "Member '%s' of %s" % (key, source), arg,
-                   allow_array=True, allow_star=allow_star,
+                   allow_array=True,
                    allow_metas=['built-in', 'union', 'alternate', 'struct',
                                 'enum'])
 
@@ -494,18 +487,16 @@  def check_member_clash(expr_info, base_name, data, source = ""):
 
 def check_command(expr, expr_info):
     name = expr['command']
-    allow_star = expr.has_key('gen')
 
     check_type(expr_info, "'data' for command '%s'" % name,
                expr.get('data'), allow_dict=True, allow_optional=True,
-               allow_metas=['struct'], allow_star=allow_star)
+               allow_metas=['struct'])
     returns_meta = ['union', 'struct']
     if name in returns_whitelist:
         returns_meta += ['built-in', 'alternate', 'enum']
     check_type(expr_info, "'returns' for command '%s'" % name,
                expr.get('returns'), allow_array=True, allow_dict=True,
-               allow_optional=True, allow_metas=returns_meta,
-               allow_star=allow_star)
+               allow_optional=True, allow_metas=returns_meta)
 
 def check_event(expr, expr_info):
     global events
@@ -1051,7 +1042,6 @@  class QAPISchema(object):
                   ('bool',   'boolean', 'bool',     'false'),
                   ('any',    'value',   'QObject' + pointer_suffix , 'NULL')]:
             self._def_builtin_type(*t)
-        self.entity_dict['**'] = self.lookup_type('any') # TODO drop this alias
 
     def _make_implicit_enum_type(self, name, values):
         name = name + 'Kind'
@@ -1192,8 +1182,6 @@  class QAPISchema(object):
     def visit(self, visitor):
         visitor.visit_begin()
         for name in sorted(self.entity_dict.keys()):
-            if self.entity_dict[name].name != name:
-                continue        # ignore alias TODO drop alias and remove
             self.entity_dict[name].visit(visitor)
         visitor.visit_end()
 
diff --git a/tests/Makefile b/tests/Makefile
index 5a38748..60b82e2 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -222,11 +222,11 @@  check-qapi-schema-y := $(addprefix tests/qapi-schema/, \
 	bad-type-dict.json double-data.json unknown-expr-key.json \
 	redefined-type.json redefined-command.json redefined-builtin.json \
 	redefined-event.json command-int.json bad-data.json event-max.json \
-	type-bypass.json type-bypass-no-gen.json type-bypass-bad-gen.json \
+	type-bypass-bad-gen.json \
 	data-array-empty.json data-array-unknown.json data-int.json \
 	data-unknown.json data-member-unknown.json data-member-array.json \
 	data-member-array-bad.json args-union.json args-alternate.json \
-	returns-array-bad.json returns-int.json \
+	args-returns-any.json returns-array-bad.json returns-int.json \
 	returns-unknown.json returns-alternate.json returns-whitelist.json \
 	missing-colon.json missing-comma-list.json missing-comma-object.json \
 	nested-struct-data.json nested-struct-returns.json non-objects.json \
diff --git a/tests/qapi-schema/args-returns-any.err b/tests/qapi-schema/args-returns-any.err
new file mode 100644
index 0000000..f7ce727
--- /dev/null
+++ b/tests/qapi-schema/args-returns-any.err
@@ -0,0 +1 @@ 
+tests/qapi-schema/args-returns-any.json:6: 'data' for command 'bar' cannot use built-in type 'any'
diff --git a/tests/qapi-schema/type-bypass-no-gen.exit b/tests/qapi-schema/args-returns-any.exit
similarity index 100%
rename from tests/qapi-schema/type-bypass-no-gen.exit
rename to tests/qapi-schema/args-returns-any.exit
diff --git a/tests/qapi-schema/args-returns-any.json b/tests/qapi-schema/args-returns-any.json
new file mode 100644
index 0000000..a74fc6f
--- /dev/null
+++ b/tests/qapi-schema/args-returns-any.json
@@ -0,0 +1,6 @@ 
+# built-in type 'any' in arguments and returns
+# works except for 'data': 'any', because that has to be a struct
+# note: command name 'qom-get' chosen to avoid "cannot use built-in" error
+{ 'command': 'qom-get', 'data': { 'arg': 'any' }, 'returns': 'any' }
+{ 'command': 'foo', 'returns': { 'arg': 'any' } }
+{ 'command': 'bar', 'data': 'any' }
diff --git a/tests/qapi-schema/type-bypass-no-gen.out b/tests/qapi-schema/args-returns-any.out
similarity index 100%
rename from tests/qapi-schema/type-bypass-no-gen.out
rename to tests/qapi-schema/args-returns-any.out
diff --git a/tests/qapi-schema/flat-union-base-star.err b/tests/qapi-schema/flat-union-base-star.err
index b7748f0..43e5aa4 100644
--- a/tests/qapi-schema/flat-union-base-star.err
+++ b/tests/qapi-schema/flat-union-base-star.err
@@ -1 +1 @@ 
-tests/qapi-schema/flat-union-base-star.json:8: Base '**' is not a valid struct
+tests/qapi-schema/flat-union-base-star.json:8: Base 'any' is not a valid struct
diff --git a/tests/qapi-schema/flat-union-base-star.json b/tests/qapi-schema/flat-union-base-star.json
index 5099439..fe66b71 100644
--- a/tests/qapi-schema/flat-union-base-star.json
+++ b/tests/qapi-schema/flat-union-base-star.json
@@ -6,7 +6,7 @@ 
 { 'struct': 'TestTypeB',
   'data': { 'integer': 'int' } }
 { 'union': 'TestUnion',
-  'base': '**',
+  'base': 'any',
   'discriminator': 'enum1',
   'data': { 'value1': 'TestTypeA',
             'value2': 'TestTypeB' } }
diff --git a/tests/qapi-schema/type-bypass-no-gen.err b/tests/qapi-schema/type-bypass-no-gen.err
deleted file mode 100644
index 20cef0a..0000000
--- a/tests/qapi-schema/type-bypass-no-gen.err
+++ /dev/null
@@ -1 +0,0 @@ 
-tests/qapi-schema/type-bypass-no-gen.json:2: Member 'arg' of 'data' for command 'unsafe' uses '**' but did not request 'gen':false
diff --git a/tests/qapi-schema/type-bypass-no-gen.json b/tests/qapi-schema/type-bypass-no-gen.json
deleted file mode 100644
index 4feae37..0000000
--- a/tests/qapi-schema/type-bypass-no-gen.json
+++ /dev/null
@@ -1,2 +0,0 @@ 
-# type bypass only works with 'gen':false
-{ 'command': 'unsafe', 'data': { 'arg': '**' }, 'returns': '**' }
diff --git a/tests/qapi-schema/type-bypass.err b/tests/qapi-schema/type-bypass.err
deleted file mode 100644
index e69de29..0000000
diff --git a/tests/qapi-schema/type-bypass.exit b/tests/qapi-schema/type-bypass.exit
deleted file mode 100644
index 573541a..0000000
--- a/tests/qapi-schema/type-bypass.exit
+++ /dev/null
@@ -1 +0,0 @@ 
-0
diff --git a/tests/qapi-schema/type-bypass.json b/tests/qapi-schema/type-bypass.json
deleted file mode 100644
index 48b2137..0000000
--- a/tests/qapi-schema/type-bypass.json
+++ /dev/null
@@ -1,2 +0,0 @@ 
-# Use of 'gen':false allows bypassing type system
-{ 'command': 'unsafe', 'data': { 'arg': '**' }, 'returns': '**', 'gen': false }
diff --git a/tests/qapi-schema/type-bypass.out b/tests/qapi-schema/type-bypass.out
deleted file mode 100644
index 2dc0c09..0000000
--- a/tests/qapi-schema/type-bypass.out
+++ /dev/null
@@ -1,4 +0,0 @@ 
-object :obj-unsafe-args
-    member arg: any optional=False
-command unsafe :obj-unsafe-args -> any
-   gen=False success_response=True