From 190dc0a389875df76d994c396451e2415aa4f4bf Mon Sep 17 00:00:00 2001 From: "Salvador E. Tropea" Date: Fri, 5 Jan 2024 12:52:46 -0300 Subject: [PATCH] Unified the exit point for errors running external commands --- .coveragerc | 21 --------------------- kibot/gs.py | 14 ++++++++++++-- kibot/kiplot.py | 5 +---- kibot/out_base_3d.py | 3 +-- kibot/out_compress.py | 6 +----- kibot/out_diff.py | 5 +---- kibot/out_ibom.py | 9 +++------ kibot/out_kibom.py | 10 ++-------- kibot/out_kicost.py | 5 +---- kibot/out_pcb_print.py | 5 +---- kibot/out_pcbdraw.py | 5 +---- kibot/out_pdfunite.py | 6 +----- kibot/out_render_3d.py | 5 +---- kibot/out_report.py | 5 +---- 14 files changed, 27 insertions(+), 77 deletions(-) delete mode 100644 .coveragerc diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index e79af2b8d..000000000 --- a/.coveragerc +++ /dev/null @@ -1,21 +0,0 @@ -[run] -source = - kibot - src -omit = */kibot/blender_scripts/* - */kibot/docopt.py - */kibot/kicad/sexpdata.py - */kibot/mcpy/* - */kibot/mcpyrate/* - */kibot/PyPDF2/* - */kibot/PcbDraw/* - */kibot/svgutils/* -parallel = true - -[report] -exclude_lines = - pragma: no cover -# @pre_class -# @output_class -# raise RuntimeError - diff --git a/kibot/gs.py b/kibot/gs.py index df9192e13..cf9e8d361 100644 --- a/kibot/gs.py +++ b/kibot/gs.py @@ -779,13 +779,23 @@ def trace_dump(): print_tb(traceback) @staticmethod - def exit_with_error(msg, level): + def exit_with_error(msg, level, run_error=None, hints=None): GS.trace_dump() if isinstance(msg, (tuple, list)): for m in msg: logger.error(m) - else: + elif msg: logger.error(msg) + if run_error: + if not msg: + logger.error('Running {} returned {}'.format(run_error.cmd, run_error.returncode)) + if run_error.output: + out = run_error.output.decode() + logger.debug('- Output from command: '+out) + if hints: + for h in hints: + if h[0] in out: + logger.error(h[1]) exit(level) @staticmethod diff --git a/kibot/kiplot.py b/kibot/kiplot.py index 76b84adf5..9cc90abd6 100644 --- a/kibot/kiplot.py +++ b/kibot/kiplot.py @@ -12,7 +12,6 @@ from collections import OrderedDict import os import re -from sys import exit from sys import path as sys_path from shutil import which, copy2 from subprocess import run, PIPE, STDOUT, Popen, CalledProcessError @@ -164,9 +163,7 @@ def run_command(command, change_to=None, just_raise=False, use_x11=False): except CalledProcessError as e: if just_raise: raise - logger.error('Running {} returned {}'.format(e.cmd, e.returncode)) - debug_output(e) - exit(FAILED_EXECUTE) + GS.exit_with_error(None, FAILED_EXECUTE, e) debug_output(res) return res.stdout.decode().rstrip() diff --git a/kibot/out_base_3d.py b/kibot/out_base_3d.py index fc3679234..f08e34326 100644 --- a/kibot/out_base_3d.py +++ b/kibot/out_base_3d.py @@ -549,8 +549,7 @@ def filter_components(self, highlight=None, force_wrl=False): if GS.sch_file: GS.load_sch() all_comps = GS.sch.get_components() - if (GS.global_kicad_dnp_applies_to_3D and - any((c.kicad_dnp is not None and c.kicad_dnp for c in all_comps))): + if (GS.global_kicad_dnp_applies_to_3D and any((c.kicad_dnp is not None and c.kicad_dnp for c in all_comps))): # One or more components are DNP, remove them reset_filters(all_comps) all_comps_hash = {c.ref: c for c in all_comps} diff --git a/kibot/out_compress.py b/kibot/out_compress.py index 785b86b7d..e82850de1 100644 --- a/kibot/out_compress.py +++ b/kibot/out_compress.py @@ -18,7 +18,6 @@ import os import glob import sys -from sys import exit from subprocess import check_output, STDOUT, CalledProcessError from zipfile import ZipFile, ZIP_STORED, ZIP_DEFLATED, ZIP_BZIP2, ZIP_LZMA from tarfile import open as tar_open @@ -126,10 +125,7 @@ def create_rar(self, output, files): try: check_output(cmd, stderr=STDOUT) except CalledProcessError as e: - logger.error('Failed to invoke rar command, error {}'.format(e.returncode)) - if e.output: - logger.debug('Output from command: '+e.output.decode()) - exit(WRONG_INSTALL) + GS.exit_with_error(f'Failed to invoke rar command, error {e.returncode}', WRONG_INSTALL, e) def solve_extension(self): if self.format == 'ZIP': diff --git a/kibot/out_diff.py b/kibot/out_diff.py index 5d76df939..276af4b40 100644 --- a/kibot/out_diff.py +++ b/kibot/out_diff.py @@ -543,10 +543,7 @@ def do_compare(self, old, old_type, new, new_type, name, name_ori): except CalledProcessError as e: if e.returncode == 10: GS.exit_with_error('Diff above the threshold', DIFF_TOO_BIG) - logger.error('Running {} returned {}'.format(e.cmd, e.returncode)) - if e.stdout: - logger.debug('- Output from command: '+e.stdout.decode()) - exit(FAILED_EXECUTE) + GS.exit_with_error(None, FAILED_EXECUTE, e) if self.add_link_id: name_comps = os.path.splitext(name_ori) target = name_comps[0]+'_'+gh1+'-'+gh2+name_comps[1] diff --git a/kibot/out_ibom.py b/kibot/out_ibom.py index da4cf6c12..fd12128cd 100644 --- a/kibot/out_ibom.py +++ b/kibot/out_ibom.py @@ -231,12 +231,9 @@ def run(self, name): if 'ERROR Parsing failed' in cmd_output_dec: raise CalledProcessError(1, cmd, cmd_output) except CalledProcessError as e: - logger.error('Failed to create BoM, error %d', e.returncode) - if e.output: - logger.debug('Output from command: '+e.output.decode()) - if "'PCB_SHAPE' object has no attribute 'GetAngle'" in e.output.decode(): - logger.error("Update Interactive HTML BoM your version doesn't support KiCad 6 files") - exit(BOM_ERROR) + GS.exit_with_error(f'Failed to create BoM, error {e.returncode}', BOM_ERROR, e, + ("'PCB_SHAPE' object has no attribute 'GetAngle'", + "Update Interactive HTML BoM your version doesn't support KiCad 6 files")) finally: if net_dir: logger.debug('Removing temporal variant dir `{}`'.format(net_dir)) diff --git a/kibot/out_kibom.py b/kibot/out_kibom.py index 3a62e46c5..a669e0e51 100644 --- a/kibot/out_kibom.py +++ b/kibot/out_kibom.py @@ -218,10 +218,7 @@ def _get_columns(): with open(csv, 'rt') as f: columns = f.readline().rstrip().split(',') except CalledProcessError as e: - logger.error('Failed to get the column names for `{}`, error {}'.format(xml, e.returncode)) - if e.output: - logger.debug('Output from command: '+e.output.decode()) - exit(BOM_ERROR) + GS.exit_with_error(f'Failed to get the column names for `{xml}`, error {e.returncode}', BOM_ERROR, e) finally: if config: os.remove(config) @@ -433,10 +430,7 @@ def run(self, name): try: cmd_output = check_output(cmd, stderr=STDOUT) except CalledProcessError as e: - logger.error('Failed to create BoM, error %d', e.returncode) - if e.output: - logger.debug('Output from command: '+e.output.decode()) - exit(BOM_ERROR) + GS.exit_with_error(f'Failed to create BoM, error {e.returncode}', BOM_ERROR, e) if force_output: # When we create the .ini we can control the name. # But when the user does it we can trust the settings. diff --git a/kibot/out_kicost.py b/kibot/out_kicost.py index 84218b203..c546dad27 100644 --- a/kibot/out_kicost.py +++ b/kibot/out_kicost.py @@ -218,10 +218,7 @@ def run(self, name): cmd_output = check_output(cmd, stderr=STDOUT) cmd_output_dec = cmd_output.decode() except CalledProcessError as e: - logger.error('Failed to create costs spreadsheet, error %d', e.returncode) - if e.output: - logger.debug('Output from command: '+e.output.decode()) - exit(BOM_ERROR) + GS.exit_with_error(f'Failed to create costs spreadsheet, error {e.returncode}', BOM_ERROR, e) finally: if net_dir: logger.debug('Removing temporal variant dir `{}`'.format(net_dir)) diff --git a/kibot/out_pcb_print.py b/kibot/out_pcb_print.py index df4df6623..ca0da1362 100644 --- a/kibot/out_pcb_print.py +++ b/kibot/out_pcb_print.py @@ -77,10 +77,7 @@ def _run_command(cmd): try: cmd_output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: - logger.error('Failed to run %s, error %d', cmd[0], e.returncode) - if e.output: - logger.debug('Output from command: '+e.output.decode()) - exit(PDF_PCB_PRINT) + GS.exit_with_error(None, PDF_PCB_PRINT, e) if cmd_output.strip(): logger.debug('- Output from command:\n'+cmd_output.decode()) diff --git a/kibot/out_pcbdraw.py b/kibot/out_pcbdraw.py index 8a049d4aa..0877b137d 100644 --- a/kibot/out_pcbdraw.py +++ b/kibot/out_pcbdraw.py @@ -55,10 +55,7 @@ def _run_command(cmd): try: cmd_output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: - logger.error('Failed to run %s, error %d', cmd[0], e.returncode) - if e.output: - logger.debug('Output from command: '+e.output.decode()) - exit(PCBDRAW_ERR) + GS.exit_with_error(None, PCBDRAW_ERR, e) out = cmd_output.decode() if out.strip(): logger.debug('Output from command:\n'+out) diff --git a/kibot/out_pdfunite.py b/kibot/out_pdfunite.py index 6b91023ad..b31b6f5ed 100644 --- a/kibot/out_pdfunite.py +++ b/kibot/out_pdfunite.py @@ -6,7 +6,6 @@ import re import os import glob -from sys import exit from subprocess import check_output, STDOUT, CalledProcessError from .gs import GS from .error import KiPlotConfigurationError @@ -113,10 +112,7 @@ def run_external(self, files, output): except FileNotFoundError: GS.exit_with_error('Missing `pdfunite` command, install it (poppler-utils)', MISSING_TOOL) except CalledProcessError as e: - logger.error('Failed to invoke pdfunite command, error {}'.format(e.returncode)) - if e.output: - logger.error('Output from command: '+e.output.decode()) - exit(WRONG_INSTALL) + GS.exit_with_error(f'Failed to invoke pdfunite command, error {e.returncode}', WRONG_INSTALL, e) def run(self, output): # Output file name diff --git a/kibot/out_render_3d.py b/kibot/out_render_3d.py index 6e47623a2..74ae35880 100644 --- a/kibot/out_render_3d.py +++ b/kibot/out_render_3d.py @@ -29,10 +29,7 @@ def _run_command(cmd): try: cmd_output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: - logger.error('Failed to run %s, error %d', cmd[0], e.returncode) - if e.output: - logger.debug('Output from command: '+e.output.decode()) - exit(RENDER_3D_ERR) + GS.exit_with_error(None, RENDER_3D_ERR, e) if cmd_output.strip(): logger.debug('- Output from command:\n'+cmd_output.decode()) diff --git a/kibot/out_report.py b/kibot/out_report.py index ad16262fa..93bfe7b9a 100644 --- a/kibot/out_report.py +++ b/kibot/out_report.py @@ -854,10 +854,7 @@ def convert(self, fname): try: check_output(cmd, stderr=STDOUT) except CalledProcessError as e: - logger.error('{} error: {}'.format(command, e.returncode)) - if e.output: - logger.debug('Output from command: '+e.output.decode()) - exit(FAILED_EXECUTE) + GS.exit_with_error(None, FAILED_EXECUTE, e) def run(self, fname): self.pcb_material = GS.global_pcb_material