diff --git a/CHANGELOG.md b/CHANGELOG.md index 37037c21..25acc15c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Internal BoM: HTML rows are highlighted on hover (not just the cell). - Now information messages go to stdout (not stderr). Debug, warning and error messages still use stderr. +- Now InteractiveHtmlBom can be installed just as a plugin. ### Fixed - Extra data about drill marks in gerber files. diff --git a/kibot/__main__.py b/kibot/__main__.py index ea27a2e2..59fe7102 100644 --- a/kibot/__main__.py +++ b/kibot/__main__.py @@ -225,6 +225,10 @@ def detect_kicad(): GS.kicad_version_n = GS.kicad_version_major*1000000+GS.kicad_version_minor*1000+GS.kicad_version_patch logger.debug('Detected KiCad v{}.{}.{} ({} {})'.format(GS.kicad_version_major, GS.kicad_version_minor, GS.kicad_version_patch, GS.kicad_version, GS.kicad_version_n)) + # Used to look for plug-ins. + # KICAD_PATH isn't good on my system. + # The kicad-nightly package overwrites the regular package!! + GS.kicad_share_path = '/usr/share/kicad' if GS.kicad_version_n >= KICAD_VERSION_5_99: # pragma: no cover (Ki6) GS.kicad_conf_path = pcbnew.GetSettingsManager().GetUserSettingsPath() if nightly: @@ -232,9 +236,24 @@ def detect_kicad(): # This script defines KICAD_CONFIG_HOME="$HOME/.config/kicadnightly" # So we just patch it, as we patch the name of the binaries GS.kicad_conf_path = GS.kicad_conf_path.replace('/kicad/', '/kicadnightly/') + GS.kicad_share_path = GS.kicad_share_path.replace('/kicad/', '/kicadnightly/') else: logger.debug('Ignore the next message about creating a wxApp, is a KiCad 5 bug (6989)') GS.kicad_conf_path = pcbnew.GetKicadConfigPath() + # Dirs to look for plugins + GS.kicad_plugins_dirs = [] + # /usr/share/kicad/* + GS.kicad_plugins_dirs.append(os.path.join(GS.kicad_share_path, 'scripting')) + GS.kicad_plugins_dirs.append(os.path.join(GS.kicad_share_path, 'scripting', 'plugins')) + # ~/.config/kicad/* + GS.kicad_plugins_dirs.append(os.path.join(GS.kicad_conf_path, 'scripting')) + GS.kicad_plugins_dirs.append(os.path.join(GS.kicad_conf_path, 'scripting', 'plugins')) + # ~/.kicad_plugins and ~/.kicad + if 'HOME' in os.environ: + home = os.environ['HOME'] + GS.kicad_plugins_dirs.append(os.path.join(home, '.kicad_plugins')) + GS.kicad_plugins_dirs.append(os.path.join(home, '.kicad','scripting')) + GS.kicad_plugins_dirs.append(os.path.join(home, '.kicad','scripting','plugins')) if GS.debug_level > 1: logger.debug('KiCad config path {}'.format(GS.kicad_conf_path)) diff --git a/kibot/gs.py b/kibot/gs.py index 0e06510c..8c5fc94b 100644 --- a/kibot/gs.py +++ b/kibot/gs.py @@ -39,6 +39,8 @@ class GS(object): time = n.strftime('%H-%M-%S') kicad_version = '' kicad_conf_path = None + kicad_share_path = None + kicad_plugins_dirs = [] # KiCad version: major*1e6+minor*1e3+patch kicad_version_n = 0 kicad_version_major = 0 diff --git a/kibot/kiplot.py b/kibot/kiplot.py index 5841ff18..78a80141 100644 --- a/kibot/kiplot.py +++ b/kibot/kiplot.py @@ -118,6 +118,19 @@ def check_eeschema_do(): check_script(CMD_EESCHEMA_DO, URL_EESCHEMA_DO, '1.5.4') +def search_as_plugin(cmd, names): + """ If a command isn't in the path look for it in the KiCad plugins """ + if which(cmd) is not None: + return cmd + for dir in GS.kicad_plugins_dirs: + for name in names: + fname = os.path.join(dir, name, cmd) + if os.path.isfile(fname): + logger.debug('Using `{}` for `{}` ({})'.format(fname, cmd, name)) + return fname + return cmd + + def exec_with_retry(cmd): logger.debug('Executing: '+str(cmd)) retry = 2 diff --git a/kibot/out_ibom.py b/kibot/out_ibom.py index 855a97f3..294b5a62 100644 --- a/kibot/out_ibom.py +++ b/kibot/out_ibom.py @@ -7,7 +7,7 @@ import os from subprocess import (check_output, STDOUT, CalledProcessError) from .misc import (CMD_IBOM, URL_IBOM, BOM_ERROR, W_EXTNAME) from .gs import (GS) -from .kiplot import check_script +from .kiplot import check_script, search_as_plugin from .out_base import VariantOptions from .macros import macros, document, output_class # noqa: F401 from . import log @@ -110,11 +110,12 @@ class IBoMOptions(VariantOptions): def run(self, output_dir): super().run(output_dir) - check_script(CMD_IBOM, URL_IBOM) + tool = search_as_plugin(CMD_IBOM, ['InteractiveHtmlBom', 'InteractiveHtmlBom/InteractiveHtmlBom']) + check_script(tool, URL_IBOM) logger.debug('Doing Interactive BoM') # Tell ibom we don't want to use the screen os.environ['INTERACTIVE_HTML_BOM_NO_DISPLAY'] = '' - cmd = [CMD_IBOM, GS.pcb_file, '--dest-dir', output_dir, '--no-browser', ] + cmd = [tool, GS.pcb_file, '--dest-dir', output_dir, '--no-browser', ] # Solve the output name output = None if self.output: diff --git a/tests/test_plot/test_misc_2.py b/tests/test_plot/test_misc_2.py index c742c6da..bafd4214 100644 --- a/tests/test_plot/test_misc_2.py +++ b/tests/test_plot/test_misc_2.py @@ -161,6 +161,7 @@ def test_ibom_parse_fail(test_dir, caplog, monkeypatch): with monkeypatch.context() as m: patch_functions(m) with context.cover_it(cov): + detect_kicad() # Load the plug-ins load_actions() # Create an ibom object