On 5/14/20 7:53 AM, John Snow wrote: > 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): > """ >
Acked-by: Philippe Mathieu-Daudé <phi...@redhat.com>