QAPI patches patches for 2021-02-18

-----BEGIN PGP SIGNATURE-----
 
 iQJGBAABCAAwFiEENUvIs9frKmtoZ05fOHC0AOuRhlMFAmAutzcSHGFybWJydUBy
 ZWRoYXQuY29tAAoJEDhwtADrkYZTvBsP/jI3Dh9j8HLLsvauU117LcIGnn5Qwog4
 8v0IrEieaOeMDNDzR8AgSqBLYm0ZQcBoZl7Qkv8XMxYa7iWiJv2uCShRS7MNl5NK
 M8IW0XWVjCJJ7TfFGj5iP/zlnhBMTzp66EDfkdiBWlig7NdZ+TBVp+WiZr8mT7EJ
 MdI2slzmgChDHJ2BLntLDt3w778GUIIXYxNFAhH4woAs6Xq7Z8tq3y+7c9JMXL/1
 B1esVN49h582mcldT5LcMK1AWOjxon+IaKS5KloMcr/uVCqaineSR/rPTXI4k9RL
 KfKeetniOz0ohyD+4dfLYW7OPhjJ3ZiUm6tSP6aVcg8D8qJAEvocw1uZS3iFpR5T
 lqdS6rcaumx3FaPix3MmhbNJLytohiAvvJyHpjLQ32ByhJ2FPzUOLFyRvoeoE+kD
 wJSTLn0iyjIlY3bz4sdA3STWK9TyKJ8enyRWGGZECL0ZJwCUe/Z7KwxZi7Ad4vLl
 j/os65T+XudTEJzk4iKpA03ThvAs82q34mpSkpACfDA9VZ584fRC79WbQoVAGmrk
 3CV4vfBS3pcPz7nCQqauTGWg3iqQT4iKYGdw9YTqA88kIk/swfPiucGrAwI1WPXz
 VReMbz/LBBa8gLb2Sx4MMlRjO/v/WlOyxJ1sfdETmiX+ZjUl8s7+94PwlWI2kT6k
 3r9bl3Tz+QlZ
 =pIh0
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2021-02-18' into staging

QAPI patches patches for 2021-02-18

# gpg: Signature made Thu 18 Feb 2021 18:51:35 GMT
# gpg:                using RSA key 354BC8B3D7EB2A6B68674E5F3870B400EB918653
# gpg:                issuer "armbru@redhat.com"
# gpg: Good signature from "Markus Armbruster <armbru@redhat.com>" [full]
# gpg:                 aka "Markus Armbruster <armbru@pond.sub.org>" [full]
# Primary key fingerprint: 354B C8B3 D7EB 2A6B 6867  4E5F 3870 B400 EB91 8653

* remotes/armbru/tags/pull-qapi-2021-02-18:
  qapi/introspect.py: set _gen_tree's default ifcond argument to ()
  qapi/introspect.py: Type _gen_tree variants as Sequence[str]
  qapi/introspect.py: Update copyright and authors list
  qapi/introspect.py: Add docstrings to _gen_tree and _tree_to_qlit
  qapi/introspect.py: add type hint annotations
  qapi/introspect.py: remove _gen_variants helper
  qapi/introspect.py: improve readability of _tree_to_qlit
  qapi/introspect.py: improve _tree_to_qlit error message
  qapi/introspect.py: create a typed 'Annotated' data strutcure
  qapi/introspect.py: Introduce preliminary tree typing
  qapi/introspect.py: Always define all 'extra' dict keys
  qapi/introspect.py: replace 'extra' dict with 'comment' argument
  qapi/introspect.py: Unify return type of _make_tree()
  qapi/introspect.py: guard against ifcond/comment misuse
  qapi/introspect.py: add _gen_features helper
  qapi/introspect.py: use _make_tree for features nodes
  qapi/introspect.py: assert schema is not None
  qapi: Replace List[str] with Sequence[str] for ifcond

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2021-02-19 17:22:42 +00:00
commit e90ef02389
8 changed files with 255 additions and 120 deletions

View File

@ -17,6 +17,7 @@ from typing import (
Dict, Dict,
List, List,
Optional, Optional,
Sequence,
Set, Set,
) )
@ -297,7 +298,7 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds)
def visit_command(self, def visit_command(self,
name: str, name: str,
info: Optional[QAPISourceInfo], info: Optional[QAPISourceInfo],
ifcond: List[str], ifcond: Sequence[str],
features: List[QAPISchemaFeature], features: List[QAPISchemaFeature],
arg_type: Optional[QAPISchemaObjectType], arg_type: Optional[QAPISchemaObjectType],
ret_type: Optional[QAPISchemaType], ret_type: Optional[QAPISchemaType],

View File

@ -12,7 +12,7 @@ This work is licensed under the terms of the GNU GPL, version 2.
See the COPYING file in the top-level directory. See the COPYING file in the top-level directory.
""" """
from typing import List, Optional from typing import List, Optional, Sequence
from .common import c_enum_const, c_name, mcgen from .common import c_enum_const, c_name, mcgen
from .gen import QAPISchemaModularCVisitor, build_params, ifcontext from .gen import QAPISchemaModularCVisitor, build_params, ifcontext
@ -214,7 +214,7 @@ void %(event_emit)s(%(event_enum)s event, QDict *qdict);
def visit_event(self, def visit_event(self,
name: str, name: str,
info: Optional[QAPISourceInfo], info: Optional[QAPISourceInfo],
ifcond: List[str], ifcond: Sequence[str],
features: List[QAPISchemaFeature], features: List[QAPISchemaFeature],
arg_type: Optional[QAPISchemaObjectType], arg_type: Optional[QAPISchemaObjectType],
boxed: bool) -> None: boxed: bool) -> None:

View File

@ -17,8 +17,8 @@ import re
from typing import ( from typing import (
Dict, Dict,
Iterator, Iterator,
List,
Optional, Optional,
Sequence,
Tuple, Tuple,
) )
@ -85,7 +85,7 @@ class QAPIGen:
fp.write(text) fp.write(text)
def _wrap_ifcond(ifcond: List[str], before: str, after: str) -> str: def _wrap_ifcond(ifcond: Sequence[str], before: str, after: str) -> str:
if before == after: if before == after:
return after # suppress empty #if ... #endif return after # suppress empty #if ... #endif
@ -127,9 +127,9 @@ def build_params(arg_type: Optional[QAPISchemaObjectType],
class QAPIGenCCode(QAPIGen): class QAPIGenCCode(QAPIGen):
def __init__(self, fname: str): def __init__(self, fname: str):
super().__init__(fname) super().__init__(fname)
self._start_if: Optional[Tuple[List[str], str, str]] = None self._start_if: Optional[Tuple[Sequence[str], str, str]] = None
def start_if(self, ifcond: List[str]) -> None: def start_if(self, ifcond: Sequence[str]) -> None:
assert self._start_if is None assert self._start_if is None
self._start_if = (ifcond, self._body, self._preamble) self._start_if = (ifcond, self._body, self._preamble)
@ -187,11 +187,11 @@ class QAPIGenH(QAPIGenC):
@contextmanager @contextmanager
def ifcontext(ifcond: List[str], *args: QAPIGenCCode) -> Iterator[None]: def ifcontext(ifcond: Sequence[str], *args: QAPIGenCCode) -> Iterator[None]:
""" """
A with-statement context manager that wraps with `start_if()` / `end_if()`. A with-statement context manager that wraps with `start_if()` / `end_if()`.
:param ifcond: A list of conditionals, passed to `start_if()`. :param ifcond: A sequence of conditionals, passed to `start_if()`.
:param args: any number of `QAPIGenCCode`. :param args: any number of `QAPIGenCCode`.
Example:: Example::

View File

@ -1,15 +1,29 @@
""" """
QAPI introspection generator QAPI introspection generator
Copyright (C) 2015-2018 Red Hat, Inc. Copyright (C) 2015-2021 Red Hat, Inc.
Authors: Authors:
Markus Armbruster <armbru@redhat.com> Markus Armbruster <armbru@redhat.com>
John Snow <jsnow@redhat.com>
This work is licensed under the terms of the GNU GPL, version 2. This work is licensed under the terms of the GNU GPL, version 2.
See the COPYING file in the top-level directory. See the COPYING file in the top-level directory.
""" """
from typing import (
Any,
Dict,
Generic,
Iterable,
List,
Optional,
Sequence,
Tuple,
TypeVar,
Union,
)
from .common import ( from .common import (
c_name, c_name,
gen_endif, gen_endif,
@ -18,91 +32,158 @@ from .common import (
) )
from .gen import QAPISchemaMonolithicCVisitor from .gen import QAPISchemaMonolithicCVisitor
from .schema import ( from .schema import (
QAPISchema,
QAPISchemaArrayType, QAPISchemaArrayType,
QAPISchemaBuiltinType, QAPISchemaBuiltinType,
QAPISchemaEntity,
QAPISchemaEnumMember,
QAPISchemaFeature,
QAPISchemaObjectType,
QAPISchemaObjectTypeMember,
QAPISchemaType, QAPISchemaType,
QAPISchemaVariant,
QAPISchemaVariants,
) )
from .source import QAPISourceInfo
def _make_tree(obj, ifcond, features, extra=None): # This module constructs a tree data structure that is used to
if extra is None: # generate the introspection information for QEMU. It is shaped
extra = {} # like a JSON value.
if ifcond: #
extra['if'] = ifcond # A complexity over JSON is that our values may or may not be annotated.
if features: #
obj['features'] = [(f.name, {'if': f.ifcond}) for f in features] # Un-annotated values may be:
if extra: # Scalar: str, bool, None.
return (obj, extra) # Non-scalar: List, Dict
return obj # _value = Union[str, bool, None, Dict[str, JSONValue], List[JSONValue]]
#
# With optional annotations, the type of all values is:
# JSONValue = Union[_Value, Annotated[_Value]]
#
# Sadly, mypy does not support recursive types; so the _Stub alias is used to
# mark the imprecision in the type model where we'd otherwise use JSONValue.
_Stub = Any
_Scalar = Union[str, bool, None]
_NonScalar = Union[Dict[str, _Stub], List[_Stub]]
_Value = Union[_Scalar, _NonScalar]
JSONValue = Union[_Value, 'Annotated[_Value]']
# These types are based on structures defined in QEMU's schema, so we
# lack precise types for them here. Python 3.6 does not offer
# TypedDict constructs, so they are broadly typed here as simple
# Python Dicts.
SchemaInfo = Dict[str, object]
SchemaInfoObject = Dict[str, object]
SchemaInfoObjectVariant = Dict[str, object]
SchemaInfoObjectMember = Dict[str, object]
SchemaInfoCommand = Dict[str, object]
def _tree_to_qlit(obj, level=0, suppress_first_indent=False): _ValueT = TypeVar('_ValueT', bound=_Value)
def indent(level):
class Annotated(Generic[_ValueT]):
"""
Annotated generally contains a SchemaInfo-like type (as a dict),
But it also used to wrap comments/ifconds around scalar leaf values,
for the benefit of features and enums.
"""
# TODO: Remove after Python 3.7 adds @dataclass:
# pylint: disable=too-few-public-methods
def __init__(self, value: _ValueT, ifcond: Iterable[str],
comment: Optional[str] = None):
self.value = value
self.comment: Optional[str] = comment
self.ifcond: Tuple[str, ...] = tuple(ifcond)
def _tree_to_qlit(obj: JSONValue,
level: int = 0,
dict_value: bool = False) -> str:
"""
Convert the type tree into a QLIT C string, recursively.
:param obj: The value to convert.
This value may not be Annotated when dict_value is True.
:param level: The indentation level for this particular value.
:param dict_value: True when the value being processed belongs to a
dict key; which suppresses the output indent.
"""
def indent(level: int) -> str:
return level * 4 * ' ' return level * 4 * ' '
if isinstance(obj, tuple): if isinstance(obj, Annotated):
ifobj, extra = obj # NB: _tree_to_qlit is called recursively on the values of a
ifcond = extra.get('if') # key:value pair; those values can't be decorated with
comment = extra.get('comment') # comments or conditionals.
msg = "dict values cannot have attached comments or if-conditionals."
assert not dict_value, msg
ret = '' ret = ''
if comment: if obj.comment:
ret += indent(level) + '/* %s */\n' % comment ret += indent(level) + f"/* {obj.comment} */\n"
if ifcond: if obj.ifcond:
ret += gen_if(ifcond) ret += gen_if(obj.ifcond)
ret += _tree_to_qlit(ifobj, level) ret += _tree_to_qlit(obj.value, level)
if ifcond: if obj.ifcond:
ret += '\n' + gen_endif(ifcond) ret += '\n' + gen_endif(obj.ifcond)
return ret return ret
ret = '' ret = ''
if not suppress_first_indent: if not dict_value:
ret += indent(level) ret += indent(level)
# Scalars:
if obj is None: if obj is None:
ret += 'QLIT_QNULL' ret += 'QLIT_QNULL'
elif isinstance(obj, str): elif isinstance(obj, str):
ret += 'QLIT_QSTR(' + to_c_string(obj) + ')' ret += f"QLIT_QSTR({to_c_string(obj)})"
elif isinstance(obj, bool):
ret += f"QLIT_QBOOL({str(obj).lower()})"
# Non-scalars:
elif isinstance(obj, list): elif isinstance(obj, list):
elts = [_tree_to_qlit(elt, level + 1).strip('\n')
for elt in obj]
elts.append(indent(level + 1) + "{}")
ret += 'QLIT_QLIST(((QLitObject[]) {\n' ret += 'QLIT_QLIST(((QLitObject[]) {\n'
ret += '\n'.join(elts) + '\n' for value in obj:
ret += _tree_to_qlit(value, level + 1).strip('\n') + '\n'
ret += indent(level + 1) + '{}\n'
ret += indent(level) + '}))' ret += indent(level) + '}))'
elif isinstance(obj, dict): elif isinstance(obj, dict):
elts = []
for key, value in sorted(obj.items()):
elts.append(indent(level + 1) + '{ %s, %s }' %
(to_c_string(key),
_tree_to_qlit(value, level + 1, True)))
elts.append(indent(level + 1) + '{}')
ret += 'QLIT_QDICT(((QLitDictEntry[]) {\n' ret += 'QLIT_QDICT(((QLitDictEntry[]) {\n'
ret += ',\n'.join(elts) + '\n' for key, value in sorted(obj.items()):
ret += indent(level + 1) + "{{ {:s}, {:s} }},\n".format(
to_c_string(key),
_tree_to_qlit(value, level + 1, dict_value=True)
)
ret += indent(level + 1) + '{}\n'
ret += indent(level) + '}))' ret += indent(level) + '}))'
elif isinstance(obj, bool):
ret += 'QLIT_QBOOL(%s)' % ('true' if obj else 'false')
else: else:
assert False # not implemented raise NotImplementedError(
f"type '{type(obj).__name__}' not implemented"
)
if level > 0: if level > 0:
ret += ',' ret += ','
return ret return ret
def to_c_string(string): def to_c_string(string: str) -> str:
return '"' + string.replace('\\', r'\\').replace('"', r'\"') + '"' return '"' + string.replace('\\', r'\\').replace('"', r'\"') + '"'
class QAPISchemaGenIntrospectVisitor(QAPISchemaMonolithicCVisitor): class QAPISchemaGenIntrospectVisitor(QAPISchemaMonolithicCVisitor):
def __init__(self, prefix, unmask): def __init__(self, prefix: str, unmask: bool):
super().__init__( super().__init__(
prefix, 'qapi-introspect', prefix, 'qapi-introspect',
' * QAPI/QMP schema introspection', __doc__) ' * QAPI/QMP schema introspection', __doc__)
self._unmask = unmask self._unmask = unmask
self._schema = None self._schema: Optional[QAPISchema] = None
self._trees = [] self._trees: List[Annotated[SchemaInfo]] = []
self._used_types = [] self._used_types: List[QAPISchemaType] = []
self._name_map = {} self._name_map: Dict[str, str] = {}
self._genc.add(mcgen(''' self._genc.add(mcgen('''
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "%(prefix)sqapi-introspect.h" #include "%(prefix)sqapi-introspect.h"
@ -110,10 +191,10 @@ class QAPISchemaGenIntrospectVisitor(QAPISchemaMonolithicCVisitor):
''', ''',
prefix=prefix)) prefix=prefix))
def visit_begin(self, schema): def visit_begin(self, schema: QAPISchema) -> None:
self._schema = schema self._schema = schema
def visit_end(self): def visit_end(self) -> None:
# visit the types that are actually used # visit the types that are actually used
for typ in self._used_types: for typ in self._used_types:
typ.visit(self) typ.visit(self)
@ -135,18 +216,20 @@ const QLitObject %(c_name)s = %(c_string)s;
self._used_types = [] self._used_types = []
self._name_map = {} self._name_map = {}
def visit_needed(self, entity): def visit_needed(self, entity: QAPISchemaEntity) -> bool:
# Ignore types on first pass; visit_end() will pick up used types # Ignore types on first pass; visit_end() will pick up used types
return not isinstance(entity, QAPISchemaType) return not isinstance(entity, QAPISchemaType)
def _name(self, name): def _name(self, name: str) -> str:
if self._unmask: if self._unmask:
return name return name
if name not in self._name_map: if name not in self._name_map:
self._name_map[name] = '%d' % len(self._name_map) self._name_map[name] = '%d' % len(self._name_map)
return self._name_map[name] return self._name_map[name]
def _use_type(self, typ): def _use_type(self, typ: QAPISchemaType) -> str:
assert self._schema is not None
# Map the various integer types to plain int # Map the various integer types to plain int
if typ.json_type() == 'int': if typ.json_type() == 'int':
typ = self._schema.lookup_type('int') typ = self._schema.lookup_type('int')
@ -165,81 +248,137 @@ const QLitObject %(c_name)s = %(c_string)s;
return '[' + self._use_type(typ.element_type) + ']' return '[' + self._use_type(typ.element_type) + ']'
return self._name(typ.name) return self._name(typ.name)
def _gen_tree(self, name, mtype, obj, ifcond, features): @staticmethod
extra = None def _gen_features(features: Sequence[QAPISchemaFeature]
) -> List[Annotated[str]]:
return [Annotated(f.name, f.ifcond) for f in features]
def _gen_tree(self, name: str, mtype: str, obj: Dict[str, object],
ifcond: Sequence[str] = (),
features: Sequence[QAPISchemaFeature] = ()) -> None:
"""
Build and append a SchemaInfo object to self._trees.
:param name: The SchemaInfo's name.
:param mtype: The SchemaInfo's meta-type.
:param obj: Additional SchemaInfo members, as appropriate for
the meta-type.
:param ifcond: Conditionals to apply to the SchemaInfo.
:param features: The SchemaInfo's features.
Will be omitted from the output if empty.
"""
comment: Optional[str] = None
if mtype not in ('command', 'event', 'builtin', 'array'): if mtype not in ('command', 'event', 'builtin', 'array'):
if not self._unmask: if not self._unmask:
# Output a comment to make it easy to map masked names # Output a comment to make it easy to map masked names
# back to the source when reading the generated output. # back to the source when reading the generated output.
extra = {'comment': '"%s" = %s' % (self._name(name), name)} comment = f'"{self._name(name)}" = {name}'
name = self._name(name) name = self._name(name)
obj['name'] = name obj['name'] = name
obj['meta-type'] = mtype obj['meta-type'] = mtype
self._trees.append(_make_tree(obj, ifcond, features, extra)) if features:
obj['features'] = self._gen_features(features)
self._trees.append(Annotated(obj, ifcond, comment))
def _gen_member(self, member): def _gen_member(self, member: QAPISchemaObjectTypeMember
obj = {'name': member.name, 'type': self._use_type(member.type)} ) -> Annotated[SchemaInfoObjectMember]:
obj: SchemaInfoObjectMember = {
'name': member.name,
'type': self._use_type(member.type)
}
if member.optional: if member.optional:
obj['default'] = None obj['default'] = None
return _make_tree(obj, member.ifcond, member.features) if member.features:
obj['features'] = self._gen_features(member.features)
return Annotated(obj, member.ifcond)
def _gen_variants(self, tag_name, variants): def _gen_variant(self, variant: QAPISchemaVariant
return {'tag': tag_name, ) -> Annotated[SchemaInfoObjectVariant]:
'variants': [self._gen_variant(v) for v in variants]} obj: SchemaInfoObjectVariant = {
'case': variant.name,
'type': self._use_type(variant.type)
}
return Annotated(obj, variant.ifcond)
def _gen_variant(self, variant): def visit_builtin_type(self, name: str, info: Optional[QAPISourceInfo],
obj = {'case': variant.name, 'type': self._use_type(variant.type)} json_type: str) -> None:
return _make_tree(obj, variant.ifcond, None) self._gen_tree(name, 'builtin', {'json-type': json_type})
def visit_builtin_type(self, name, info, json_type): def visit_enum_type(self, name: str, info: Optional[QAPISourceInfo],
self._gen_tree(name, 'builtin', {'json-type': json_type}, [], None) ifcond: Sequence[str],
features: List[QAPISchemaFeature],
members: List[QAPISchemaEnumMember],
prefix: Optional[str]) -> None:
self._gen_tree(
name, 'enum',
{'values': [Annotated(m.name, m.ifcond) for m in members]},
ifcond, features
)
def visit_enum_type(self, name, info, ifcond, features, members, prefix): def visit_array_type(self, name: str, info: Optional[QAPISourceInfo],
self._gen_tree(name, 'enum', ifcond: Sequence[str],
{'values': [_make_tree(m.name, m.ifcond, None) element_type: QAPISchemaType) -> None:
for m in members]},
ifcond, features)
def visit_array_type(self, name, info, ifcond, element_type):
element = self._use_type(element_type) element = self._use_type(element_type)
self._gen_tree('[' + element + ']', 'array', {'element-type': element}, self._gen_tree('[' + element + ']', 'array', {'element-type': element},
ifcond, None) ifcond)
def visit_object_type_flat(self, name, info, ifcond, features, def visit_object_type_flat(self, name: str, info: Optional[QAPISourceInfo],
members, variants): ifcond: Sequence[str],
obj = {'members': [self._gen_member(m) for m in members]} features: List[QAPISchemaFeature],
members: List[QAPISchemaObjectTypeMember],
variants: Optional[QAPISchemaVariants]) -> None:
obj: SchemaInfoObject = {
'members': [self._gen_member(m) for m in members]
}
if variants: if variants:
obj.update(self._gen_variants(variants.tag_member.name, obj['tag'] = variants.tag_member.name
variants.variants)) obj['variants'] = [self._gen_variant(v) for v in variants.variants]
self._gen_tree(name, 'object', obj, ifcond, features) self._gen_tree(name, 'object', obj, ifcond, features)
def visit_alternate_type(self, name, info, ifcond, features, variants): def visit_alternate_type(self, name: str, info: Optional[QAPISourceInfo],
self._gen_tree(name, 'alternate', ifcond: Sequence[str],
{'members': [ features: List[QAPISchemaFeature],
_make_tree({'type': self._use_type(m.type)}, variants: QAPISchemaVariants) -> None:
m.ifcond, None) self._gen_tree(
for m in variants.variants]}, name, 'alternate',
ifcond, features) {'members': [Annotated({'type': self._use_type(m.type)},
m.ifcond)
for m in variants.variants]},
ifcond, features
)
def visit_command(self, name: str, info: Optional[QAPISourceInfo],
ifcond: Sequence[str],
features: List[QAPISchemaFeature],
arg_type: Optional[QAPISchemaObjectType],
ret_type: Optional[QAPISchemaType], gen: bool,
success_response: bool, boxed: bool, allow_oob: bool,
allow_preconfig: bool, coroutine: bool) -> None:
assert self._schema is not None
def visit_command(self, name, info, ifcond, features,
arg_type, ret_type, gen, success_response, boxed,
allow_oob, allow_preconfig, coroutine):
arg_type = arg_type or self._schema.the_empty_object_type arg_type = arg_type or self._schema.the_empty_object_type
ret_type = ret_type or self._schema.the_empty_object_type ret_type = ret_type or self._schema.the_empty_object_type
obj = {'arg-type': self._use_type(arg_type), obj: SchemaInfoCommand = {
'ret-type': self._use_type(ret_type)} 'arg-type': self._use_type(arg_type),
'ret-type': self._use_type(ret_type)
}
if allow_oob: if allow_oob:
obj['allow-oob'] = allow_oob obj['allow-oob'] = allow_oob
self._gen_tree(name, 'command', obj, ifcond, features) self._gen_tree(name, 'command', obj, ifcond, features)
def visit_event(self, name, info, ifcond, features, arg_type, boxed): def visit_event(self, name: str, info: Optional[QAPISourceInfo],
ifcond: Sequence[str], features: List[QAPISchemaFeature],
arg_type: Optional[QAPISchemaObjectType],
boxed: bool) -> None:
assert self._schema is not None
arg_type = arg_type or self._schema.the_empty_object_type arg_type = arg_type or self._schema.the_empty_object_type
self._gen_tree(name, 'event', {'arg-type': self._use_type(arg_type)}, self._gen_tree(name, 'event', {'arg-type': self._use_type(arg_type)},
ifcond, features) ifcond, features)
def gen_introspect(schema, output_dir, prefix, opt_unmask): def gen_introspect(schema: QAPISchema, output_dir: str, prefix: str,
opt_unmask: bool) -> None:
vis = QAPISchemaGenIntrospectVisitor(prefix, opt_unmask) vis = QAPISchemaGenIntrospectVisitor(prefix, opt_unmask)
schema.visit(vis) schema.visit(vis)
vis.write(output_dir) vis.write(output_dir)

View File

@ -13,11 +13,6 @@ disallow_untyped_defs = False
disallow_incomplete_defs = False disallow_incomplete_defs = False
check_untyped_defs = False check_untyped_defs = False
[mypy-qapi.introspect]
disallow_untyped_defs = False
disallow_incomplete_defs = False
check_untyped_defs = False
[mypy-qapi.parser] [mypy-qapi.parser]
disallow_untyped_defs = False disallow_untyped_defs = False
disallow_incomplete_defs = False disallow_incomplete_defs = False

View File

@ -28,7 +28,7 @@ from .parser import QAPISchemaParser
class QAPISchemaEntity: class QAPISchemaEntity:
meta: Optional[str] = None meta: Optional[str] = None
def __init__(self, name, info, doc, ifcond=None, features=None): def __init__(self, name: str, info, doc, ifcond=None, features=None):
assert name is None or isinstance(name, str) assert name is None or isinstance(name, str)
for f in features or []: for f in features or []:
assert isinstance(f, QAPISchemaFeature) assert isinstance(f, QAPISchemaFeature)

View File

@ -13,7 +13,7 @@ This work is licensed under the terms of the GNU GPL, version 2.
# See the COPYING file in the top-level directory. # See the COPYING file in the top-level directory.
""" """
from typing import List, Optional from typing import List, Optional, Sequence
from .common import ( from .common import (
c_enum_const, c_enum_const,
@ -139,7 +139,7 @@ def gen_struct_members(members: List[QAPISchemaObjectTypeMember]) -> str:
return ret return ret
def gen_object(name: str, ifcond: List[str], def gen_object(name: str, ifcond: Sequence[str],
base: Optional[QAPISchemaObjectType], base: Optional[QAPISchemaObjectType],
members: List[QAPISchemaObjectTypeMember], members: List[QAPISchemaObjectTypeMember],
variants: Optional[QAPISchemaVariants]) -> str: variants: Optional[QAPISchemaVariants]) -> str:
@ -307,7 +307,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
def visit_enum_type(self, def visit_enum_type(self,
name: str, name: str,
info: Optional[QAPISourceInfo], info: Optional[QAPISourceInfo],
ifcond: List[str], ifcond: Sequence[str],
features: List[QAPISchemaFeature], features: List[QAPISchemaFeature],
members: List[QAPISchemaEnumMember], members: List[QAPISchemaEnumMember],
prefix: Optional[str]) -> None: prefix: Optional[str]) -> None:
@ -318,7 +318,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
def visit_array_type(self, def visit_array_type(self,
name: str, name: str,
info: Optional[QAPISourceInfo], info: Optional[QAPISourceInfo],
ifcond: List[str], ifcond: Sequence[str],
element_type: QAPISchemaType) -> None: element_type: QAPISchemaType) -> None:
with ifcontext(ifcond, self._genh, self._genc): with ifcontext(ifcond, self._genh, self._genc):
self._genh.preamble_add(gen_fwd_object_or_array(name)) self._genh.preamble_add(gen_fwd_object_or_array(name))
@ -328,7 +328,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
def visit_object_type(self, def visit_object_type(self,
name: str, name: str,
info: Optional[QAPISourceInfo], info: Optional[QAPISourceInfo],
ifcond: List[str], ifcond: Sequence[str],
features: List[QAPISchemaFeature], features: List[QAPISchemaFeature],
base: Optional[QAPISchemaObjectType], base: Optional[QAPISchemaObjectType],
members: List[QAPISchemaObjectTypeMember], members: List[QAPISchemaObjectTypeMember],
@ -351,7 +351,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
def visit_alternate_type(self, def visit_alternate_type(self,
name: str, name: str,
info: Optional[QAPISourceInfo], info: Optional[QAPISourceInfo],
ifcond: List[str], ifcond: Sequence[str],
features: List[QAPISchemaFeature], features: List[QAPISchemaFeature],
variants: QAPISchemaVariants) -> None: variants: QAPISchemaVariants) -> None:
with ifcontext(ifcond, self._genh): with ifcontext(ifcond, self._genh):

View File

@ -13,7 +13,7 @@ This work is licensed under the terms of the GNU GPL, version 2.
See the COPYING file in the top-level directory. See the COPYING file in the top-level directory.
""" """
from typing import List, Optional from typing import List, Optional, Sequence
from .common import ( from .common import (
c_enum_const, c_enum_const,
@ -337,7 +337,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
def visit_enum_type(self, def visit_enum_type(self,
name: str, name: str,
info: Optional[QAPISourceInfo], info: Optional[QAPISourceInfo],
ifcond: List[str], ifcond: Sequence[str],
features: List[QAPISchemaFeature], features: List[QAPISchemaFeature],
members: List[QAPISchemaEnumMember], members: List[QAPISchemaEnumMember],
prefix: Optional[str]) -> None: prefix: Optional[str]) -> None:
@ -348,7 +348,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
def visit_array_type(self, def visit_array_type(self,
name: str, name: str,
info: Optional[QAPISourceInfo], info: Optional[QAPISourceInfo],
ifcond: List[str], ifcond: Sequence[str],
element_type: QAPISchemaType) -> None: element_type: QAPISchemaType) -> None:
with ifcontext(ifcond, self._genh, self._genc): with ifcontext(ifcond, self._genh, self._genc):
self._genh.add(gen_visit_decl(name)) self._genh.add(gen_visit_decl(name))
@ -357,7 +357,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
def visit_object_type(self, def visit_object_type(self,
name: str, name: str,
info: Optional[QAPISourceInfo], info: Optional[QAPISourceInfo],
ifcond: List[str], ifcond: Sequence[str],
features: List[QAPISchemaFeature], features: List[QAPISchemaFeature],
base: Optional[QAPISchemaObjectType], base: Optional[QAPISchemaObjectType],
members: List[QAPISchemaObjectTypeMember], members: List[QAPISchemaObjectTypeMember],
@ -379,7 +379,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
def visit_alternate_type(self, def visit_alternate_type(self,
name: str, name: str,
info: Optional[QAPISourceInfo], info: Optional[QAPISourceInfo],
ifcond: List[str], ifcond: Sequence[str],
features: List[QAPISchemaFeature], features: List[QAPISchemaFeature],
variants: QAPISchemaVariants) -> None: variants: QAPISchemaVariants) -> None:
with ifcontext(ifcond, self._genh, self._genc): with ifcontext(ifcond, self._genh, self._genc):