From 4538236574898c26abd062853b03ffaaab322387 Mon Sep 17 00:00:00 2001 From: "Salvador E. Tropea" Date: Thu, 2 Jul 2020 12:30:30 -0300 Subject: [PATCH] Now outputs and preflights are loaded as plugins. They can be added from ~/.config/kiplot/plugins/ Also sorted the preflights in the YAML example and allower -v for --help-list-outputs, needed to know from where are the plugins loaded. --- README.md | 2 +- docs/samples/generic_plot.kiplot.yaml | 18 +++++++-------- kiplot/__main__.py | 7 ++++-- kiplot/config_reader.py | 25 +------------------- kiplot/kiplot.py | 33 +++++++++++++++++++++++++++ 5 files changed, 49 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 8d239e34..033d5e79 100644 --- a/README.md +++ b/README.md @@ -520,7 +520,7 @@ Usage: [-q | -v...] [-i] [TARGET...] kiplot [-c PLOT_CONFIG] --list kiplot [-b BOARD] [-d OUT_DIR] [-p] --example - kiplot --help-list-outputs + kiplot [-v] --help-list-outputs kiplot --help-output=HELP_OUTPUT kiplot --help-outputs kiplot --help-preflights diff --git a/docs/samples/generic_plot.kiplot.yaml b/docs/samples/generic_plot.kiplot.yaml index c19c05f6..3c2d6933 100644 --- a/docs/samples/generic_plot.kiplot.yaml +++ b/docs/samples/generic_plot.kiplot.yaml @@ -2,21 +2,21 @@ kiplot: version: 1 preflight: + # [boolean=false] Zones are filled before doing any operation involving PCB layers + check_zone_fills: true + # A list of entries to filter out ERC/DRC messages. Keys: `filter`, `number` and `regex` + filters: + - filter: 'Filter description' + number: 10 + regex: 'Regular expression to match' + # [boolean=false] Option for `run_drc`. Ignores the unconnected nets. Useful if you didn't finish the routing + ignore_unconnected: false # [boolean=false] Runs the DRC (Distance Rules Check). To ensure we have a valid PCB run_drc: true # [boolean=false] Runs the ERC (Electrical Rules Check). To ensure the schematic is electrically correct run_erc: true # [boolean=false] Update the XML version of the BoM (Bill of Materials). To ensure our generated BoM is up to date update_xml: true - # [boolean=false] Zones are filled before doing any operation involving PCB layers - check_zone_fills: true - # [boolean=false] Option for `run_drc`. Ignores the unconnected nets. Useful if you didn't finish the routing - ignore_unconnected: false - # A list of entries to filter out ERC/DRC messages. Keys: `filter`, `number` and `regex` - filters: - - filter: 'Filter description' - number: 10 - regex: 'Regular expression to match' outputs: # DXF (Drawing Exchange Format): diff --git a/kiplot/__main__.py b/kiplot/__main__.py index 5d7f4854..17df82d4 100644 --- a/kiplot/__main__.py +++ b/kiplot/__main__.py @@ -6,7 +6,7 @@ Usage: [-q | -v...] [-i] [TARGET...] kiplot [-c PLOT_CONFIG] --list kiplot [-b BOARD] [-d OUT_DIR] [-p] --example - kiplot --help-list-outputs + kiplot [-v] --help-list-outputs kiplot --help-output=HELP_OUTPUT kiplot --help-outputs kiplot --help-preflights @@ -53,7 +53,7 @@ from logging import DEBUG from . import log log.set_domain('kiplot') from .gs import (GS) -from .kiplot import (generate_outputs) +from .kiplot import (generate_outputs, load_actions) from .pre_base import (BasePreFlight) from .config_reader import (CfgYamlReader, print_outputs_help, print_output_help, print_preflights_help, create_example) from .misc import (NO_PCB_FILE, NO_SCH_FILE, EXIT_BAD_ARGS) @@ -162,6 +162,9 @@ def main(): # Output dir: relative to CWD (absolute path overrides) GS.out_dir = os.path.join(os.getcwd(), args.out_dir) + # Load output and preflight plugins + load_actions() + if args.help_outputs or args.help_list_outputs: print_outputs_help(details=args.help_outputs) sys.exit(0) diff --git a/kiplot/config_reader.py b/kiplot/config_reader.py index c346a05e..876ac536 100644 --- a/kiplot/config_reader.py +++ b/kiplot/config_reader.py @@ -9,31 +9,8 @@ from collections import OrderedDict from .error import (KiPlotConfigurationError) from .kiplot import (Layer, load_board) from .misc import (NO_YAML_MODULE, EXIT_BAD_CONFIG, EXIT_BAD_ARGS, EXAMPLE_CFG, WONT_OVERWRITE) -from mcpy import activate # noqa: F401 -# Output classes from .out_base import BaseOutput -from . import out_gerber # noqa: F401 -from . import out_ps # noqa: F401 -from . import out_hpgl # noqa: F401 -from . import out_dxf # noqa: F401 -from . import out_pdf # noqa: F401 -from . import out_svg # noqa: F401 -from . import out_gerb_drill # noqa: F401 -from . import out_excellon # noqa: F401 -from . import out_position # noqa: F401 -from . import out_step # noqa: F401 -from . import out_kibom # noqa: F401 -from . import out_ibom # noqa: F401 -from . import out_pdf_sch_print # noqa: F401 -from . import out_pdf_pcb_print # noqa: F401 -# PreFlight classes from .pre_base import BasePreFlight -from . import pre_drc # noqa: F401 -from . import pre_erc # noqa: F401 -from . import pre_update_xml # noqa: F401 -from . import pre_check_zone_fills # noqa: F401 -from . import pre_ignore_unconnected # noqa: F401 -from . import pre_filters # noqa: F401 # Logger from . import log @@ -316,7 +293,7 @@ def create_example(pcb_file, out_dir, copy_options): # Preflights f.write('\npreflight:\n') pres = BasePreFlight.get_registered() - for n, o in pres.items(): + for n, o in OrderedDict(sorted(pres.items())).items(): if o.__doc__: f.write(' #'+o.__doc__.rstrip()+'\n') f.write(' {}: {}\n'.format(n, o.get_example())) diff --git a/kiplot/kiplot.py b/kiplot/kiplot.py index 71b0c643..191d8f84 100644 --- a/kiplot/kiplot.py +++ b/kiplot/kiplot.py @@ -7,7 +7,9 @@ import re from sys import exit from shutil import which from subprocess import (run, PIPE) +from glob import glob from distutils.version import StrictVersion +from importlib.util import (spec_from_file_location, module_from_spec) from .gs import (GS) from .misc import (PLOT_ERROR, NO_PCBNEW_MODULE, MISSING_TOOL, CMD_EESCHEMA_DO, URL_EESCHEMA_DO, NO_SCH_FILE, CORRUPTED_PCB, @@ -18,6 +20,7 @@ from . import log logger = log.get_logger(__name__) + try: import pcbnew except ImportError: # pragma: no cover @@ -156,6 +159,36 @@ class Layer(object): return "{} ({} '{}' {})".format(self.name, self.id, self.desc, self.suffix) +def _import(name, path): + # Python 3.4+ import mechanism + spec = spec_from_file_location("kiplot."+name, path) + mod = module_from_spec(spec) + spec.loader.exec_module(mod) + + +def _load_actions(path): + logger.debug("Importing from "+path) + lst = glob(os.path.join(path, 'out_*.py')) + glob(os.path.join(path, 'pre_*.py')) + for p in lst: + name = os.path.splitext(os.path.basename(p))[0] + logger.debug("- Importing "+name) + _import(name, p) + + +def load_actions(): + """ Load all the available ouputs and preflights """ + from mcpy import activate + _load_actions(os.path.abspath(os.path.dirname(__file__))) + home = os.environ.get('HOME') + if home: + dir = os.path.join(home, '.config', 'kiplot', 'plugins') + if os.path.isdir(dir): + _load_actions(dir) + if 'de_activate' in activate.__dict__: + logger.debug('Deactivating macros') + activate.de_activate() + + def check_version(command, version): cmd = [command, '--version'] logger.debug('Running: '+str(cmd))