From 199e8b27b4a9df1f68eab14b0c8935b84d8e26ef Mon Sep 17 00:00:00 2001 From: Douglas Raillard Date: Mon, 26 Feb 2024 12:06:47 +0000 Subject: [PATCH] lisa.utils: Add subprocess_detailed_excep() context manager FEATURE Add a context manager that wraps subprocess.CalledProcessError into a custom exception type that adds extra details such as stdout/stderr when printing the exception. --- lisa/_kmod.py | 14 ++++---------- lisa/utils.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/lisa/_kmod.py b/lisa/_kmod.py index a5aa40096..1aab8fd1f 100644 --- a/lisa/_kmod.py +++ b/lisa/_kmod.py @@ -141,7 +141,7 @@ from devlib.target import AndroidTarget, KernelVersion, TypedKernelConfig, Kerne from devlib.host import LocalConnection from devlib.exception import TargetStableError, TargetStableCalledProcessError -from lisa.utils import nullcontext, Loggable, LISA_CACHE_HOME, checksum, DirCache, chain_cm, memoized, LISA_HOST_ABI, subprocess_log, SerializeViaConstructor, destroyablecontextmanager, ContextManagerExit, ignore_exceps, get_nested_key, is_link_dead, deduplicate +from lisa.utils import nullcontext, Loggable, LISA_CACHE_HOME, checksum, DirCache, chain_cm, memoized, LISA_HOST_ABI, subprocess_log, SerializeViaConstructor, destroyablecontextmanager, ContextManagerExit, ignore_exceps, get_nested_key, is_link_dead, deduplicate, subprocess_detailed_excep from lisa._assets import ASSETS_PATH, HOST_PATH, ABI_BINARIES_FOLDER from lisa._unshare import ensure_root import lisa._git as git @@ -263,7 +263,8 @@ def _subprocess_log(*args, env=None, extra_env=None, **kwargs): } env.update(extra_env or {}) - return subprocess_log(*args, **kwargs, env=env) + with subprocess_detailed_excep(): + return subprocess_log(*args, **kwargs, env=env) def _kbuild_make_cmd(path, targets, cc, make_vars): @@ -1939,15 +1940,8 @@ class _KernelBuildEnv(Loggable, SerializeViaConstructor): cm.__exit__(None, None, None) return - def format_excep(e): - # We expect stderr to be merged in stdout - if isinstance(e, subprocess.CalledProcessError) and e.stdout: - return f'{e}:\n{e.stdout}' - else: - return str(e) - excep_str = "\n".join( - f"{loader.__name__}: {e.__class__.__name__}: {format_excep(e)}" + f"{loader.__name__}: {e.__class__.__name__}: {e}" for loader, e in exceps ) raise ValueError(f'Could not load kernel trees:\n{excep_str}') diff --git a/lisa/utils.py b/lisa/utils.py index fa0587918..b9d0e1df7 100644 --- a/lisa/utils.py +++ b/lisa/utils.py @@ -4098,5 +4098,35 @@ def is_link_dead(url): return None +class _DetailedCalledProcessError(subprocess.CalledProcessError): + @classmethod + def _from_excep(cls, excep): + return cls(*excep.args) + + def __str__(self): + logs = [ + x for x in (self.stdout, self.stderr) + if x is not None + ] + base = super().__str__() + if logs: + logs = '\n'.join(logs) + return f'{base}:\n{logs}' + else: + return base + + +@contextlib.contextmanager +def subprocess_detailed_excep(): + """ + Context manager that will replace :class:`subprocess.CalledProcessError` by + a subclass that shows more details. + """ + + try: + yield + except subprocess.CalledProcessError as e: + raise _DetailedCalledProcessError._from_excep(e) + # vim :set tabstop=4 shiftwidth=4 textwidth=80 expandtab -- GitLab