Commit 2e2d9305 authored by John Snow's avatar John Snow Committed by Philippe Mathieu-Daudé
Browse files

python/qmp.py: add casts to JSON deserialization



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: default avatarJohn Snow <jsnow@redhat.com>
Reviewed-by: default avatarKevin Wolf <kwolf@redhat.com>
Message-Id: <20200710052220.3306-6-jsnow@redhat.com>
Signed-off-by: default avatarPhilippe Mathieu-Daudé <philmd@redhat.com>
parent ef5d4744
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@ import socket
import logging
from typing import (
    Any,
    cast,
    Dict,
    Optional,
    TextIO,
@@ -130,7 +131,10 @@ class QEMUMonitorProtocol:
            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: QMPMessage = json.loads(data)
            if 'event' in resp:
                self.logger.debug("<<< %s", resp)
                self.__events.append(resp)
@@ -262,7 +266,7 @@ class QEMUMonitorProtocol:
        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):
        """