changeset 4251:601e72332907

tools (common/async_process): show command and arguments used in error message in case a failure.
author Goffi <goffi@goffi.org>
date Fri, 31 May 2024 11:08:23 +0200
parents 4b6b812f485a
children 02a7860486b5
files libervia/backend/tools/common/async_process.py
diffstat 1 files changed, 27 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/libervia/backend/tools/common/async_process.py	Fri May 31 11:08:22 2024 +0200
+++ b/libervia/backend/tools/common/async_process.py	Fri May 31 11:08:23 2024 +0200
@@ -20,6 +20,7 @@
 """tools to launch process in a async way (using Twisted)"""
 
 import os.path
+from typing import Any
 from twisted.internet import defer, reactor, protocol
 from twisted.python.failure import Failure
 from libervia.backend.core.i18n import _
@@ -46,6 +47,8 @@
         self._deferred = deferred
         self.data = []
         self.err_data = []
+        self.cmd_args: list[str]|None = None
+        self.cmd_kwargs: dict[str, Any]|None = None
 
     @property
     def command_name(self):
@@ -83,14 +86,28 @@
         else:
             err_data = b''.join(self.err_data)
 
-            msg = (_("Can't complete {name} command (error code: {code}):\n"
-                     "stderr:\n{stderr}\n{stdout}\n")
-                   .format(name = self.command_name,
-                           code = reason.value.exitCode,
-                           stderr= err_data.decode(errors='replace'),
-                           stdout = "stdout: " + data.decode(errors='replace')
-                                    if data else '',
-                           ))
+            assert self.cmd_args is not None
+            assert self.cmd_kwargs is not None
+            msg = (
+                _(
+                    "Can't complete {name} command (error code: {code}):\n"
+                    "Executed command: {command}\n"
+                    "Keyword arguments:\n"
+                    "{command_kw}\n\n"
+                    "stderr:\n{stderr}\n{stdout}\n"
+                )
+                .format(
+                    name = self.command_name,
+                    code = reason.value.exitCode,
+                    command = " ".join(self.cmd_args),
+                    command_kw = "\n".join(
+                        f"    - {k} = {v!r}" for k,v in self.cmd_kwargs.items()
+                    ),
+                    stderr= err_data.decode(errors='replace'),
+                    stdout = "stdout: " + data.decode(errors='replace')
+                    if data else '',
+                )
+            )
             self._deferred.errback(Failure(exceptions.CommandException(
                 msg, data, err_data)))
 
@@ -131,6 +148,8 @@
         else:
             command = cls.command
         cmd_args = [command] + args
+        prot.cmd_args = cmd_args
+        prot.cmd_kwargs = kwargs
         if "env" not in kwargs:
             # we pass parent environment by default
             # FIXME: `None` doesn't seem to work, despite what documentation says, to be