aboutsummaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2021-02-19 17:22:42 +0000
committerPeter Maydell <peter.maydell@linaro.org>2021-02-19 17:22:42 +0000
commite90ef02389dc8b57eaea22b290244609d720a8bf (patch)
tree088f13b20e19285e440e4f4cea4a955c849ab9ff /scripts
parentce42fe17ad2d2459436fdacbc207df3212a58428 (diff)
parent9b77d946990e7497469bb98171b90b4f3ab186a9 (diff)
downloadqemu-e90ef02389dc8b57eaea22b290244609d720a8bf.zip
qemu-e90ef02389dc8b57eaea22b290244609d720a8bf.tar.gz
qemu-e90ef02389dc8b57eaea22b290244609d720a8bf.tar.bz2
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>
Diffstat (limited to 'scripts')
-rw-r--r--scripts/qapi/commands.py3
-rw-r--r--scripts/qapi/events.py4
-rw-r--r--scripts/qapi/gen.py12
-rw-r--r--scripts/qapi/introspect.py349
-rw-r--r--scripts/qapi/mypy.ini5
-rw-r--r--scripts/qapi/schema.py2
-rw-r--r--scripts/qapi/types.py12
-rw-r--r--scripts/qapi/visit.py10
8 files changed, 266 insertions, 131 deletions
diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py
index 54af519..0a75a93 100644
--- a/scripts/qapi/commands.py
+++ b/scripts/qapi/commands.py
@@ -17,6 +17,7 @@ from typing import (
Dict,
List,
Optional,
+ Sequence,
Set,
)
@@ -297,7 +298,7 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds)
def visit_command(self,
name: str,
info: Optional[QAPISourceInfo],
- ifcond: List[str],
+ ifcond: Sequence[str],
features: List[QAPISchemaFeature],
arg_type: Optional[QAPISchemaObjectType],
ret_type: Optional[QAPISchemaType],
diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py
index 8c57deb..90d2f61 100644
--- a/scripts/qapi/events.py
+++ b/scripts/qapi/events.py
@@ -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.
"""
-from typing import List, Optional
+from typing import List, Optional, Sequence
from .common import c_enum_const, c_name, mcgen
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,
name: str,
info: Optional[QAPISourceInfo],
- ifcond: List[str],
+ ifcond: Sequence[str],
features: List[QAPISchemaFeature],
arg_type: Optional[QAPISchemaObjectType],
boxed: bool) -> None:
diff --git a/scripts/qapi/gen.py b/scripts/qapi/gen.py
index 63549cc..1fa503b 100644
--- a/scripts/qapi/gen.py
+++ b/scripts/qapi/gen.py
@@ -17,8 +17,8 @@ import re
from typing import (
Dict,
Iterator,
- List,
Optional,
+ Sequence,
Tuple,
)
@@ -85,7 +85,7 @@ class QAPIGen:
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:
return after # suppress empty #if ... #endif
@@ -127,9 +127,9 @@ def build_params(arg_type: Optional[QAPISchemaObjectType],
class QAPIGenCCode(QAPIGen):
def __init__(self, fname: str):
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
self._start_if = (ifcond, self._body, self._preamble)
@@ -187,11 +187,11 @@ class QAPIGenH(QAPIGenC):
@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()`.
- :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`.
Example::
diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py
index fafec94..9a348ca 100644
--- a/scripts/qapi/introspect.py
+++ b/scripts/qapi/introspect.py
@@ -1,15 +1,29 @@
"""
QAPI introspection generator
-Copyright (C) 2015-2018 Red Hat, Inc.
+Copyright (C) 2015-2021 Red Hat, Inc.
Authors:
Markus Armbruster <armbru@redhat.com>
+ John Snow <jsnow@redhat.com>
This work is licensed under the terms of the GNU GPL, version 2.
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 (
c_name,
gen_endif,
@@ -18,91 +32,158 @@ from .common import (
)
from .gen import QAPISchemaMonolithicCVisitor
from .schema import (
+ QAPISchema,
QAPISchemaArrayType,
QAPISchemaBuiltinType,
+ QAPISchemaEntity,
+ QAPISchemaEnumMember,
+ QAPISchemaFeature,
+ QAPISchemaObjectType,
+ QAPISchemaObjectTypeMember,
QAPISchemaType,
+ QAPISchemaVariant,
+ QAPISchemaVariants,
)
-
-
-def _make_tree(obj, ifcond, features, extra=None):
- if extra is None:
- extra = {}
- if ifcond:
- extra['if'] = ifcond
- if features:
- obj['features'] = [(f.name, {'if': f.ifcond}) for f in features]
- if extra:
- return (obj, extra)
- return obj
-
-
-def _tree_to_qlit(obj, level=0, suppress_first_indent=False):
-
- def indent(level):
+from .source import QAPISourceInfo
+
+
+# This module constructs a tree data structure that is used to
+# generate the introspection information for QEMU. It is shaped
+# like a JSON value.
+#
+# A complexity over JSON is that our values may or may not be annotated.
+#
+# Un-annotated values may be:
+# Scalar: str, bool, None.
+# Non-scalar: List, Dict
+# _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]
+
+
+_ValueT = TypeVar('_ValueT', bound=_Value)
+
+
+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 * ' '
- if isinstance(obj, tuple):
- ifobj, extra = obj
- ifcond = extra.get('if')
- comment = extra.get('comment')
+ if isinstance(obj, Annotated):
+ # NB: _tree_to_qlit is called recursively on the values of a
+ # key:value pair; those values can't be decorated with
+ # comments or conditionals.
+ msg = "dict values cannot have attached comments or if-conditionals."
+ assert not dict_value, msg
+
ret = ''
- if comment:
- ret += indent(level) + '/* %s */\n' % comment
- if ifcond:
- ret += gen_if(ifcond)
- ret += _tree_to_qlit(ifobj, level)
- if ifcond:
- ret += '\n' + gen_endif(ifcond)
+ if obj.comment:
+ ret += indent(level) + f"/* {obj.comment} */\n"
+ if obj.ifcond:
+ ret += gen_if(obj.ifcond)
+ ret += _tree_to_qlit(obj.value, level)
+ if obj.ifcond:
+ ret += '\n' + gen_endif(obj.ifcond)
return ret
ret = ''
- if not suppress_first_indent:
+ if not dict_value:
ret += indent(level)
+
+ # Scalars:
if obj is None:
ret += 'QLIT_QNULL'
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):
- elts = [_tree_to_qlit(elt, level + 1).strip('\n')
- for elt in obj]
- elts.append(indent(level + 1) + "{}")
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) + '}))'
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 += ',\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) + '}))'
- elif isinstance(obj, bool):
- ret += 'QLIT_QBOOL(%s)' % ('true' if obj else 'false')
else:
- assert False # not implemented
+ raise NotImplementedError(
+ f"type '{type(obj).__name__}' not implemented"
+ )
+
if level > 0:
ret += ','
return ret
-def to_c_string(string):
+def to_c_string(string: str) -> str:
return '"' + string.replace('\\', r'\\').replace('"', r'\"') + '"'
class QAPISchemaGenIntrospectVisitor(QAPISchemaMonolithicCVisitor):
- def __init__(self, prefix, unmask):
+ def __init__(self, prefix: str, unmask: bool):
super().__init__(
prefix, 'qapi-introspect',
' * QAPI/QMP schema introspection', __doc__)
self._unmask = unmask
- self._schema = None
- self._trees = []
- self._used_types = []
- self._name_map = {}
+ self._schema: Optional[QAPISchema] = None
+ self._trees: List[Annotated[SchemaInfo]] = []
+ self._used_types: List[QAPISchemaType] = []
+ self._name_map: Dict[str, str] = {}
self._genc.add(mcgen('''
#include "qemu/osdep.h"
#include "%(prefix)sqapi-introspect.h"
@@ -110,10 +191,10 @@ class QAPISchemaGenIntrospectVisitor(QAPISchemaMonolithicCVisitor):
''',
prefix=prefix))
- def visit_begin(self, schema):
+ def visit_begin(self, schema: QAPISchema) -> None:
self._schema = schema
- def visit_end(self):
+ def visit_end(self) -> None:
# visit the types that are actually used
for typ in self._used_types:
typ.visit(self)
@@ -135,18 +216,20 @@ const QLitObject %(c_name)s = %(c_string)s;
self._used_types = []
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
return not isinstance(entity, QAPISchemaType)
- def _name(self, name):
+ def _name(self, name: str) -> str:
if self._unmask:
return name
if name not in self._name_map:
self._name_map[name] = '%d' % len(self._name_map)
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
if typ.json_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._name(typ.name)
- def _gen_tree(self, name, mtype, obj, ifcond, features):
- extra = None
+ @staticmethod
+ 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 not self._unmask:
# Output a comment to make it easy to map masked names
# 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)
obj['name'] = name
obj['meta-type'] = mtype
- self._trees.append(_make_tree(obj, ifcond, features, extra))
-
- def _gen_member(self, member):
- obj = {'name': member.name, 'type': self._use_type(member.type)}
+ if features:
+ obj['features'] = self._gen_features(features)
+ self._trees.append(Annotated(obj, ifcond, comment))
+
+ def _gen_member(self, member: QAPISchemaObjectTypeMember
+ ) -> Annotated[SchemaInfoObjectMember]:
+ obj: SchemaInfoObjectMember = {
+ 'name': member.name,
+ 'type': self._use_type(member.type)
+ }
if member.optional:
obj['default'] = None
- return _make_tree(obj, member.ifcond, member.features)
-
- def _gen_variants(self, tag_name, variants):
- return {'tag': tag_name,
- 'variants': [self._gen_variant(v) for v in variants]}
-
- def _gen_variant(self, variant):
- obj = {'case': variant.name, 'type': self._use_type(variant.type)}
- return _make_tree(obj, variant.ifcond, None)
-
- def visit_builtin_type(self, name, info, json_type):
- self._gen_tree(name, 'builtin', {'json-type': json_type}, [], None)
-
- def visit_enum_type(self, name, info, ifcond, features, members, prefix):
- self._gen_tree(name, 'enum',
- {'values': [_make_tree(m.name, m.ifcond, None)
- for m in members]},
- ifcond, features)
-
- def visit_array_type(self, name, info, ifcond, element_type):
+ if member.features:
+ obj['features'] = self._gen_features(member.features)
+ return Annotated(obj, member.ifcond)
+
+ def _gen_variant(self, variant: QAPISchemaVariant
+ ) -> Annotated[SchemaInfoObjectVariant]:
+ obj: SchemaInfoObjectVariant = {
+ 'case': variant.name,
+ 'type': self._use_type(variant.type)
+ }
+ return Annotated(obj, variant.ifcond)
+
+ def visit_builtin_type(self, name: str, info: Optional[QAPISourceInfo],
+ json_type: str) -> None:
+ self._gen_tree(name, 'builtin', {'json-type': json_type})
+
+ def visit_enum_type(self, name: str, info: Optional[QAPISourceInfo],
+ 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_array_type(self, name: str, info: Optional[QAPISourceInfo],
+ ifcond: Sequence[str],
+ element_type: QAPISchemaType) -> None:
element = self._use_type(element_type)
self._gen_tree('[' + element + ']', 'array', {'element-type': element},
- ifcond, None)
-
- def visit_object_type_flat(self, name, info, ifcond, features,
- members, variants):
- obj = {'members': [self._gen_member(m) for m in members]}
+ ifcond)
+
+ def visit_object_type_flat(self, name: str, info: Optional[QAPISourceInfo],
+ ifcond: Sequence[str],
+ features: List[QAPISchemaFeature],
+ members: List[QAPISchemaObjectTypeMember],
+ variants: Optional[QAPISchemaVariants]) -> None:
+ obj: SchemaInfoObject = {
+ 'members': [self._gen_member(m) for m in members]
+ }
if variants:
- obj.update(self._gen_variants(variants.tag_member.name,
- variants.variants))
-
+ obj['tag'] = variants.tag_member.name
+ obj['variants'] = [self._gen_variant(v) for v in variants.variants]
self._gen_tree(name, 'object', obj, ifcond, features)
- def visit_alternate_type(self, name, info, ifcond, features, variants):
- self._gen_tree(name, 'alternate',
- {'members': [
- _make_tree({'type': self._use_type(m.type)},
- m.ifcond, None)
- for m in variants.variants]},
- ifcond, features)
+ def visit_alternate_type(self, name: str, info: Optional[QAPISourceInfo],
+ ifcond: Sequence[str],
+ features: List[QAPISchemaFeature],
+ variants: QAPISchemaVariants) -> None:
+ self._gen_tree(
+ name, 'alternate',
+ {'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
ret_type = ret_type or self._schema.the_empty_object_type
- obj = {'arg-type': self._use_type(arg_type),
- 'ret-type': self._use_type(ret_type)}
+ obj: SchemaInfoCommand = {
+ 'arg-type': self._use_type(arg_type),
+ 'ret-type': self._use_type(ret_type)
+ }
if allow_oob:
obj['allow-oob'] = allow_oob
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
self._gen_tree(name, 'event', {'arg-type': self._use_type(arg_type)},
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)
schema.visit(vis)
vis.write(output_dir)
diff --git a/scripts/qapi/mypy.ini b/scripts/qapi/mypy.ini
index 04bd5db..0a000d5 100644
--- a/scripts/qapi/mypy.ini
+++ b/scripts/qapi/mypy.ini
@@ -13,11 +13,6 @@ disallow_untyped_defs = False
disallow_incomplete_defs = False
check_untyped_defs = False
-[mypy-qapi.introspect]
-disallow_untyped_defs = False
-disallow_incomplete_defs = False
-check_untyped_defs = False
-
[mypy-qapi.parser]
disallow_untyped_defs = False
disallow_incomplete_defs = False
diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
index 353e802..ff16578 100644
--- a/scripts/qapi/schema.py
+++ b/scripts/qapi/schema.py
@@ -28,7 +28,7 @@ from .parser import QAPISchemaParser
class QAPISchemaEntity:
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)
for f in features or []:
assert isinstance(f, QAPISchemaFeature)
diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
index 2bdd626..20d572a 100644
--- a/scripts/qapi/types.py
+++ b/scripts/qapi/types.py
@@ -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.
"""
-from typing import List, Optional
+from typing import List, Optional, Sequence
from .common import (
c_enum_const,
@@ -139,7 +139,7 @@ def gen_struct_members(members: List[QAPISchemaObjectTypeMember]) -> str:
return ret
-def gen_object(name: str, ifcond: List[str],
+def gen_object(name: str, ifcond: Sequence[str],
base: Optional[QAPISchemaObjectType],
members: List[QAPISchemaObjectTypeMember],
variants: Optional[QAPISchemaVariants]) -> str:
@@ -307,7 +307,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
def visit_enum_type(self,
name: str,
info: Optional[QAPISourceInfo],
- ifcond: List[str],
+ ifcond: Sequence[str],
features: List[QAPISchemaFeature],
members: List[QAPISchemaEnumMember],
prefix: Optional[str]) -> None:
@@ -318,7 +318,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
def visit_array_type(self,
name: str,
info: Optional[QAPISourceInfo],
- ifcond: List[str],
+ ifcond: Sequence[str],
element_type: QAPISchemaType) -> None:
with ifcontext(ifcond, self._genh, self._genc):
self._genh.preamble_add(gen_fwd_object_or_array(name))
@@ -328,7 +328,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
def visit_object_type(self,
name: str,
info: Optional[QAPISourceInfo],
- ifcond: List[str],
+ ifcond: Sequence[str],
features: List[QAPISchemaFeature],
base: Optional[QAPISchemaObjectType],
members: List[QAPISchemaObjectTypeMember],
@@ -351,7 +351,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
def visit_alternate_type(self,
name: str,
info: Optional[QAPISourceInfo],
- ifcond: List[str],
+ ifcond: Sequence[str],
features: List[QAPISchemaFeature],
variants: QAPISchemaVariants) -> None:
with ifcontext(ifcond, self._genh):
diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
index 22e62df..9aa0b1e 100644
--- a/scripts/qapi/visit.py
+++ b/scripts/qapi/visit.py
@@ -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.
"""
-from typing import List, Optional
+from typing import List, Optional, Sequence
from .common import (
c_enum_const,
@@ -337,7 +337,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
def visit_enum_type(self,
name: str,
info: Optional[QAPISourceInfo],
- ifcond: List[str],
+ ifcond: Sequence[str],
features: List[QAPISchemaFeature],
members: List[QAPISchemaEnumMember],
prefix: Optional[str]) -> None:
@@ -348,7 +348,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
def visit_array_type(self,
name: str,
info: Optional[QAPISourceInfo],
- ifcond: List[str],
+ ifcond: Sequence[str],
element_type: QAPISchemaType) -> None:
with ifcontext(ifcond, self._genh, self._genc):
self._genh.add(gen_visit_decl(name))
@@ -357,7 +357,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
def visit_object_type(self,
name: str,
info: Optional[QAPISourceInfo],
- ifcond: List[str],
+ ifcond: Sequence[str],
features: List[QAPISchemaFeature],
base: Optional[QAPISchemaObjectType],
members: List[QAPISchemaObjectTypeMember],
@@ -379,7 +379,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
def visit_alternate_type(self,
name: str,
info: Optional[QAPISourceInfo],
- ifcond: List[str],
+ ifcond: Sequence[str],
features: List[QAPISchemaFeature],
variants: QAPISchemaVariants) -> None:
with ifcontext(ifcond, self._genh, self._genc):