mypy and python type hints are not powerful enough to properly describe JSON messages in Python 3.6. The best we can do, generally, is describe them as Dict[str, Any].
Add casts to coerce this type for static analysis; but do NOT enforce this type at runtime in any way. Note: Python 3.8 adds a TypedDict construct which allows for the description of more arbitrary Dictionary shapes. There is a third-party module, "Pydantic", which is compatible with 3.6 that can be used instead of the JSON library that parses JSON messages to fully-typed Python objects, and may be preferable in some cases. (That is well beyond the scope of this commit or series.) Signed-off-by: John Snow <js...@redhat.com> --- python/qemu/lib/qmp.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/python/qemu/lib/qmp.py b/python/qemu/lib/qmp.py index 0036204218..e460234f2e 100644 --- a/python/qemu/lib/qmp.py +++ b/python/qemu/lib/qmp.py @@ -13,6 +13,7 @@ import logging from typing import ( Any, + cast, Dict, Optional, TextIO, @@ -129,7 +130,10 @@ def __json_read(self, only_event=False): data = self.__sockfile.readline() if not data: return None - resp = json.loads(data) + # By definition, any JSON received from QMP is a QMPMessage, + # and we are asserting only at static analysis time that it + # has a particular shape. + resp = cast(QMPMessage, json.loads(data)) if 'event' in resp: self.logger.debug("<<< %s", resp) self.__events.append(resp) @@ -261,7 +265,7 @@ def command(self, cmd, **kwds): ret = self.cmd(cmd, kwds) if 'error' in ret: raise QMPResponseError(ret) - return ret['return'] + return cast(QMPReturnValue, ret['return']) def pull_event(self, wait=False): """ -- 2.21.1