From ca861fc21e4293ae4dc76d4f812a64df52cc244b Mon Sep 17 00:00:00 2001 From: "Salvador E. Tropea" Date: Thu, 19 May 2022 08:47:06 -0300 Subject: [PATCH] Added dependency collection mechanism - Currently used to better document the dependencies --- README.md | 80 ++++++++++++++++++++++------ docs/README.in | 20 ++----- docs/replace_tags.pl | 2 + docs/samples/generic_plot.kibot.yaml | 4 +- kibot/__init__.py | 10 +++- kibot/__main__.py | 19 +++---- kibot/bom/xlsx_writer.py | 4 +- kibot/config_reader.py | 75 +++++++++++++++++++++++++- kibot/create_pdf.py | 43 +++++++++++++++ kibot/misc.py | 60 +++++++++++++++++++++ kibot/out_any_pcb_print.py | 7 ++- kibot/out_any_sch_print.py | 7 ++- kibot/out_bom.py | 8 ++- kibot/out_compress.py | 7 ++- kibot/out_gencad.py | 4 +- kibot/out_ibom.py | 8 ++- kibot/out_kibom.py | 10 ++-- kibot/out_kicost.py | 9 ++-- kibot/out_netlist.py | 5 +- kibot/out_pcb_print.py | 48 ++++------------- kibot/out_pcbdraw.py | 14 +++-- kibot/out_pdf_pcb_print.py | 3 +- kibot/out_pdf_sch_print.py | 3 +- kibot/out_pdfunite.py | 2 +- kibot/out_qr_lib.py | 3 ++ kibot/out_render_3d.py | 4 +- kibot/out_report.py | 8 ++- kibot/out_step.py | 4 +- kibot/out_svg_pcb_print.py | 3 +- kibot/out_svg_sch_print.py | 3 +- kibot/pre_drc.py | 14 ++--- kibot/pre_erc.py | 16 +++--- kibot/pre_update_xml.py | 16 +++--- kibot/registrable.py | 27 ++++++++++ setup.py | 4 +- 35 files changed, 415 insertions(+), 139 deletions(-) create mode 100644 kibot/create_pdf.py diff --git a/README.md b/README.md index 6385fc97..e3f2710a 100644 --- a/README.md +++ b/README.md @@ -90,21 +90,65 @@ You can also run KiBot using docker images in a CI/CD environment like GitHub or ### Dependencies -- For ERC, DRC, BoM XML update and SCH print install [KiCad Automation Scripts](https://github.com/INTI-CMNB/kicad-automation-scripts/) -- BoM files (HTML/CSV/TSV/TXT/XML/XLSX) can be generated using the internal BoM generator or using [KiBoM](https://github.com/INTI-CMNB/KiBoM). -- For interactive BoM install [InteractiveHtmlBom](https://github.com/INTI-CMNB/InteractiveHtmlBom) -- For SVG/PNG/JPG beauty PCB render [PcbDraw](https://github.com/INTI-CMNB/PcbDraw). Also install the convert (from imagemagick) and rsvg-convert (from librsvg2-bin) tools. -- For BoMs with costs information install [KiCost](https://github.com/hildogjr/KiCost/) -- To create RAR files install the rar tool. -- To generate reports in PDF format (also ODF, DOCX, etc.) install [Pandoc](https://pandoc.org/) -- If you need to generate the PCB prints in postscript format install ghostscript -- The following Python modules are also used: (Note that using pip or the Debian package they will be installed automatically) - - `colorama` - - `distutils`. This is part of Python, but on debian systems this is in a separated package: `python3-distutils` - - `qrcodegen`. Only to generate QR code symbols and footprints. - - `requests` - - `xlsxwriter`. If you need BoMs in XLSX format. - - `yaml` +Notes: +- When installing from the Debian repo you don't need to worry about dependencies, just pay attention to *recommended* and *suggested* packages. +- When installing using `pip` the dependencies marked as **PyPi dependency** will be automatically installed. + +[**distutils**](https://pypi.org/project/distutils/) (python module) [Debian](https://packages.debian.org/bullseye/python3-distutils) +- Mandatory + +[**PyYAML**](https://pypi.org/project/PyYAML/) (python module) (PyPi dependency) [Debian](https://packages.debian.org/bullseye/python3-yaml) +- Mandatory + +[**requests**](https://pypi.org/project/requests/) (python module) (PyPi dependency) [Debian](https://packages.debian.org/bullseye/python3-requests) +- Mandatory + +[**KiCad Automation tools**](https://github.com/INTI-CMNB/KiAuto) v1.6.11 (tool) (PyPi dependency) +- Mandatory for: `gencad`, `netlist`, `pdf_pcb_print`, `pdf_sch_print`, `render_3d`, `run_drc`, `run_erc`, `step`, `svg_pcb_print`, `svg_sch_print`, `update_xml` + +[**KiCost**](https://github.com/INTI-CMNB/KiCost) v1.1.8 (tool) +- Mandatory for `kicost` +- Optional to find components costs and specs for `bom` + +[**Interactive HTML BoM**](https://github.com/INTI-CMNB/InteractiveHtmlBom) v2.4.1.3 (tool) +- Mandatory for `ibom` + +[**KiBoM**](https://github.com/INTI-CMNB/KiBoM) v1.8.0 (tool) +- Mandatory for `kibom` + +[**lxml**](https://pypi.org/project/lxml/) (python module) [Debian](https://packages.debian.org/bullseye/python3-lxml) +- Mandatory for `pcb_print` + +[**PcbDraw**](https://github.com/INTI-CMNB/pcbdraw) v0.9.0 (tool) +- Mandatory for `pcbdraw` + +[**qrcodegen**](https://pypi.org/project/qrcodegen/) (python module) (PyPi dependency) [Debian](https://packages.debian.org/bullseye/python3-qrcodegen) +- Mandatory for `qr_lib` + +[**colorama**](https://pypi.org/project/colorama/) (python module) (PyPi dependency) [Debian](https://packages.debian.org/bullseye/python3-colorama) +- Optional to get color messages in a portable way for general use + +[**RSVG tools**](https://cran.r-project.org/web/packages/rsvg/index.html) (tool) [Debian](https://packages.debian.org/bullseye/librsvg2-bin) +- Optional to: + - Create PDF, PNG, EPS and PS formats for `pcb_print` + - Create PNG and JPG images for `pcbdraw` + +[**Ghostscript**](https://www.ghostscript.com/) (tool) [Debian](https://packages.debian.org/bullseye/ghostscript) +- Optional to create PS files for `pcb_print` + +[**ImageMagick**](https://imagemagick.org/) (tool) [Debian](https://packages.debian.org/bullseye/imagemagick) +- Optional to create JPG images for `pcbdraw` + +[**Pandoc**](https://pandoc.org/) (tool) [Debian](https://packages.debian.org/bullseye/pandoc) +- Optional to create PDF/ODF/DOCX files for `report` + +[**RAR**](https://www.rarlab.com/) (tool) [Debian](https://packages.debian.org/bullseye/rar) +- Optional to compress in RAR format for `compress` + +[**xlsxwriter**](https://pypi.org/project/xlsxwriter/) (python module) (PyPi dependency) [Debian](https://packages.debian.org/bullseye/python3-xlsxwriter) +- Optional to create XLSX files for `bom` + + ### Installation on Ubuntu/Debian @@ -1622,7 +1666,7 @@ Next time you need this list just use an alias, like this: - `dark_mode`: [boolean=false] Default to dark mode. - `dnf_filter`: [string|list(string)='_none'] Name of the filter to mark components as not fitted. A short-cut to use for simple cases where a variant is an overkill. - Avoid using it in conjunction with with IBoM native filtering options. + Avoid using it in conjunction with IBoM native filtering options. - `dnp_field`: [string=''] Name of the extra field that indicates do not populate status. Components with this field not empty will be blacklisted. IBoM option, avoid using in conjunction with KiBot variants/filters. @@ -1660,7 +1704,7 @@ Next time you need this list just use an alias, like this: Value and Footprint are displayed when nothing is specified. - `sort_order`: [string='C,R,L,D,U,Y,X,F,SW,A,~,HS,CNN,J,P,NT,MH'] Default sort order for components. Must contain '~' once. - `variant`: [string=''] Board variant to apply. - Avoid using it in conjunction with with IBoM native filtering options. + Avoid using it in conjunction with IBoM native filtering options. - `variant_field`: [string=''] Name of the extra field that stores board variant for component. IBoM option, avoid using in conjunction with KiBot variants/filters. - `variants_blacklist`: [string=''] List of board variants to exclude from the BOM. @@ -2982,6 +3026,7 @@ Usage: kibot [-v...] [--start PATH] [-d OUT_DIR] [--dry] [-t, --type TYPE]... --quick-start kibot [-v...] --help-filters + kibot [-v...] [--markdown] --help-dependencies kibot [-v...] --help-global-options kibot [-v...] --help-list-outputs kibot [-v...] --help-output=HELP_OUTPUT @@ -3019,6 +3064,7 @@ Quick start options: Help options: -h, --help Show this help message and exit + --help-dependencies List dependencies in human readable format --help-filters List supported filters and details --help-global-options List supported global variables --help-list-outputs List supported outputs diff --git a/docs/README.in b/docs/README.in index 10dc8043..6229dc21 100644 --- a/docs/README.in +++ b/docs/README.in @@ -90,21 +90,11 @@ You can also run KiBot using docker images in a CI/CD environment like GitHub or ### Dependencies -- For ERC, DRC, BoM XML update and SCH print install [KiCad Automation Scripts](https://github.com/INTI-CMNB/kicad-automation-scripts/) -- BoM files (HTML/CSV/TSV/TXT/XML/XLSX) can be generated using the internal BoM generator or using [KiBoM](https://github.com/INTI-CMNB/KiBoM). -- For interactive BoM install [InteractiveHtmlBom](https://github.com/INTI-CMNB/InteractiveHtmlBom) -- For SVG/PNG/JPG beauty PCB render [PcbDraw](https://github.com/INTI-CMNB/PcbDraw). Also install the convert (from imagemagick) and rsvg-convert (from librsvg2-bin) tools. -- For BoMs with costs information install [KiCost](https://github.com/hildogjr/KiCost/) -- To create RAR files install the rar tool. -- To generate reports in PDF format (also ODF, DOCX, etc.) install [Pandoc](https://pandoc.org/) -- If you need to generate the PCB prints in postscript format install ghostscript -- The following Python modules are also used: (Note that using pip or the Debian package they will be installed automatically) - - `colorama` - - `distutils`. This is part of Python, but on debian systems this is in a separated package: `python3-distutils` - - `qrcodegen`. Only to generate QR code symbols and footprints. - - `requests` - - `xlsxwriter`. If you need BoMs in XLSX format. - - `yaml` +Notes: +- When installing from the Debian repo you don't need to worry about dependencies, just pay attention to *recommended* and *suggested* packages. +- When installing using `pip` the dependencies marked as **PyPi dependency** will be automatically installed. + +@dependencies@ ### Installation on Ubuntu/Debian diff --git a/docs/replace_tags.pl b/docs/replace_tags.pl index 897bac42..be0ac300 100644 --- a/docs/replace_tags.pl +++ b/docs/replace_tags.pl @@ -5,6 +5,7 @@ $cmd_help=`../src/kibot --help`; $preflight=`../src/kibot --help-preflights`; $filters=`../src/kibot --help-filters`; $global_options=`../src/kibot --help-global-options`; +$dependencies=`../src/kibot --help-dependencies --markdown`; while (<>) { @@ -13,6 +14,7 @@ while (<>) $_ =~ s/\@preflight\@/$preflight/; $_ =~ s/\@filters\@/$filters/; $_ =~ s/\@global_options\@/$global_options/; + $_ =~ s/\@dependencies\@/$dependencies/; print $_; } diff --git a/docs/samples/generic_plot.kibot.yaml b/docs/samples/generic_plot.kibot.yaml index 72883e09..7d0b70b8 100644 --- a/docs/samples/generic_plot.kibot.yaml +++ b/docs/samples/generic_plot.kibot.yaml @@ -714,7 +714,7 @@ outputs: dark_mode: false # [string|list(string)='_none'] Name of the filter to mark components as not fitted. # A short-cut to use for simple cases where a variant is an overkill. - # Avoid using it in conjunction with with IBoM native filtering options + # Avoid using it in conjunction with IBoM native filtering options dnf_filter: '_none' # [string=''] Name of the extra field that indicates do not populate status. # Components with this field not empty will be blacklisted. @@ -772,7 +772,7 @@ outputs: # [string='C,R,L,D,U,Y,X,F,SW,A,~,HS,CNN,J,P,NT,MH'] Default sort order for components. Must contain '~' once sort_order: 'C,R,L,D,U,Y,X,F,SW,A,~,HS,CNN,J,P,NT,MH' # [string=''] Board variant to apply. - # Avoid using it in conjunction with with IBoM native filtering options + # Avoid using it in conjunction with IBoM native filtering options variant: '' # [string=''] Name of the extra field that stores board variant for component. # IBoM option, avoid using in conjunction with KiBot variants/filters diff --git a/kibot/__init__.py b/kibot/__init__.py index 94b1ae1b..ec883564 100644 --- a/kibot/__init__.py +++ b/kibot/__init__.py @@ -1 +1,9 @@ -# This file indicates this directory is a Python package +__author__ = 'Salvador E. Tropea, John Beard' +__copyright__ = 'Copyright 2018-2022, Salvador E. Tropea/INTI/John Beard' +__credits__ = ['Salvador E. Tropea', 'John Beard'] +__license__ = 'GPL v3+' +__email__ = 'stropea@inti.gob.ar' +__url__ = 'https://github.com/INTI-CMNB/KiBot/' +__status__ = 'stable' +__version__ = '1.0.0' +__pypi_deps__ = ['kiauto', 'pyyaml', 'xlsxwriter', 'colorama', 'requests', 'qrcodegen'] diff --git a/kibot/__main__.py b/kibot/__main__.py index 2fada169..4f0554de 100644 --- a/kibot/__main__.py +++ b/kibot/__main__.py @@ -15,6 +15,7 @@ Usage: kibot [-v...] [--start PATH] [-d OUT_DIR] [--dry] [-t, --type TYPE]... --quick-start kibot [-v...] --help-filters + kibot [-v...] [--markdown] --help-dependencies kibot [-v...] --help-global-options kibot [-v...] --help-list-outputs kibot [-v...] --help-output=HELP_OUTPUT @@ -52,6 +53,7 @@ Quick start options: Help options: -h, --help Show this help message and exit + --help-dependencies List dependencies in human readable format --help-filters List supported filters and details --help-global-options List supported global variables --help-list-outputs List supported outputs @@ -60,16 +62,6 @@ Help options: --help-preflights List supported preflights and details """ -__author__ = 'Salvador E. Tropea, John Beard' -__copyright__ = 'Copyright 2018-2022, Salvador E. Tropea/INTI/John Beard' -__credits__ = ['Salvador E. Tropea', 'John Beard'] -__license__ = 'GPL v3+' -__email__ = 'stropea@inti.gob.ar' -__url__ = 'https://github.com/INTI-CMNB/KiBot/' -__status__ = 'stable' -__version__ = '1.0.0' - - import os import sys from sys import path as sys_path @@ -77,7 +69,7 @@ import re import gzip import locale from glob import glob - +from . import __version__, __copyright__, __license__ # Import log first to set the domain from . import log log.set_domain('kibot') @@ -100,7 +92,7 @@ from .gs import (GS) from .misc import (EXIT_BAD_ARGS, W_VARCFG, NO_PCBNEW_MODULE, W_NOKIVER, hide_stderr) from .pre_base import (BasePreFlight) from .config_reader import (CfgYamlReader, print_outputs_help, print_output_help, print_preflights_help, create_example, - print_filters_help, print_global_options_help) + print_filters_help, print_global_options_help, print_dependencies) from .kiplot import (generate_outputs, load_actions, config_output, generate_makefile, generate_examples, solve_schematic, solve_board_file, solve_project_file, check_board_file) GS.kibot_version = __version__ @@ -274,6 +266,9 @@ def main(): if args.help_global_options: print_global_options_help() sys.exit(0) + if args.help_dependencies: + print_dependencies(args.markdown) + sys.exit(0) if args.example: check_board_file(args.board_file) if args.copy_options and not args.board_file: diff --git a/kibot/bom/xlsx_writer.py b/kibot/bom/xlsx_writer.py index d7a3906a..75243d9e 100644 --- a/kibot/bom/xlsx_writer.py +++ b/kibot/bom/xlsx_writer.py @@ -21,7 +21,7 @@ from .. import log from ..misc import W_NOKICOST, W_UNKDIST, KICOST_ERROR, W_BADFIELD from ..error import trace_dump from ..gs import GS -from ..__main__ import __version__ +from .. import __version__ try: from xlsxwriter import Workbook XLSX_SUPPORT = True @@ -549,7 +549,7 @@ def dis_enable_apis(api_options, cfg): def _create_kicost_sheet(workbook, groups, image_data, fmt_title, fmt_info, fmt_subtitle, fmt_head, fmt_cols, cfg): if not KICOST_SUPPORT: - logger.warning(W_NOKICOST, 'KiCost sheet requested but failed to load KiCost support') + logger.warning(W_NOKICOST+'KiCost sheet requested but failed to load KiCost support') return if cfg.debug_level > 2: logger.debug("Groups exported to KiCost:") diff --git a/kibot/config_reader.py b/kibot/config_reader.py index 6924ca44..ef81a01b 100644 --- a/kibot/config_reader.py +++ b/kibot/config_reader.py @@ -17,13 +17,18 @@ from .error import (KiPlotConfigurationError, config_error) from .misc import (NO_YAML_MODULE, EXIT_BAD_ARGS, EXAMPLE_CFG, WONT_OVERWRITE, W_NOOUTPUTS, W_UNKOUT, W_NOFILTERS, W_NOVARIANTS, W_NOGLOBALS) from .gs import GS -from .registrable import RegOutput, RegVariant, RegFilter +from .registrable import RegOutput, RegVariant, RegFilter, RegDependency from .pre_base import BasePreFlight - +from . import __pypi_deps__ # Logger from . import log logger = log.get_logger() +LOCAL_OPTIONAL = 1 +GLOBAL_OPTIONAL = LOCAL_OPTIONAL*100 +LOCAL_MANDATORY = GLOBAL_OPTIONAL*100 +GLOBAL_MANDATORY = LOCAL_MANDATORY*100 + try: import yaml @@ -683,3 +688,69 @@ def create_example(pcb_file, out_dir, copy_options, copy_expand): f.write(" description: '{}'\n".format(layer.description)) else: f.write(' layers: {}\n'.format(layers)) + + +def global2human(name): + return '`'+name+'`' if name != 'global' else 'general use' + + +def print_dependencies(markdown=True): + # Compute the importance of each dependency + for dep in RegDependency.get_registered().values(): + importance = 0 + for r in dep.roles: + local = r.output != 'global' + if r.mandatory: + importance += LOCAL_MANDATORY if local else GLOBAL_MANDATORY + else: + importance += LOCAL_OPTIONAL if local else GLOBAL_OPTIONAL + dep.importance = importance + # Now print them sorted by importance (and by name as a second criteria) + for name, dep in sorted(sorted(RegDependency.get_registered().items(), key=lambda x: x[0].lower()), # noqa C414 + key=lambda x: x[1].importance, reverse=True): + dtype = 'python module' if dep.is_python else 'tool' + is_pypi_dep = ' (PyPi dependency)' if dep.pypi_name.lower() in __pypi_deps__ else '' + deb = '' + if markdown: + if dep.is_python: + url = 'https://pypi.org/project/{}/'.format(name) + else: + url = dep.url + name = '[**{}**]({})'.format(name, url) + if dep.in_debian: + deb = ' [Debian](https://packages.debian.org/bullseye/{})'.format(dep.deb_package) + needed = [] + optional = [] + version = None + for r in dep.roles: + if r.mandatory: + needed.append(global2human(r.output)) + else: + optional.append(r) + if r.version and (version is None or r.version > version): + version = r.version + ver = '' + if version: + ver = 'v'+'.'.join(map(str, version))+' ' + print("{} {}({}){}{}".format(name, ver, dtype, is_pypi_dep, deb)) + if needed: + if len(needed) == 1: + if needed[0] == 'general use': + print('- Mandatory') + else: + print('- Mandatory for '+needed[0]) + else: + print('- Mandatory for: '+', '.join(sorted(needed))) + if optional: + if len(optional) == 1: + o = optional[0] + desc = o.desc[0].lower()+o.desc[1:] + print('- Optional to {} for {}'.format(desc, global2human(o.output))) + else: + print('- Optional to:') + for o in optional: + ver = '' + if o.version: + ver = ' (v'+'.'.join(map(str, o.version))+')' + print(' - {} for {}{}'.format(o.desc, global2human(o.output), ver)) + print() diff --git a/kibot/create_pdf.py b/kibot/create_pdf.py new file mode 100644 index 00000000..39a980ed --- /dev/null +++ b/kibot/create_pdf.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2022 Salvador E. Tropea +# Copyright (c) 2022 Instituto Nacional de Tecnología Industrial +# Copyright (c) 2022 Albin Dennevi (create_pdf_from_pages) +# License: GPL-3.0 +# Project: KiBot (formerly KiPlot) +# Base idea: https://gitlab.com/dennevi/Board2Pdf/ (Released as Public Domain) +from . import PyPDF2 +from .error import KiPlotConfigurationError + + +def create_pdf_from_pages(input_files, output_fn): + output = PyPDF2.PdfFileWriter() + # Collect all pages + open_files = [] + er = None + for filename in input_files: + try: + file = open(filename, 'rb') + open_files.append(file) + pdf_reader = PyPDF2.PdfFileReader(file) + page_obj = pdf_reader.getPage(0) + page_obj.compressContentStreams() + output.addPage(page_obj) + except (IOError, ValueError, EOFError) as e: + er = str(e) + if er: + raise KiPlotConfigurationError('Error reading `{}` ({})'.format(filename, er)) + # Write all pages to a file + pdf_output = None + try: + pdf_output = open(output_fn, 'wb') + output.write(pdf_output) + except (IOError, ValueError, EOFError) as e: + er = str(e) + finally: + if pdf_output: + pdf_output.close() + if er: + raise KiPlotConfigurationError('Error creating `{}` ({})'.format(output_fn, er)) + # Close the files + for f in open_files: + f.close() diff --git a/kibot/misc.py b/kibot/misc.py index 8fd73898..1a75e2e2 100644 --- a/kibot/misc.py +++ b/kibot/misc.py @@ -293,3 +293,63 @@ def hide_stderr(): os.close(devnull) yield os.dup2(newstderr, 2) + + +class ToolDependencyRole(object): + """ Class used to define the role of a tool """ + def __init__(self, desc=None, version=None, output=None): + # Is this tool mandatory + self.mandatory = desc is None + # If not mandatory, for what? + self.desc = desc + # Which version is needed? + self.version = version + # Which output needs it? + self.output = output + + +class ToolDependency(object): + """ Class used to define tools needed for an output """ + def __init__(self, output, name, url=None, url_down=None, is_python=False, deb=None, in_debian=True, extra_deb=None, + roles=None, is_kicad_plugin=False, command=None, pypi_name=None): + # The associated output + self.output = output + # Name of the tool + self.name = name + # Name of the .deb + if deb is None: + if is_python: + self.deb_package = 'python3-'+name.lower() + else: + self.deb_package = name.lower() + else: + self.deb_package = deb + self.is_python = is_python + # If this tool has an official Debian package + self.in_debian = in_debian + # Name at PyPi, can be fake for things that aren't at PyPi + # Is used just to indicate if a dependency will we installed from PyPi + self.pypi_name = pypi_name if pypi_name is not None else name + # Extra Debian packages needed to complement it + self.extra_deb = extra_deb + # URLs + self.url = url + self.url_down = url_down + # Can be installed as a KiCad plug-in? + self.is_kicad_plugin = is_kicad_plugin + # Command we run + self.command = command + # Roles + if roles is None: + roles = [ToolDependencyRole()] + elif not isinstance(roles, list): + roles = [roles] + for r in roles: + r.output = output + self.roles = roles + + +def kiauto_dependency(output, version=None): + role = None if version is None else ToolDependencyRole(version=version) + return ToolDependency(output, 'KiCad Automation tools', URL_EESCHEMA_DO, url_down=URL_EESCHEMA_DO+'/releases', + in_debian=False, pypi_name='kiauto', roles=role) diff --git a/kibot/out_any_pcb_print.py b/kibot/out_any_pcb_print.py index b595202e..a1d6f63b 100644 --- a/kibot/out_any_pcb_print.py +++ b/kibot/out_any_pcb_print.py @@ -9,8 +9,9 @@ from .pre_base import BasePreFlight from .error import KiPlotConfigurationError from .gs import GS from .kiplot import check_script, exec_with_retry, add_extra_options -from .misc import CMD_PCBNEW_PRINT_LAYERS, URL_PCBNEW_PRINT_LAYERS, PDF_PCB_PRINT +from .misc import CMD_PCBNEW_PRINT_LAYERS, URL_PCBNEW_PRINT_LAYERS, PDF_PCB_PRINT, kiauto_dependency from .out_base import VariantOptions +from .registrable import RegDependency from .macros import macros, document, output_class # noqa: F401 from .layer import Layer from . import log @@ -18,6 +19,10 @@ from . import log logger = log.get_logger() +def register_deps(pre): + RegDependency.register(kiauto_dependency(pre+'_pcb_print', (1, 6, 7))) + + class Any_PCB_PrintOptions(VariantOptions): # Mappings to KiCad config values. They should be the same used in drill_marks.py _drill_marks_map = {'none': 0, 'small': 1, 'full': 2} diff --git a/kibot/out_any_sch_print.py b/kibot/out_any_sch_print.py index 02697dfb..97822d26 100644 --- a/kibot/out_any_sch_print.py +++ b/kibot/out_any_sch_print.py @@ -8,15 +8,20 @@ from tempfile import mkdtemp from shutil import rmtree, copy2 from .gs import GS from .kiplot import check_eeschema_do, exec_with_retry, add_extra_options -from .misc import CMD_EESCHEMA_DO +from .misc import CMD_EESCHEMA_DO, kiauto_dependency from .out_base import VariantOptions from .kicad.config import KiConf +from .registrable import RegDependency from .macros import macros, document, output_class # noqa: F401 from . import log logger = log.get_logger() +def register_deps(pre): + RegDependency.register(kiauto_dependency(pre+'_sch_print')) + + def copy_project(sch_dir): """ Copy the project file to the temporal dir """ ext = GS.pro_ext diff --git a/kibot/out_bom.py b/kibot/out_bom.py index 68bfd3c3..6eaaa399 100644 --- a/kibot/out_bom.py +++ b/kibot/out_bom.py @@ -11,9 +11,9 @@ import os import re from copy import deepcopy from .gs import GS -from .misc import W_BADFIELD, W_NEEDSPCB, DISTRIBUTORS +from .misc import W_BADFIELD, W_NEEDSPCB, DISTRIBUTORS, ToolDependency, ToolDependencyRole, URL_KICOST from .optionable import Optionable, BaseOptions -from .registrable import RegOutput +from .registrable import RegOutput, RegDependency from .error import KiPlotConfigurationError from .kiplot import get_board_comps_data, load_any_sch from .bom.columnlist import ColumnList, BoMError @@ -37,6 +37,10 @@ DEFAULT_ALIASES = [['r', 'r_small', 'res', 'resistor'], ['zener', 'zenersmall'], ['d', 'diode', 'd_small'], ] +RegDependency.register(ToolDependency('bom', 'KiCost', URL_KICOST, url_down=URL_KICOST+'/releases', in_debian=False, + roles=ToolDependencyRole(desc='Find components costs and specs', version=(1, 1, 8)))) +RegDependency.register(ToolDependency('bom', 'xlsxwriter', is_python=True, + roles=ToolDependencyRole(desc='Create XLSX files'))) class BoMJoinField(Optionable): diff --git a/kibot/out_compress.py b/kibot/out_compress.py index fee22485..98a01674 100644 --- a/kibot/out_compress.py +++ b/kibot/out_compress.py @@ -14,13 +14,16 @@ from tarfile import open as tar_open from collections import OrderedDict from .gs import GS from .kiplot import config_output, get_output_dir, run_output -from .misc import MISSING_TOOL, WRONG_INSTALL, W_EMPTYZIP, WRONG_ARGUMENTS, INTERNAL_ERROR +from .misc import MISSING_TOOL, WRONG_INSTALL, W_EMPTYZIP, WRONG_ARGUMENTS, INTERNAL_ERROR, ToolDependency, ToolDependencyRole from .optionable import Optionable, BaseOptions -from .registrable import RegOutput +from .registrable import RegOutput, RegDependency from .macros import macros, document, output_class # noqa: F401 from . import log logger = log.get_logger() +RegDependency.register(ToolDependency('compress', 'RAR', 'https://www.rarlab.com/', + url_down='https://www.rarlab.com/download.htm', + roles=ToolDependencyRole(desc='Compress in RAR format'))) class FilesList(Optionable): diff --git a/kibot/out_gencad.py b/kibot/out_gencad.py index da9a0126..1e70124c 100644 --- a/kibot/out_gencad.py +++ b/kibot/out_gencad.py @@ -6,12 +6,14 @@ import os from .gs import GS from .optionable import BaseOptions -from .misc import CMD_PCBNEW_GENCAD, URL_PCBNEW_GENCAD, FAILED_EXECUTE +from .misc import CMD_PCBNEW_GENCAD, URL_PCBNEW_GENCAD, FAILED_EXECUTE, kiauto_dependency from .kiplot import check_script, exec_with_retry, add_extra_options +from .registrable import RegDependency from .macros import macros, document, output_class # noqa: F401 from . import log logger = log.get_logger() +RegDependency.register(kiauto_dependency('gencad', (1, 6, 5))) class GenCADOptions(BaseOptions): diff --git a/kibot/out_ibom.py b/kibot/out_ibom.py index 5e82b80c..dded5c5e 100644 --- a/kibot/out_ibom.py +++ b/kibot/out_ibom.py @@ -5,15 +5,19 @@ # Project: KiBot (formerly KiPlot) import os from subprocess import (check_output, STDOUT, CalledProcessError) -from .misc import (CMD_IBOM, URL_IBOM, BOM_ERROR, W_EXTNAME, W_NONETLIST) +from .misc import (CMD_IBOM, URL_IBOM, BOM_ERROR, W_EXTNAME, ToolDependency, ToolDependencyRole, W_NONETLIST) from .gs import (GS) from .kiplot import check_script, search_as_plugin from .out_base import VariantOptions +from .registrable import RegDependency from .macros import macros, document, output_class # noqa: F401 from . import log logger = log.get_logger() -WARNING_MIX = "Avoid using it in conjunction with with IBoM native filtering options" +WARNING_MIX = "Avoid using it in conjunction with IBoM native filtering options" +RegDependency.register(ToolDependency('ibom', 'Interactive HTML BoM', URL_IBOM, url_down=URL_IBOM+'/releases', + is_kicad_plugin=True, command=CMD_IBOM, in_debian=False, + roles=ToolDependencyRole(version=(2, 4, 1, 3)))) def check_tool(): diff --git a/kibot/out_kibom.py b/kibot/out_kibom.py index f43415f9..596e2774 100644 --- a/kibot/out_kibom.py +++ b/kibot/out_kibom.py @@ -1,24 +1,26 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2020-2021 Salvador E. Tropea -# Copyright (c) 2020-2021 Instituto Nacional de Tecnología Industrial +# Copyright (c) 2020-2022 Salvador E. Tropea +# Copyright (c) 2020-2022 Instituto Nacional de Tecnología Industrial # License: GPL-3.0 # Project: KiBot (formerly KiPlot) import os from re import search from tempfile import NamedTemporaryFile from subprocess import (check_output, STDOUT, CalledProcessError) -from .misc import (CMD_KIBOM, URL_KIBOM, BOM_ERROR, W_EXTNAME) +from .misc import (CMD_KIBOM, URL_KIBOM, BOM_ERROR, ToolDependency, ToolDependencyRole, W_EXTNAME) from .kiplot import (check_script) from .gs import (GS) from .optionable import Optionable, BaseOptions from .error import KiPlotConfigurationError from .bom.columnlist import ColumnList +from .registrable import RegDependency from .macros import macros, document, output_class # noqa: F401 from . import log logger = log.get_logger() - CONFIG_FILENAME = 'config.kibom.ini' +RegDependency.register(ToolDependency('kibom', 'KiBoM', URL_KIBOM, url_down=URL_KIBOM+'/releases', + command=CMD_KIBOM, in_debian=False, roles=ToolDependencyRole(version=(1, 8, 0)))) class KiBoMRegex(Optionable): diff --git a/kibot/out_kicost.py b/kibot/out_kicost.py index 2a69adba..f3c89b85 100644 --- a/kibot/out_kicost.py +++ b/kibot/out_kicost.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2021 Salvador E. Tropea -# Copyright (c) 2021 Instituto Nacional de Tecnología Industrial +# Copyright (c) 2021-2022 Salvador E. Tropea +# Copyright (c) 2021-2022 Instituto Nacional de Tecnología Industrial # License: GPL-3.0 # Project: KiBot (formerly KiPlot) import os @@ -9,7 +9,8 @@ from subprocess import check_output, STDOUT, CalledProcessError from tempfile import mkdtemp from shutil import rmtree from .misc import (CMD_KICOST, URL_KICOST, BOM_ERROR, DISTRIBUTORS, W_UNKDIST, ISO_CURRENCIES, W_UNKCUR, KICOST_SUBMODULE, - W_KICOSTFLD, W_MIXVARIANT) + W_KICOSTFLD, W_MIXVARIANT, ToolDependency, ToolDependencyRole) +from .registrable import RegDependency from .error import KiPlotConfigurationError from .optionable import Optionable from .gs import GS @@ -21,6 +22,8 @@ from . import log logger = log.get_logger() WARNING_MIX = ("Don't use the `kicost_variant` when using internal variants/filters") +RegDependency.register(ToolDependency('kicost', 'KiCost', URL_KICOST, url_down=URL_KICOST+'/releases', in_debian=False, + roles=ToolDependencyRole(version=(1, 1, 7)))) class Aggregate(Optionable): diff --git a/kibot/out_netlist.py b/kibot/out_netlist.py index 6d48695e..b8ecb655 100644 --- a/kibot/out_netlist.py +++ b/kibot/out_netlist.py @@ -6,12 +6,15 @@ import os from .gs import GS from .optionable import BaseOptions -from .misc import CMD_PCBNEW_IPC_NETLIST, URL_PCBNEW_IPC_NETLIST, CMD_EESCHEMA_DO, URL_EESCHEMA_DO, FAILED_EXECUTE +from .misc import (CMD_PCBNEW_IPC_NETLIST, URL_PCBNEW_IPC_NETLIST, CMD_EESCHEMA_DO, URL_EESCHEMA_DO, FAILED_EXECUTE, + kiauto_dependency) from .kiplot import check_script, exec_with_retry, add_extra_options +from .registrable import RegDependency from .macros import macros, document, output_class # noqa: F401 from . import log logger = log.get_logger() +RegDependency.register(kiauto_dependency('netlist', (1, 6, 11))) class NetlistOptions(BaseOptions): diff --git a/kibot/out_pcb_print.py b/kibot/out_pcb_print.py index bd359169..e67f50f2 100644 --- a/kibot/out_pcb_print.py +++ b/kibot/out_pcb_print.py @@ -23,12 +23,13 @@ from .kicad.config import KiConf from .kicad.v5_sch import SchError from .kicad.pcb import PCB from .misc import (CMD_PCBNEW_PRINT_LAYERS, URL_PCBNEW_PRINT_LAYERS, PDF_PCB_PRINT, MISSING_TOOL, W_PDMASKFAIL, - KICAD5_SVG_SCALE, W_MISSTOOL) + KICAD5_SVG_SCALE, W_MISSTOOL, ToolDependency, ToolDependencyRole) from .kiplot import check_script, exec_with_retry, add_extra_options +from .registrable import RegDependency +from .create_pdf import create_pdf_from_pages from .macros import macros, document, output_class # noqa: F401 from .layer import Layer, get_priority -from .__main__ import __version__ -from . import PyPDF2 +from . import __version__ from . import log logger = log.get_logger() @@ -41,6 +42,13 @@ POLY_FILL_STYLE = ("fill:{0}; fill-opacity:1.0; stroke:{0}; stroke-width:1; stro "stroke-linejoin:round;fill-rule:evenodd;") DRAWING_LAYERS = ['Dwgs.User', 'Cmts.User', 'Eco1.User', 'Eco2.User'] EXTRA_LAYERS = ['F.Fab', 'B.Fab', 'F.CrtYd', 'B.CrtYd'] +RegDependency.register(ToolDependency('pcb_print', 'RSVG tools', + 'https://cran.r-project.org/web/packages/rsvg/index.html', deb='librsvg2-bin', + roles=ToolDependencyRole(desc='Create PDF, PNG, EPS and PS formats'))) +RegDependency.register(ToolDependency('pcb_print', 'Ghostscript', 'https://www.ghostscript.com/', + url_down='https://github.com/ArtifexSoftware/ghostpdl-downloads/releases', + roles=ToolDependencyRole(desc='Create PS files'))) +RegDependency.register(ToolDependency('pcb_print', 'lxml', is_python=True)) def _run_command(cmd): @@ -102,40 +110,6 @@ def get_size(svg): return float(view_box[2]), float(view_box[3]) -def create_pdf_from_pages(input_files, output_fn): - output = PyPDF2.PdfFileWriter() - # Collect all pages - open_files = [] - er = None - for filename in input_files: - try: - file = open(filename, 'rb') - open_files.append(file) - pdf_reader = PyPDF2.PdfFileReader(file) - page_obj = pdf_reader.getPage(0) - page_obj.compressContentStreams() - output.addPage(page_obj) - except (IOError, ValueError, EOFError) as e: - er = str(e) - if er: - raise KiPlotConfigurationError('Error reading `{}` ({})'.format(filename, er)) - # Write all pages to a file - pdf_output = None - try: - pdf_output = open(output_fn, 'wb') - output.write(pdf_output) - except (IOError, ValueError, EOFError) as e: - er = str(e) - finally: - if pdf_output: - pdf_output.close() - if er: - raise KiPlotConfigurationError('Error creating `{}` ({})'.format(output_fn, er)) - # Close the files - for f in open_files: - f.close() - - def svg_to_pdf(input_folder, svg_file, pdf_file): # Note: rsvg-convert uses 90 dpi but KiCad (and the docs I found) says SVG pt is 72 dpi cmd = [SVG2PDF, '-d', '72', '-p', '72', '-f', 'pdf', '-o', os.path.join(input_folder, pdf_file), diff --git a/kibot/out_pcbdraw.py b/kibot/out_pcbdraw.py index 9c5a8d5e..234a3a3f 100644 --- a/kibot/out_pcbdraw.py +++ b/kibot/out_pcbdraw.py @@ -4,14 +4,15 @@ # License: GPL-3.0 # Project: KiBot (formerly KiPlot) import os -from tempfile import (NamedTemporaryFile) +from tempfile import NamedTemporaryFile # Here we import the whole module to make monkeypatch work import subprocess import shutil from .misc import (PCBDRAW, PCBDRAW_ERR, URL_PCBDRAW, W_AMBLIST, W_UNRETOOL, W_USESVG2, W_USEIMAGICK, PCB_MAT_COLORS, - PCB_FINISH_COLORS, SOLDER_COLORS, SILK_COLORS) + PCB_FINISH_COLORS, SOLDER_COLORS, SILK_COLORS, ToolDependency, ToolDependencyRole) from .kiplot import check_script -from .gs import (GS) +from .registrable import RegDependency +from .gs import GS from .optionable import Optionable from .out_base import VariantOptions from .macros import macros, document, output_class # noqa: F401 @@ -22,6 +23,13 @@ SVG2PNG = 'rsvg-convert' CONVERT = 'convert' # 0.9.0 implements KiCad 6 support MIN_VERSION = '0.9.0' +RegDependency.register(ToolDependency('pcbdraw', 'RSVG tools', 'https://cran.r-project.org/web/packages/rsvg/index.html', + deb='librsvg2-bin', + roles=ToolDependencyRole(desc='Create PNG and JPG images'))) +RegDependency.register(ToolDependency('pcbdraw', 'ImageMagick', 'https://imagemagick.org/', + roles=ToolDependencyRole(desc='Create JPG images'))) +RegDependency.register(ToolDependency('pcbdraw', 'PcbDraw', URL_PCBDRAW, url_down=URL_PCBDRAW+'/releases', in_debian=False, + roles=ToolDependencyRole(version=(0, 9, 0)))) class PcbDrawStyle(Optionable): diff --git a/kibot/out_pdf_pcb_print.py b/kibot/out_pdf_pcb_print.py index f9dec514..5f7ac160 100644 --- a/kibot/out_pdf_pcb_print.py +++ b/kibot/out_pdf_pcb_print.py @@ -4,13 +4,14 @@ # License: GPL-3.0 # Project: KiBot (formerly KiPlot) from .gs import GS -from .out_any_pcb_print import Any_PCB_PrintOptions +from .out_any_pcb_print import Any_PCB_PrintOptions, register_deps from .error import KiPlotConfigurationError from .macros import macros, document, output_class # noqa: F401 from .layer import Layer from . import log logger = log.get_logger() +register_deps('pdf') class PDF_PCB_PrintOptions(Any_PCB_PrintOptions): diff --git a/kibot/out_pdf_sch_print.py b/kibot/out_pdf_sch_print.py index 93efa20f..4b79337e 100644 --- a/kibot/out_pdf_sch_print.py +++ b/kibot/out_pdf_sch_print.py @@ -4,12 +4,13 @@ # License: GPL-3.0 # Project: KiBot (formerly KiPlot) from .gs import GS -from .out_any_sch_print import Any_SCH_PrintOptions +from .out_any_sch_print import Any_SCH_PrintOptions, register_deps from .misc import PDF_SCH_PRINT from .macros import macros, document, output_class # noqa: F401 from . import log logger = log.get_logger() +register_deps('pdf') class PDF_SCH_PrintOptions(Any_SCH_PrintOptions): diff --git a/kibot/out_pdfunite.py b/kibot/out_pdfunite.py index bb8bfa86..2449c98d 100644 --- a/kibot/out_pdfunite.py +++ b/kibot/out_pdfunite.py @@ -14,8 +14,8 @@ from .kiplot import config_output, get_output_dir, run_output from .misc import MISSING_TOOL, WRONG_INSTALL, WRONG_ARGUMENTS, INTERNAL_ERROR, W_NOTPDF from .optionable import Optionable, BaseOptions from .registrable import RegOutput +from .create_pdf import create_pdf_from_pages from .macros import macros, document, output_class # noqa: F401 -from .out_pcb_print import create_pdf_from_pages from . import log logger = log.get_logger() diff --git a/kibot/out_qr_lib.py b/kibot/out_qr_lib.py index 77baa0fc..96afef75 100644 --- a/kibot/out_qr_lib.py +++ b/kibot/out_qr_lib.py @@ -12,6 +12,8 @@ from .error import KiPlotConfigurationError from .kicad.sexpdata import Symbol, dumps, Sep, load, SExpData, sexp_iter from .kicad.v6_sch import DrawRectangleV6, PointXY, Stroke, Fill, SchematicFieldV6, FontEffects from .kiplot import load_board +from .misc import ToolDependency, ToolDependencyRole +from .registrable import RegDependency from .macros import macros, document, output_class # noqa: F401 from . import log @@ -22,6 +24,7 @@ QR_ECCS = {'low': QrCode.Ecc.LOW, logger = log.get_logger() TO_SEPARATE = {'kicad_pcb', 'general', 'title_block', 'layers', 'setup', 'pcbplotparams', 'net_class', 'module', 'kicad_sch', 'lib_symbols', 'symbol', 'sheet', 'sheet_instances', 'symbol_instances'} +RegDependency.register(ToolDependency('qr_lib', 'qrcodegen', is_python=True, roles=ToolDependencyRole())) def is_symbol(name, sexp): diff --git a/kibot/out_render_3d.py b/kibot/out_render_3d.py index e43739e4..4bb20bf0 100644 --- a/kibot/out_render_3d.py +++ b/kibot/out_render_3d.py @@ -7,14 +7,16 @@ import os from shutil import rmtree from .misc import (CMD_PCBNEW_3D, URL_PCBNEW_3D, RENDER_3D_ERR, PCB_MAT_COLORS, PCB_FINISH_COLORS, SOLDER_COLORS, SILK_COLORS, - KICAD_VERSION_6_0_2, MISSING_TOOL) + KICAD_VERSION_6_0_2, MISSING_TOOL, kiauto_dependency) from .gs import (GS) from .kiplot import check_script, exec_with_retry, add_extra_options from .out_base_3d import Base3DOptions, Base3D +from .registrable import RegDependency from .macros import macros, document, output_class # noqa: F401 from . import log logger = log.get_logger() +RegDependency.register(kiauto_dependency('render_3d', (1, 6, 8))) class Render3DOptions(Base3DOptions): diff --git a/kibot/out_report.py b/kibot/out_report.py index 54a5eb05..65605d91 100644 --- a/kibot/out_report.py +++ b/kibot/out_report.py @@ -11,8 +11,8 @@ from shutil import which from .gs import GS from .misc import (UI_SMD, UI_VIRTUAL, MOD_THROUGH_HOLE, MOD_SMD, MOD_EXCLUDE_FROM_POS_FILES, PANDOC, MISSING_TOOL, - FAILED_EXECUTE, W_WRONGEXT, W_WRONGOAR, W_ECCLASST, W_MISSTOOL) -from .registrable import RegOutput + FAILED_EXECUTE, W_WRONGEXT, W_WRONGOAR, W_ECCLASST, W_MISSTOOL, ToolDependency, ToolDependencyRole) +from .registrable import RegOutput, RegDependency from .out_base import BaseOptions from .error import KiPlotConfigurationError from .kiplot import config_output @@ -23,6 +23,10 @@ logger = log.get_logger() INF = float('inf') PANDOC_INSTALL = ("In CI/CD environments: the `kicad_auto_test` docker image contains it.\n" "In Debian/Ubuntu environments: install `pandoc`, `texlive-latex-base` and `texlive-latex-recommended`") +RegDependency.register(ToolDependency('report', 'Pandoc', 'https://pandoc.org/', + url_down='https://github.com/jgm/pandoc/releases', + extra_deb=['texlive-latex-base', 'texlive-latex-recommended'], + roles=ToolDependencyRole(desc='Create PDF/ODF/DOCX files'))) def do_round(v, dig): diff --git a/kibot/out_step.py b/kibot/out_step.py index ac6f0952..d7c561f1 100644 --- a/kibot/out_step.py +++ b/kibot/out_step.py @@ -9,14 +9,16 @@ import re from subprocess import (check_output, STDOUT, CalledProcessError) from shutil import rmtree from .error import KiPlotConfigurationError -from .misc import KICAD2STEP, KICAD2STEP_ERR, URL_PCBNEW_RUN_DRC +from .misc import KICAD2STEP, KICAD2STEP_ERR, URL_PCBNEW_RUN_DRC, kiauto_dependency from .gs import (GS) from .out_base_3d import Base3DOptions, Base3D from .kiplot import check_script, add_extra_options +from .registrable import RegDependency from .macros import macros, document, output_class # noqa: F401 from . import log logger = log.get_logger() +RegDependency.register(kiauto_dependency('step', (1, 6, 1))) class STEPOptions(Base3DOptions): diff --git a/kibot/out_svg_pcb_print.py b/kibot/out_svg_pcb_print.py index 056bd6ea..464daeae 100644 --- a/kibot/out_svg_pcb_print.py +++ b/kibot/out_svg_pcb_print.py @@ -5,7 +5,7 @@ # Project: KiBot (formerly KiPlot) import os from .gs import GS -from .out_any_pcb_print import Any_PCB_PrintOptions +from .out_any_pcb_print import Any_PCB_PrintOptions, register_deps from .error import KiPlotConfigurationError from .kicad.patch_svg import patch_svg_file from .macros import macros, document, output_class # noqa: F401 @@ -13,6 +13,7 @@ from .layer import Layer from . import log logger = log.get_logger() +register_deps('svg') class SVG_PCB_PrintOptions(Any_PCB_PrintOptions): diff --git a/kibot/out_svg_sch_print.py b/kibot/out_svg_sch_print.py index 47d4075e..2fd82746 100644 --- a/kibot/out_svg_sch_print.py +++ b/kibot/out_svg_sch_print.py @@ -5,12 +5,13 @@ # License: GPL-3.0 # Project: KiBot (formerly KiPlot) from .gs import GS -from .out_any_sch_print import Any_SCH_PrintOptions +from .out_any_sch_print import Any_SCH_PrintOptions, register_deps from .misc import SVG_SCH_PRINT from .macros import macros, document, output_class # noqa: F401 from . import log logger = log.get_logger() +register_deps('svg') class SVG_SCH_PrintOptions(Any_SCH_PrintOptions): diff --git a/kibot/pre_drc.py b/kibot/pre_drc.py index 7f28be86..8e97df99 100644 --- a/kibot/pre_drc.py +++ b/kibot/pre_drc.py @@ -1,19 +1,21 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2020-2021 Salvador E. Tropea -# Copyright (c) 2020-2021 Instituto Nacional de Tecnología Industrial +# Copyright (c) 2020-2022 Salvador E. Tropea +# Copyright (c) 2020-2022 Instituto Nacional de Tecnología Industrial # License: GPL-3.0 # Project: KiBot (formerly KiPlot) import os -from sys import (exit) +from sys import exit from .macros import macros, pre_class # noqa: F401 from .error import (KiPlotConfigurationError) -from .gs import (GS) +from .gs import GS from .optionable import Optionable from .kiplot import check_script, exec_with_retry, load_board, add_extra_options -from .misc import (CMD_PCBNEW_RUN_DRC, URL_PCBNEW_RUN_DRC, DRC_ERROR) -from .log import (get_logger) +from .misc import CMD_PCBNEW_RUN_DRC, URL_PCBNEW_RUN_DRC, DRC_ERROR, kiauto_dependency +from .registrable import RegDependency +from .log import get_logger logger = get_logger(__name__) +RegDependency.register(kiauto_dependency('run_drc')) @pre_class diff --git a/kibot/pre_erc.py b/kibot/pre_erc.py index 961010d3..0bdd66cf 100644 --- a/kibot/pre_erc.py +++ b/kibot/pre_erc.py @@ -1,19 +1,21 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2020-2021 Salvador E. Tropea -# Copyright (c) 2020-2021 Instituto Nacional de Tecnología Industrial +# Copyright (c) 2020-2022 Salvador E. Tropea +# Copyright (c) 2020-2022 Instituto Nacional de Tecnología Industrial # License: GPL-3.0 # Project: KiBot (formerly KiPlot) import os -from sys import (exit) +from sys import exit from .macros import macros, pre_class # noqa: F401 -from .gs import (GS) +from .gs import GS from .optionable import Optionable from .kiplot import check_eeschema_do, exec_with_retry, load_sch, add_extra_options -from .error import (KiPlotConfigurationError) -from .misc import (CMD_EESCHEMA_DO, ERC_ERROR) -from .log import (get_logger) +from .error import KiPlotConfigurationError +from .misc import CMD_EESCHEMA_DO, ERC_ERROR, kiauto_dependency +from .registrable import RegDependency +from .log import get_logger logger = get_logger(__name__) +RegDependency.register(kiauto_dependency('run_erc')) @pre_class diff --git a/kibot/pre_update_xml.py b/kibot/pre_update_xml.py index e8f90ada..a9a922e1 100644 --- a/kibot/pre_update_xml.py +++ b/kibot/pre_update_xml.py @@ -1,18 +1,20 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2020-2021 Salvador E. Tropea -# Copyright (c) 2020-2021 Instituto Nacional de Tecnología Industrial +# Copyright (c) 2020-2022 Salvador E. Tropea +# Copyright (c) 2020-2022 Instituto Nacional de Tecnología Industrial # License: GPL-3.0 # Project: KiBot (formerly KiPlot) import os -from sys import (exit) +from sys import exit from .macros import macros, pre_class # noqa: F401 -from .error import (KiPlotConfigurationError) -from .gs import (GS) +from .error import KiPlotConfigurationError +from .gs import GS from .kiplot import check_eeschema_do, exec_with_retry, add_extra_options -from .misc import (CMD_EESCHEMA_DO, BOM_ERROR) -from .log import (get_logger) +from .misc import CMD_EESCHEMA_DO, BOM_ERROR, kiauto_dependency +from .registrable import RegDependency +from .log import get_logger logger = get_logger(__name__) +RegDependency.register(kiauto_dependency('update_xml')) @pre_class diff --git a/kibot/registrable.py b/kibot/registrable.py index f54a4a50..f61a148f 100644 --- a/kibot/registrable.py +++ b/kibot/registrable.py @@ -6,6 +6,7 @@ from collections import OrderedDict from .optionable import Optionable from .error import KiPlotConfigurationError +from .misc import ToolDependency, ToolDependencyRole class Registrable(object): @@ -148,3 +149,29 @@ class RegFilter(Optionable, Registrable): def __init__(self): super().__init__() + + +class RegDependency(Registrable): + """ Used to register output tools dependencies """ + _registered = {} + + def __init__(self): + super().__init__() + + @classmethod + def register(cl, aclass): + name = aclass.name + if name in cl._registered: + # Already registered, add the roles + old_reg = cl._registered[name] + old_reg.roles.extend(aclass.roles) + else: + cl._registered[name] = aclass + + +# Here we register some global dependencies +RegDependency.register(ToolDependency('global', 'colorama', is_python=True, + roles=ToolDependencyRole(desc='get color messages in a portable way'))) +RegDependency.register(ToolDependency('global', 'distutils', is_python=True)) +RegDependency.register(ToolDependency('global', 'requests', is_python=True)) +RegDependency.register(ToolDependency('global', 'PyYAML', is_python=True, deb='python3-yaml')) diff --git a/setup.py b/setup.py index fbffae0f..b4ecc14a 100755 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ #!/usr/bin/python3 from setuptools import setup, find_packages # Package meta-data, mostly from the package -from kibot.__main__ import __author__, __email__, __url__, __doc__, __version__ +from kibot import __author__, __email__, __url__, __doc__, __version__, __pypi_deps__ # Use the README.md as a long description. # Note this is also included in the MANIFEST.in @@ -20,7 +20,7 @@ setup(name='kibot', # Packages are marked using __init__.py packages=find_packages(), scripts=['src/kibot', 'src/kiplot'], - install_requires=['kiauto', 'pyyaml', 'xlsxwriter', 'colorama', 'requests', 'qrcodegen'], + install_requires=__pypi_deps__, include_package_data=True, classifiers=['Development Status :: 5 - Production/Stable', 'Environment :: Console',