tools (common/async_process): show command and arguments used in error message in case a failure.

This commit is contained in:
Goffi 2024-05-31 11:08:23 +02:00
commit 4fb87fb4c1

View file

@ -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 @@ class CommandProtocol(protocol.ProcessProtocol):
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 @@ class CommandProtocol(protocol.ProcessProtocol):
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 @@ class CommandProtocol(protocol.ProcessProtocol):
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