diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2021-02-08 16:12:20 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2021-02-08 16:12:21 +0000 |
commit | 4f799257b323e1238a900fd0c71c2057863e0308 (patch) | |
tree | 9e90cd7c079216533ce6d1261e110263c4db3b33 /scripts | |
parent | 8eef07b4d3c2f1048012f6a5174671bc167b4604 (diff) | |
parent | c51172667b64abc570640f141ca3bf7109fbbd17 (diff) |
Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2021-02-08' into staging
QAPI patches patches for 2021-02-08
# gpg: Signature made Mon 08 Feb 2021 13:54:26 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-08:
qapi: enable strict-optional checks
qapi: type 'info' as Optional[QAPISourceInfo]
qapi/gen: Drop support for QAPIGen without a file name
qapi/commands: Simplify command registry generation
qapi/gen: Support switching to another module temporarily
qapi/gen: write _genc/_genh access shims
qapi: centralize the built-in module name definition
qapi/gen: Combine ._add_[user|system]_module
qapi: use './builtin' as the built-in module name
qapi: use explicitly internal module names
qapi/gen: Replace ._begin_system_module()
qapi: centralize is_[user|system|builtin]_module methods
qapi/gen: inline _wrap_ifcond into end_if()
qapi/main: handle theoretical None-return from re.match()
qapi/events: fix visit_event typing
qapi/commands: assert arg_type is not None
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/qapi/commands.py | 62 | ||||
-rw-r--r-- | scripts/qapi/events.py | 16 | ||||
-rw-r--r-- | scripts/qapi/gen.py | 94 | ||||
-rw-r--r-- | scripts/qapi/main.py | 2 | ||||
-rw-r--r-- | scripts/qapi/mypy.ini | 1 | ||||
-rw-r--r-- | scripts/qapi/schema.py | 42 | ||||
-rw-r--r-- | scripts/qapi/types.py | 4 | ||||
-rw-r--r-- | scripts/qapi/visit.py | 6 |
8 files changed, 131 insertions, 96 deletions
diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py index 50978090b4..54af519f44 100644 --- a/scripts/qapi/commands.py +++ b/scripts/qapi/commands.py @@ -23,7 +23,6 @@ from typing import ( from .common import c_name, mcgen from .gen import ( QAPIGenC, - QAPIGenCCode, QAPISchemaModularCVisitor, build_params, ifcontext, @@ -126,6 +125,9 @@ def gen_marshal(name: str, boxed: bool, ret_type: Optional[QAPISchemaType]) -> str: have_args = boxed or (arg_type and not arg_type.is_empty()) + if have_args: + assert arg_type is not None + arg_type_c_name = arg_type.c_name() ret = mcgen(''' @@ -147,7 +149,7 @@ def gen_marshal(name: str, ret += mcgen(''' %(c_name)s arg = {0}; ''', - c_name=arg_type.c_name()) + c_name=arg_type_c_name) ret += mcgen(''' @@ -163,7 +165,7 @@ def gen_marshal(name: str, ok = visit_check_struct(v, errp); } ''', - c_arg_type=arg_type.c_name()) + c_arg_type=arg_type_c_name) else: ret += mcgen(''' ok = visit_check_struct(v, errp); @@ -193,7 +195,7 @@ out: ret += mcgen(''' visit_type_%(c_arg_type)s_members(v, &arg, NULL); ''', - c_arg_type=arg_type.c_name()) + c_arg_type=arg_type_c_name) ret += mcgen(''' visit_end_struct(v, NULL); @@ -234,28 +236,11 @@ def gen_register_command(name: str, return ret -def gen_registry(registry: str, prefix: str) -> str: - ret = mcgen(''' - -void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds) -{ - QTAILQ_INIT(cmds); - -''', - c_prefix=c_name(prefix, protect=False)) - ret += registry - ret += mcgen(''' -} -''') - return ret - - class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor): def __init__(self, prefix: str): super().__init__( prefix, 'qapi-commands', ' * Schema-defined QAPI/QMP commands', None, __doc__) - self._regy = QAPIGenCCode(None) self._visited_ret_types: Dict[QAPIGenC, Set[QAPISchemaType]] = {} def _begin_user_module(self, name: str) -> None: @@ -282,25 +267,36 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor): ''', types=types)) - def visit_end(self) -> None: - self._add_system_module('init', ' * QAPI Commands initialization') + def visit_begin(self, schema: QAPISchema) -> None: + self._add_module('./init', ' * QAPI Commands initialization') self._genh.add(mcgen(''' #include "qapi/qmp/dispatch.h" void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds); ''', c_prefix=c_name(self._prefix, protect=False))) - self._genc.preamble_add(mcgen(''' + self._genc.add(mcgen(''' #include "qemu/osdep.h" #include "%(prefix)sqapi-commands.h" #include "%(prefix)sqapi-init-commands.h" + +void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds) +{ + QTAILQ_INIT(cmds); + ''', - prefix=self._prefix)) - self._genc.add(gen_registry(self._regy.get_content(), self._prefix)) + prefix=self._prefix, + c_prefix=c_name(self._prefix, protect=False))) + + def visit_end(self) -> None: + with self._temp_module('./init'): + self._genc.add(mcgen(''' +} +''')) def visit_command(self, name: str, - info: QAPISourceInfo, + info: Optional[QAPISourceInfo], ifcond: List[str], features: List[QAPISchemaFeature], arg_type: Optional[QAPISchemaObjectType], @@ -321,15 +317,17 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds); if ret_type and ret_type not in self._visited_ret_types[self._genc]: self._visited_ret_types[self._genc].add(ret_type) with ifcontext(ret_type.ifcond, - self._genh, self._genc, self._regy): + self._genh, self._genc): self._genc.add(gen_marshal_output(ret_type)) - with ifcontext(ifcond, self._genh, self._genc, self._regy): + with ifcontext(ifcond, self._genh, self._genc): self._genh.add(gen_command_decl(name, arg_type, boxed, ret_type)) self._genh.add(gen_marshal_decl(name)) self._genc.add(gen_marshal(name, arg_type, boxed, ret_type)) - self._regy.add(gen_register_command(name, success_response, - allow_oob, allow_preconfig, - coroutine)) + with self._temp_module('./init'): + with ifcontext(ifcond, self._genh, self._genc): + self._genc.add(gen_register_command(name, success_response, + allow_oob, allow_preconfig, + coroutine)) def gen_commands(schema: QAPISchema, diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py index 599f3d1f56..8c57deb2b8 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 +from typing import List, Optional from .common import c_enum_const, c_name, mcgen from .gen import QAPISchemaModularCVisitor, build_params, ifcontext @@ -27,7 +27,7 @@ from .types import gen_enum, gen_enum_lookup def build_event_send_proto(name: str, - arg_type: QAPISchemaObjectType, + arg_type: Optional[QAPISchemaObjectType], boxed: bool) -> str: return 'void qapi_event_send_%(c_name)s(%(param)s)' % { 'c_name': c_name(name.lower()), @@ -35,7 +35,7 @@ def build_event_send_proto(name: str, def gen_event_send_decl(name: str, - arg_type: QAPISchemaObjectType, + arg_type: Optional[QAPISchemaObjectType], boxed: bool) -> str: return mcgen(''' @@ -78,7 +78,7 @@ def gen_param_var(typ: QAPISchemaObjectType) -> str: def gen_event_send(name: str, - arg_type: QAPISchemaObjectType, + arg_type: Optional[QAPISchemaObjectType], boxed: bool, event_enum_name: str, event_emit: str) -> str: @@ -99,6 +99,7 @@ def gen_event_send(name: str, proto=build_event_send_proto(name, arg_type, boxed)) if have_args: + assert arg_type is not None ret += mcgen(''' QObject *obj; Visitor *v; @@ -114,6 +115,7 @@ def gen_event_send(name: str, name=name) if have_args: + assert arg_type is not None ret += mcgen(''' v = qobject_output_visitor_new(&obj); ''') @@ -189,7 +191,7 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor): types=types)) def visit_end(self) -> None: - self._add_system_module('emit', ' * QAPI Events emission') + self._add_module('./emit', ' * QAPI Events emission') self._genc.preamble_add(mcgen(''' #include "qemu/osdep.h" #include "%(prefix)sqapi-emit-events.h" @@ -211,10 +213,10 @@ void %(event_emit)s(%(event_enum)s event, QDict *qdict); def visit_event(self, name: str, - info: QAPISourceInfo, + info: Optional[QAPISourceInfo], ifcond: List[str], features: List[QAPISchemaFeature], - arg_type: QAPISchemaObjectType, + arg_type: Optional[QAPISchemaObjectType], boxed: bool) -> None: with ifcontext(ifcond, self._genh, self._genc): self._genh.add(gen_event_send_decl(name, arg_type, boxed)) diff --git a/scripts/qapi/gen.py b/scripts/qapi/gen.py index b40f18eee3..63549cc8d4 100644 --- a/scripts/qapi/gen.py +++ b/scripts/qapi/gen.py @@ -31,12 +31,16 @@ from .common import ( guardstart, mcgen, ) -from .schema import QAPISchemaObjectType, QAPISchemaVisitor +from .schema import ( + QAPISchemaModule, + QAPISchemaObjectType, + QAPISchemaVisitor, +) from .source import QAPISourceInfo class QAPIGen: - def __init__(self, fname: Optional[str]): + def __init__(self, fname: str): self.fname = fname self._preamble = '' self._body = '' @@ -121,7 +125,7 @@ def build_params(arg_type: Optional[QAPISchemaObjectType], class QAPIGenCCode(QAPIGen): - def __init__(self, fname: Optional[str]): + def __init__(self, fname: str): super().__init__(fname) self._start_if: Optional[Tuple[List[str], str, str]] = None @@ -130,15 +134,12 @@ class QAPIGenCCode(QAPIGen): self._start_if = (ifcond, self._body, self._preamble) def end_if(self) -> None: - assert self._start_if - self._wrap_ifcond() - self._start_if = None - - def _wrap_ifcond(self) -> None: + assert self._start_if is not None self._body = _wrap_ifcond(self._start_if[0], self._start_if[1], self._body) self._preamble = _wrap_ifcond(self._start_if[0], self._start_if[2], self._preamble) + self._start_if = None def get_content(self) -> str: assert self._start_if is None @@ -243,85 +244,88 @@ class QAPISchemaModularCVisitor(QAPISchemaVisitor): self._user_blurb = user_blurb self._builtin_blurb = builtin_blurb self._pydoc = pydoc - self._genc: Optional[QAPIGenC] = None - self._genh: Optional[QAPIGenH] = None - self._module: Dict[Optional[str], Tuple[QAPIGenC, QAPIGenH]] = {} + self._current_module: Optional[str] = None + self._module: Dict[str, Tuple[QAPIGenC, QAPIGenH]] = {} self._main_module: Optional[str] = None - @staticmethod - def _is_user_module(name: Optional[str]) -> bool: - return bool(name and not name.startswith('./')) + @property + def _genc(self) -> QAPIGenC: + assert self._current_module is not None + return self._module[self._current_module][0] - @staticmethod - def _is_builtin_module(name: Optional[str]) -> bool: - return not name + @property + def _genh(self) -> QAPIGenH: + assert self._current_module is not None + return self._module[self._current_module][1] - def _module_dirname(self, name: Optional[str]) -> str: - if self._is_user_module(name): + @staticmethod + def _module_dirname(name: str) -> str: + if QAPISchemaModule.is_user_module(name): return os.path.dirname(name) return '' - def _module_basename(self, what: str, name: Optional[str]) -> str: - ret = '' if self._is_builtin_module(name) else self._prefix - if self._is_user_module(name): + def _module_basename(self, what: str, name: str) -> str: + ret = '' if QAPISchemaModule.is_builtin_module(name) else self._prefix + if QAPISchemaModule.is_user_module(name): basename = os.path.basename(name) ret += what if name != self._main_module: ret += '-' + os.path.splitext(basename)[0] else: - name = name[2:] if name else 'builtin' - ret += re.sub(r'-', '-' + name + '-', what) + assert QAPISchemaModule.is_system_module(name) + ret += re.sub(r'-', '-' + name[2:] + '-', what) return ret - def _module_filename(self, what: str, name: Optional[str]) -> str: + def _module_filename(self, what: str, name: str) -> str: return os.path.join(self._module_dirname(name), self._module_basename(what, name)) - def _add_module(self, name: Optional[str], blurb: str) -> None: + def _add_module(self, name: str, blurb: str) -> None: + if QAPISchemaModule.is_user_module(name): + if self._main_module is None: + self._main_module = name basename = self._module_filename(self._what, name) genc = QAPIGenC(basename + '.c', blurb, self._pydoc) genh = QAPIGenH(basename + '.h', blurb, self._pydoc) self._module[name] = (genc, genh) - self._genc, self._genh = self._module[name] - - def _add_user_module(self, name: str, blurb: str) -> None: - assert self._is_user_module(name) - if self._main_module is None: - self._main_module = name - self._add_module(name, blurb) + self._current_module = name - def _add_system_module(self, name: Optional[str], blurb: str) -> None: - self._add_module(name and './' + name, blurb) + @contextmanager + def _temp_module(self, name: str) -> Iterator[None]: + old_module = self._current_module + self._current_module = name + yield + self._current_module = old_module def write(self, output_dir: str, opt_builtins: bool = False) -> None: for name in self._module: - if self._is_builtin_module(name) and not opt_builtins: + if QAPISchemaModule.is_builtin_module(name) and not opt_builtins: continue (genc, genh) = self._module[name] genc.write(output_dir) genh.write(output_dir) - def _begin_system_module(self, name: None) -> None: + def _begin_builtin_module(self) -> None: pass def _begin_user_module(self, name: str) -> None: pass - def visit_module(self, name: Optional[str]) -> None: - if name is None: + def visit_module(self, name: str) -> None: + if QAPISchemaModule.is_builtin_module(name): if self._builtin_blurb: - self._add_system_module(None, self._builtin_blurb) - self._begin_system_module(name) + self._add_module(name, self._builtin_blurb) + self._begin_builtin_module() else: # The built-in module has not been created. No code may # be generated. - self._genc = None - self._genh = None + self._current_module = None else: - self._add_user_module(name, self._user_blurb) + assert QAPISchemaModule.is_user_module(name) + self._add_module(name, self._user_blurb) self._begin_user_module(name) - def visit_include(self, name: str, info: QAPISourceInfo) -> None: + def visit_include(self, name: str, info: Optional[QAPISourceInfo]) -> None: relname = os.path.relpath(self._module_filename(self._what, name), os.path.dirname(self._genh.fname)) self._genh.preamble_add(mcgen(''' diff --git a/scripts/qapi/main.py b/scripts/qapi/main.py index 42517210b8..703e7ed1ed 100644 --- a/scripts/qapi/main.py +++ b/scripts/qapi/main.py @@ -23,6 +23,8 @@ from .visit import gen_visit def invalid_prefix_char(prefix: str) -> Optional[str]: match = re.match(r'([A-Za-z_.-][A-Za-z0-9_.-]*)?', prefix) + # match cannot be None, but mypy cannot infer that. + assert match is not None if match.end() != len(prefix): return prefix[match.end()] return None diff --git a/scripts/qapi/mypy.ini b/scripts/qapi/mypy.ini index 74fc6c8215..04bd5db527 100644 --- a/scripts/qapi/mypy.ini +++ b/scripts/qapi/mypy.ini @@ -1,6 +1,5 @@ [mypy] strict = True -strict_optional = False disallow_untyped_calls = False python_version = 3.6 diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py index 720449feee..353e8020a2 100644 --- a/scripts/qapi/schema.py +++ b/scripts/qapi/schema.py @@ -68,7 +68,8 @@ class QAPISchemaEntity: def _set_module(self, schema, info): assert self._checked - self._module = schema.module_by_fname(info and info.fname) + fname = info.fname if info else QAPISchemaModule.BUILTIN_MODULE_NAME + self._module = schema.module_by_fname(fname) self._module.add_entity(self) def set_module(self, schema): @@ -137,10 +138,40 @@ class QAPISchemaVisitor: class QAPISchemaModule: + + BUILTIN_MODULE_NAME = './builtin' + def __init__(self, name): self.name = name self._entity_list = [] + @staticmethod + def is_system_module(name: str) -> bool: + """ + System modules are internally defined modules. + + Their names start with the "./" prefix. + """ + return name.startswith('./') + + @classmethod + def is_user_module(cls, name: str) -> bool: + """ + User modules are those defined by the user in qapi JSON files. + + They do not start with the "./" prefix. + """ + return not cls.is_system_module(name) + + @classmethod + def is_builtin_module(cls, name: str) -> bool: + """ + The built-in module is a single System module for the built-in types. + + It is always "./builtin". + """ + return name == cls.BUILTIN_MODULE_NAME + def add_entity(self, ent): self._entity_list.append(ent) @@ -825,7 +856,7 @@ class QAPISchema: self._entity_dict = {} self._module_dict = OrderedDict() self._schema_dir = os.path.dirname(fname) - self._make_module(None) # built-ins + self._make_module(QAPISchemaModule.BUILTIN_MODULE_NAME) self._make_module(fname) self._predefining = True self._def_predefineds() @@ -870,9 +901,9 @@ class QAPISchema: info, "%s uses unknown type '%s'" % (what, name)) return typ - def _module_name(self, fname): - if fname is None: - return None + def _module_name(self, fname: str) -> str: + if QAPISchemaModule.is_system_module(fname): + return fname return os.path.relpath(fname, self._schema_dir) def _make_module(self, fname): @@ -883,7 +914,6 @@ class QAPISchema: def module_by_fname(self, fname): name = self._module_name(fname) - assert name in self._module_dict return self._module_dict[name] def _def_include(self, expr, info, doc): diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py index 2b4916cdaa..2bdd626847 100644 --- a/scripts/qapi/types.py +++ b/scripts/qapi/types.py @@ -271,7 +271,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor): prefix, 'qapi-types', ' * Schema-defined QAPI types', ' * Built-in QAPI types', __doc__) - def _begin_system_module(self, name: None) -> None: + def _begin_builtin_module(self) -> None: self._genc.preamble_add(mcgen(''' #include "qemu/osdep.h" #include "qapi/dealloc-visitor.h" @@ -350,7 +350,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor): def visit_alternate_type(self, name: str, - info: QAPISourceInfo, + info: Optional[QAPISourceInfo], ifcond: List[str], features: List[QAPISchemaFeature], variants: QAPISchemaVariants) -> None: diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py index 339f152152..22e62df901 100644 --- a/scripts/qapi/visit.py +++ b/scripts/qapi/visit.py @@ -305,7 +305,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor): prefix, 'qapi-visit', ' * Schema-defined QAPI visitors', ' * Built-in QAPI visitors', __doc__) - def _begin_system_module(self, name: None) -> None: + def _begin_builtin_module(self) -> None: self._genc.preamble_add(mcgen(''' #include "qemu/osdep.h" #include "qapi/error.h" @@ -336,7 +336,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor): def visit_enum_type(self, name: str, - info: QAPISourceInfo, + info: Optional[QAPISourceInfo], ifcond: List[str], features: List[QAPISchemaFeature], members: List[QAPISchemaEnumMember], @@ -378,7 +378,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor): def visit_alternate_type(self, name: str, - info: QAPISourceInfo, + info: Optional[QAPISourceInfo], ifcond: List[str], features: List[QAPISchemaFeature], variants: QAPISchemaVariants) -> None: |