import traceback import subprocess errors = [] warnings = [] class Entry: def __init__(self, msg): self.msgs = [msg] def more(self, *msgs): if len(msgs) == 0: msgs = [""] for msg in msgs: print(msg) self.msgs.append(msg) def log_error(msg): msg = f"ERROR: {msg}" print(msg) entry = Entry(msg) errors.append(entry) return entry def log_warning(msg): msg = f"WARNING: {msg}" print(msg) entry = Entry(msg) warnings.append(entry) return entry def log_finish(success): if success and len(errors) + len(warnings) == 0: print("Task completed successfully.") return print() result_str = "succeeded" if success else "failed" errors_str = "1 error" if len(errors) == 1 else f"{len(errors)} errors" warnings_str = "1 warning" if len(warnings) == 1 else f"{len(warnings)} warnings" if len(errors) > 0 and len(warnings) > 0: print(f"Task {result_str} with {errors_str} and {warnings_str}:") for entry in warnings: print("\n".join(entry.msgs)) for entry in errors: print("\n".join(entry.msgs)) elif len(errors) > 0: print(f"Task {result_str} with {errors_str}:") for entry in errors: print("\n".join(entry.msgs)) elif len(warnings) > 0: print(f"Task {result_str} with {warnings_str}:") for entry in warnings: print("\n".join(entry.msgs)) def shellish(func): def shellfunc(*args, **kwargs): exitcode = 0 try: func(*args, **kwargs) except subprocess.CalledProcessError as err: msg = log_error(f"The following command failed with code {err.returncode}:") msg.more(" ".join(err.cmd)) exitcode = err.returncode except SystemExit as err: exitcode = err.code except Exception as err: log_error(err) print(traceback.format_exc()) exitcode = 1 except: print("something went REALLY wrong and also Ben does not know how to handle Python errors") exitcode = 1 finally: log_finish(exitcode == 0) exit(exitcode) return shellfunc