From 353546cee81a1c49bf6c43d4d02ee987865058ac Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Sun, 23 Apr 2023 15:47:38 +0200 Subject: [PATCH] Tweak exception handling - Remove optional exception argument of die() in favor of just using logging.error() and re-raising the exception - Instead of raising RuntimeError in die(), just call sys.exit() instead which raises SystemExit. - Show stacktrace of every exception that isn't SystemExit, KeyboardInterrupt or subprocess.CalledProcessError. --- mkosi/__main__.py | 8 -------- mkosi/log.py | 3 +-- mkosi/run.py | 15 +++++++++------ tests/test_parse_load_args.py | 6 +++--- 4 files changed, 13 insertions(+), 19 deletions(-) diff --git a/mkosi/__main__.py b/mkosi/__main__.py index 91a4f159b..fd8884f4c 100644 --- a/mkosi/__main__.py +++ b/mkosi/__main__.py @@ -37,14 +37,6 @@ def propagate_failed_return() -> Iterator[None]: # We always log when subprocess.CalledProcessError is raised, so we don't log again here. sys.exit(e.returncode) - except Exception as e: - if ARG_DEBUG.get(): - raise e - elif not isinstance(e, RuntimeError): - # RuntimeError is used to wrap generic errors, and the message that was printed should be enough. - logging.info(f"Hint: mkosi failed because of an internal exception {e.__class__.__name__}, " - "rerun mkosi with --debug to get more information") - sys.exit(1) @propagate_failed_return() diff --git a/mkosi/log.py b/mkosi/log.py index 9f11370bd..8cdfef70e 100644 --- a/mkosi/log.py +++ b/mkosi/log.py @@ -20,13 +20,12 @@ class Style: def die(message: str, - exception: Optional[Exception] = None, *, hint: Optional[str] = None) -> NoReturn: logging.error(f"{message}") if hint: logging.info(f"({hint})") - raise exception or RuntimeError(message) + sys.exit(1) def color_error(text: Any) -> str: diff --git a/mkosi/run.py b/mkosi/run.py index 6be3bb028..aaa0b0135 100644 --- a/mkosi/run.py +++ b/mkosi/run.py @@ -238,11 +238,11 @@ def run( env=env, **kwargs, preexec_fn=foreground) - except FileNotFoundError as e: - die(f"{cmdline[0]} not found in PATH.", e) + except FileNotFoundError: + die(f"{cmdline[0]} not found in PATH.") except subprocess.CalledProcessError as e: if log: - die(f'"{shlex.join(str(s) for s in cmdline)}" returned non-zero exit code {e.returncode}.', e) + logging.error(f'"{shlex.join(str(s) for s in cmdline)}" returned non-zero exit code {e.returncode}.') raise e @@ -266,7 +266,8 @@ def spawn( except FileNotFoundError: die(f"{cmdline[0]} not found in PATH.") except subprocess.CalledProcessError as e: - die(f'"{shlex.join(str(s) for s in cmdline)}" returned non-zero exit code {e.returncode}.', e) + logging.error(f'"{shlex.join(str(s) for s in cmdline)}" returned non-zero exit code {e.returncode}.') + raise e def bwrap( @@ -321,9 +322,10 @@ def bwrap( return run([*cmdline, template.format(shlex.join(str(s) for s in cmd))], text=True, stdout=stdout, env=env, log=False) except subprocess.CalledProcessError as e: + logging.error(f'"{shlex.join(str(s) for s in cmd)}" returned non-zero exit code {e.returncode}.') if ARG_DEBUG_SHELL.get(): run([*cmdline, template.format("sh")], stdin=sys.stdin, check=False, env=env, log=False) - die(f'"{shlex.join(str(s) for s in cmd)}" returned non-zero exit code {e.returncode}.') + raise e def run_workspace_command( @@ -382,9 +384,10 @@ def run_workspace_command( return run([*cmdline, template.format(shlex.join(str(s) for s in cmd))], text=True, stdout=stdout, env=env, log=False) except subprocess.CalledProcessError as e: + logging.error(f'"{shlex.join(str(s) for s in cmd)}" returned non-zero exit code {e.returncode}.') if ARG_DEBUG_SHELL.get(): run([*cmdline, template.format("sh")], stdin=sys.stdin, check=False, env=env, log=False) - die(f'"{shlex.join(str(s) for s in cmd)}" returned non-zero exit code {e.returncode}.') + raise e finally: if tmp.is_symlink(): resolve.unlink(missing_ok=True) diff --git a/tests/test_parse_load_args.py b/tests/test_parse_load_args.py index 9a06e66ff..4a5e737f0 100644 --- a/tests/test_parse_load_args.py +++ b/tests/test_parse_load_args.py @@ -75,13 +75,13 @@ def test_parse_config_files_filter() -> None: def test_shell_boot() -> None: with cd_temp_dir(): - with pytest.raises(RuntimeError, match=".boot.*tar"): + with pytest.raises(SystemExit): parse(["--format", "tar", "boot"]) - with pytest.raises(RuntimeError, match=".boot.*cpio"): + with pytest.raises(SystemExit): parse(["--format", "cpio", "boot"]) - with pytest.raises(RuntimeError, match=".boot.*compressed" ): + with pytest.raises(SystemExit): parse(["--format", "disk", "--compress-output=yes", "boot"]) -- 2.47.2