qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: John Snow <jsnow@redhat.com>
To: qemu-devel@nongnu.org
Cc: qemu-block@nongnu.org, "Cleber Rosa" <crosa@redhat.com>,
	"Daniel Berrangé" <berrange@redhat.com>,
	"Hanna Reitz" <hreitz@redhat.com>, "John Snow" <jsnow@redhat.com>,
	"Kevin Wolf" <kwolf@redhat.com>
Subject: [PATCH v2 01/18] python: backport 'Change error classes to have better repr methods'
Date: Wed,  3 Sep 2025 01:11:07 -0400	[thread overview]
Message-ID: <20250903051125.3020805-2-jsnow@redhat.com> (raw)
In-Reply-To: <20250903051125.3020805-1-jsnow@redhat.com>

By passing all of the arguments to the base class and overriding the
__str__ method when we want a different "human readable" message that
isn't just printing the list of arguments, we can ensure that all custom
error classes have a reasonable __repr__ implementation.

In the case of ExecuteError, the pseudo-field that isn't actually
correlated to an input argument can be re-imagined as a read-only
property; this forces consistency in the class and makes the repr output
more obviously correct.

Signed-off-by: John Snow <jsnow@redhat.com>
cherry picked from commit afdb7893f3b34212da4259b7202973f9a8cb85b3
---
 python/qemu/qmp/error.py      |  7 +++++--
 python/qemu/qmp/message.py    | 12 ++++++------
 python/qemu/qmp/protocol.py   |  7 +++++--
 python/qemu/qmp/qmp_client.py | 20 +++++++++++++-------
 4 files changed, 29 insertions(+), 17 deletions(-)

diff --git a/python/qemu/qmp/error.py b/python/qemu/qmp/error.py
index 24ba4d50541..c87b078f620 100644
--- a/python/qemu/qmp/error.py
+++ b/python/qemu/qmp/error.py
@@ -44,7 +44,10 @@ class ProtocolError(QMPError):
 
     :param error_message: Human-readable string describing the error.
     """
-    def __init__(self, error_message: str):
-        super().__init__(error_message)
+    def __init__(self, error_message: str, *args: object):
+        super().__init__(error_message, *args)
         #: Human-readable error message, without any prefix.
         self.error_message: str = error_message
+
+    def __str__(self) -> str:
+        return self.error_message
diff --git a/python/qemu/qmp/message.py b/python/qemu/qmp/message.py
index f76ccc90746..c2e9dd0dd54 100644
--- a/python/qemu/qmp/message.py
+++ b/python/qemu/qmp/message.py
@@ -178,15 +178,15 @@ class DeserializationError(ProtocolError):
     :param raw: The raw `bytes` that prompted the failure.
     """
     def __init__(self, error_message: str, raw: bytes):
-        super().__init__(error_message)
+        super().__init__(error_message, raw)
         #: The raw `bytes` that were not understood as JSON.
         self.raw: bytes = raw
 
     def __str__(self) -> str:
-        return "\n".join([
+        return "\n".join((
             super().__str__(),
             f"  raw bytes were: {str(self.raw)}",
-        ])
+        ))
 
 
 class UnexpectedTypeError(ProtocolError):
@@ -197,13 +197,13 @@ class UnexpectedTypeError(ProtocolError):
     :param value: The deserialized JSON value that wasn't an object.
     """
     def __init__(self, error_message: str, value: object):
-        super().__init__(error_message)
+        super().__init__(error_message, value)
         #: The JSON value that was expected to be an object.
         self.value: object = value
 
     def __str__(self) -> str:
         strval = json.dumps(self.value, indent=2)
-        return "\n".join([
+        return "\n".join((
             super().__str__(),
             f"  json value was: {strval}",
-        ])
+        ))
diff --git a/python/qemu/qmp/protocol.py b/python/qemu/qmp/protocol.py
index a4ffdfad51b..86e588881b7 100644
--- a/python/qemu/qmp/protocol.py
+++ b/python/qemu/qmp/protocol.py
@@ -80,7 +80,7 @@ class ConnectError(QMPError):
     :param exc: The root-cause exception.
     """
     def __init__(self, error_message: str, exc: Exception):
-        super().__init__(error_message)
+        super().__init__(error_message, exc)
         #: Human-readable error string
         self.error_message: str = error_message
         #: Wrapped root cause exception
@@ -108,11 +108,14 @@ class StateError(QMPError):
     """
     def __init__(self, error_message: str,
                  state: Runstate, required: Runstate):
-        super().__init__(error_message)
+        super().__init__(error_message, state, required)
         self.error_message = error_message
         self.state = state
         self.required = required
 
+    def __str__(self) -> str:
+        return self.error_message
+
 
 F = TypeVar('F', bound=Callable[..., Any])  # pylint: disable=invalid-name
 
diff --git a/python/qemu/qmp/qmp_client.py b/python/qemu/qmp/qmp_client.py
index 2a817f9db33..a87fb565ab5 100644
--- a/python/qemu/qmp/qmp_client.py
+++ b/python/qemu/qmp/qmp_client.py
@@ -41,7 +41,7 @@ class _WrappedProtocolError(ProtocolError):
     :param exc: The root-cause exception.
     """
     def __init__(self, error_message: str, exc: Exception):
-        super().__init__(error_message)
+        super().__init__(error_message, exc)
         self.exc = exc
 
     def __str__(self) -> str:
@@ -76,15 +76,21 @@ class ExecuteError(QMPError):
     """
     def __init__(self, error_response: ErrorResponse,
                  sent: Message, received: Message):
-        super().__init__(error_response.error.desc)
+        super().__init__(error_response, sent, received)
         #: The sent `Message` that caused the failure
         self.sent: Message = sent
         #: The received `Message` that indicated failure
         self.received: Message = received
         #: The parsed error response
         self.error: ErrorResponse = error_response
-        #: The QMP error class
-        self.error_class: str = error_response.error.class_
+
+    @property
+    def error_class(self) -> str:
+        """The QMP error class"""
+        return self.error.error.class_
+
+    def __str__(self) -> str:
+        return self.error.error.desc
 
 
 class ExecInterruptedError(QMPError):
@@ -110,8 +116,8 @@ class _MsgProtocolError(ProtocolError):
     :param error_message: Human-readable string describing the error.
     :param msg: The QMP `Message` that caused the error.
     """
-    def __init__(self, error_message: str, msg: Message):
-        super().__init__(error_message)
+    def __init__(self, error_message: str, msg: Message, *args: object):
+        super().__init__(error_message, msg, *args)
         #: The received `Message` that caused the error.
         self.msg: Message = msg
 
@@ -150,7 +156,7 @@ class BadReplyError(_MsgProtocolError):
     :param sent: The message that was sent that prompted the error.
     """
     def __init__(self, error_message: str, msg: Message, sent: Message):
-        super().__init__(error_message, msg)
+        super().__init__(error_message, msg, sent)
         #: The sent `Message` that caused the failure
         self.sent = sent
 
-- 
2.50.1



  reply	other threads:[~2025-09-03  5:14 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-09-03  5:11 [PATCH v2 00/18] python: 3.14 compatibility and python-qemu-qmp synchronization John Snow
2025-09-03  5:11 ` John Snow [this message]
2025-09-08 16:23   ` [PATCH v2 01/18] python: backport 'Change error classes to have better repr methods' Daniel P. Berrangé
2025-09-08 17:16     ` John Snow
2025-09-03  5:11 ` [PATCH v2 02/18] python: backport 'EventListener: add __repr__ method' John Snow
2025-09-08 16:24   ` Daniel P. Berrangé
2025-09-03  5:11 ` [PATCH v2 03/18] python: backport 'kick event queue on legacy event_pull()' John Snow
2025-09-08 16:24   ` Daniel P. Berrangé
2025-09-03  5:11 ` [PATCH v2 04/18] python: backport 'protocol: adjust logging name when changing client name' John Snow
2025-09-08 16:25   ` Daniel P. Berrangé
2025-09-03  5:11 ` [PATCH v2 05/18] python: backport 'drop Python3.6 workarounds' John Snow
2025-09-08 16:28   ` Daniel P. Berrangé
2025-09-03  5:11 ` [PATCH v2 06/18] python: backport 'qmp-shell: add common_parser()' John Snow
2025-09-08 16:47   ` Daniel P. Berrangé
2025-09-08 17:39     ` John Snow
2025-09-08 18:16       ` Daniel P. Berrangé
2025-09-03  5:11 ` [PATCH v2 07/18] python: backport 'feat: allow setting read buffer limit' John Snow
2025-09-08 16:49   ` Daniel P. Berrangé
2025-09-03  5:11 ` [PATCH v2 08/18] python: backport 'make require() preserve async-ness' John Snow
2025-09-08 16:50   ` Daniel P. Berrangé
2025-09-03  5:11 ` [PATCH v2 09/18] python: backport 'qmp-shell-wrap: handle missing binary gracefully' John Snow
2025-09-08 16:50   ` Daniel P. Berrangé
2025-09-03  5:11 ` [PATCH v2 10/18] python: backport 'qmp-tui: Do not crash if optional dependencies are not met' John Snow
2025-09-08 16:51   ` Daniel P. Berrangé
2025-09-03  5:11 ` [PATCH v2 11/18] python: backport 'Remove deprecated get_event_loop calls' John Snow
2025-09-08 16:52   ` Daniel P. Berrangé
2025-09-03  5:11 ` [PATCH v2 12/18] python: backport 'avoid creating additional event loops per thread' John Snow
2025-09-08 16:52   ` Daniel P. Berrangé
2025-09-03  5:11 ` [PATCH v2 13/18] python: synchronize qemu.qmp documentation John Snow
2025-09-08 16:53   ` Daniel P. Berrangé
2025-09-03  5:11 ` [PATCH v2 14/18] iotests: drop compat for old version context manager John Snow
2025-09-03  5:11 ` [PATCH v2 15/18] python: ensure QEMUQtestProtocol closes its socket John Snow
2025-09-03  5:11 ` [PATCH v2 16/18] iotests/147: ensure temporary sockets are closed before exiting John Snow
2025-09-03  5:11 ` [PATCH v2 17/18] iotests/151: ensure subprocesses are cleaned up John Snow
2025-09-03  5:11 ` [PATCH v2 18/18] iotests/check: always enable all python warnings John Snow

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=20250903051125.3020805-2-jsnow@redhat.com \
    --to=jsnow@redhat.com \
    --cc=berrange@redhat.com \
    --cc=crosa@redhat.com \
    --cc=hreitz@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=qemu-block@nongnu.org \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).