All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Philippe Mathieu-Daudé" <philmd@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Kevin Wolf" <kwolf@redhat.com>,
	"Eduardo Habkost" <ehabkost@redhat.com>,
	"John Snow" <jsnow@redhat.com>,
	"Ahmed Karaman" <ahmedkhaledkaraman@gmail.com>,
	"Cleber Rosa" <crosa@redhat.com>,
	"Philippe Mathieu-Daudé" <philmd@redhat.com>
Subject: [PULL 18/19] python/qmp.py: add casts to JSON deserialization
Date: Wed, 15 Jul 2020 00:21:31 +0200	[thread overview]
Message-ID: <20200714222132.10815-19-philmd@redhat.com> (raw)
In-Reply-To: <20200714222132.10815-1-philmd@redhat.com>

From: John Snow <jsnow@redhat.com>

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 <jsnow@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20200710052220.3306-6-jsnow@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
 python/qemu/qmp.py | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/python/qemu/qmp.py b/python/qemu/qmp.py
index ef3c919b76..1ae36050a4 100644
--- a/python/qemu/qmp.py
+++ b/python/qemu/qmp.py
@@ -13,6 +13,7 @@
 import logging
 from typing import (
     Any,
+    cast,
     Dict,
     Optional,
     TextIO,
@@ -130,7 +131,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: QMPMessage = json.loads(data)
             if 'event' in resp:
                 self.logger.debug("<<< %s", resp)
                 self.__events.append(resp)
@@ -262,7 +266,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.3



  parent reply	other threads:[~2020-07-14 22:33 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-07-14 22:21 [PULL 00/19] Python patches for 5.1 Philippe Mathieu-Daudé
2020-07-14 22:21 ` [PULL 01/19] scripts/performance: Add dissect.py script Philippe Mathieu-Daudé
2020-07-14 22:21 ` [PULL 02/19] python/machine.py: consolidate _post_shutdown() Philippe Mathieu-Daudé
2020-07-14 22:21 ` [PULL 03/19] python/machine.py: Close QMP socket in cleanup Philippe Mathieu-Daudé
2020-07-14 22:21 ` [PULL 04/19] python/machine.py: Add _early_cleanup hook Philippe Mathieu-Daudé
2020-07-14 22:21 ` [PULL 05/19] python/machine.py: Perform early cleanup for wait() calls, too Philippe Mathieu-Daudé
2020-07-14 22:21 ` [PULL 06/19] python/machine.py: Prohibit multiple shutdown() calls Philippe Mathieu-Daudé
2020-07-14 22:21 ` [PULL 07/19] python/machine.py: Add a configurable timeout to shutdown() Philippe Mathieu-Daudé
2020-07-14 22:21 ` [PULL 08/19] python/machine.py: Make wait() call shutdown() Philippe Mathieu-Daudé
2020-07-14 22:21 ` [PULL 09/19] tests/acceptance: wait() instead of shutdown() where appropriate Philippe Mathieu-Daudé
2020-07-14 22:21 ` [PULL 10/19] tests/acceptance: Don't test reboot on cubieboard Philippe Mathieu-Daudé
2020-07-14 22:21 ` [PULL 11/19] python/machine.py: split shutdown into hard and soft flavors Philippe Mathieu-Daudé
2020-07-14 22:21 ` [PULL 12/19] python/machine.py: re-add sigkill warning suppression Philippe Mathieu-Daudé
2020-07-14 22:21 ` [PULL 13/19] python/machine.py: change default wait timeout to 3 seconds Philippe Mathieu-Daudé
2020-07-14 22:21 ` [PULL 14/19] python/qmp.py: Define common types Philippe Mathieu-Daudé
2020-07-14 22:21 ` [PULL 15/19] iotests.py: use qemu.qmp type aliases Philippe Mathieu-Daudé
2020-07-14 22:21 ` [PULL 16/19] python/qmp.py: re-absorb MonitorResponseError Philippe Mathieu-Daudé
2020-07-14 22:21 ` [PULL 17/19] python/qmp.py: Do not return None from cmd_obj Philippe Mathieu-Daudé
2020-07-14 22:21 ` Philippe Mathieu-Daudé [this message]
2020-07-14 22:21 ` [PULL 19/19] python/qmp.py: add QMPProtocolError Philippe Mathieu-Daudé
2020-07-15 12:53 ` [PULL 00/19] Python patches for 5.1 Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200714222132.10815-19-philmd@redhat.com \
    --to=philmd@redhat.com \
    --cc=ahmedkhaledkaraman@gmail.com \
    --cc=crosa@redhat.com \
    --cc=ehabkost@redhat.com \
    --cc=jsnow@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.