1917 lines
58 KiB
Python
Executable File
1917 lines
58 KiB
Python
Executable File
#!/usr/bin/python3
|
|
# -*- coding: utf-8 -*-
|
|
# Copyright (c) 2022 Salvador E. Tropea
|
|
# Copyright (c) 2022 Instituto Nacional de Tecnología Industrial
|
|
# License: GPL-3.0
|
|
# Project: KiBot (formerly KiPlot)
|
|
#
|
|
# This is the installation checker, should help people to detect installation issues and install needed tools
|
|
import argparse
|
|
from contextlib import contextmanager
|
|
import importlib
|
|
import json
|
|
import os
|
|
import platform
|
|
import re
|
|
from shutil import which
|
|
import site
|
|
import subprocess
|
|
import sys
|
|
|
|
deps = '{\
|
|
"Bash": {\
|
|
"arch": "bash",\
|
|
"command": "bash",\
|
|
"comments": [],\
|
|
"deb_package": "bash",\
|
|
"downloader": null,\
|
|
"downloader_str": null,\
|
|
"extra_arch": null,\
|
|
"extra_deb": null,\
|
|
"help_option": "--version",\
|
|
"importance": 3,\
|
|
"in_debian": true,\
|
|
"is_kicad_plugin": false,\
|
|
"is_python": false,\
|
|
"name": "Bash",\
|
|
"no_cmd_line_version": false,\
|
|
"no_cmd_line_version_old": false,\
|
|
"output": "pcb_replace",\
|
|
"plugin_dirs": null,\
|
|
"pypi_name": "Bash",\
|
|
"role": [\
|
|
{\
|
|
"desc": "Run external commands to create replacement text",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "pcb_replace",\
|
|
"version": null\
|
|
},\
|
|
{\
|
|
"desc": "Run external commands to create replacement text",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "sch_replace",\
|
|
"version": null\
|
|
},\
|
|
{\
|
|
"desc": "Run external commands to create replacement text",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "set_text_variables",\
|
|
"version": null\
|
|
}\
|
|
],\
|
|
"tests": [],\
|
|
"url": "https://www.gnu.org/software/bash/",\
|
|
"url_down": null\
|
|
},\
|
|
"Blender": {\
|
|
"arch": "blender",\
|
|
"command": "blender",\
|
|
"comments": [],\
|
|
"deb_package": "blender",\
|
|
"downloader": null,\
|
|
"downloader_str": null,\
|
|
"extra_arch": null,\
|
|
"extra_deb": null,\
|
|
"help_option": "--version",\
|
|
"importance": 10000,\
|
|
"in_debian": true,\
|
|
"is_kicad_plugin": false,\
|
|
"is_python": false,\
|
|
"name": "Blender",\
|
|
"no_cmd_line_version": false,\
|
|
"no_cmd_line_version_old": false,\
|
|
"output": "blender_export",\
|
|
"plugin_dirs": null,\
|
|
"pypi_name": "Blender",\
|
|
"role": [\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "blender_export",\
|
|
"version": [\
|
|
3,\
|
|
4,\
|
|
0\
|
|
]\
|
|
}\
|
|
],\
|
|
"tests": [],\
|
|
"url": "https://www.blender.org/",\
|
|
"url_down": null\
|
|
},\
|
|
"Colorama": {\
|
|
"arch": "python-colorama",\
|
|
"command": "colorama",\
|
|
"comments": [],\
|
|
"deb_package": "python3-colorama",\
|
|
"downloader": null,\
|
|
"downloader_str": null,\
|
|
"extra_arch": null,\
|
|
"extra_deb": null,\
|
|
"help_option": "--version",\
|
|
"importance": 100,\
|
|
"in_debian": true,\
|
|
"is_kicad_plugin": false,\
|
|
"is_python": true,\
|
|
"module_name": "colorama",\
|
|
"name": "Colorama",\
|
|
"no_cmd_line_version": false,\
|
|
"no_cmd_line_version_old": false,\
|
|
"output": "global",\
|
|
"plugin_dirs": null,\
|
|
"pypi_name": "Colorama",\
|
|
"role": [\
|
|
{\
|
|
"desc": "Get color messages in a portable way",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "global",\
|
|
"version": null\
|
|
}\
|
|
],\
|
|
"tests": [],\
|
|
"url": null,\
|
|
"url_down": null\
|
|
},\
|
|
"Ghostscript": {\
|
|
"arch": "ghostscript",\
|
|
"command": "gs",\
|
|
"comments": [],\
|
|
"deb_package": "ghostscript",\
|
|
"downloader": {},\
|
|
"downloader_str": "gs",\
|
|
"extra_arch": null,\
|
|
"extra_deb": null,\
|
|
"help_option": "--version",\
|
|
"importance": 2,\
|
|
"in_debian": true,\
|
|
"is_kicad_plugin": false,\
|
|
"is_python": false,\
|
|
"name": "Ghostscript",\
|
|
"no_cmd_line_version": false,\
|
|
"no_cmd_line_version_old": false,\
|
|
"output": "navigate_results",\
|
|
"plugin_dirs": null,\
|
|
"pypi_name": "Ghostscript",\
|
|
"role": [\
|
|
{\
|
|
"desc": "Create outputs preview",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "navigate_results",\
|
|
"version": null\
|
|
},\
|
|
{\
|
|
"desc": "Create PNG, PS and EPS formats",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "pcb_print",\
|
|
"version": null\
|
|
}\
|
|
],\
|
|
"tests": [],\
|
|
"url": "https://www.ghostscript.com/",\
|
|
"url_down": "https://github.com/ArtifexSoftware/ghostpdl-downloads/releases"\
|
|
},\
|
|
"Git": {\
|
|
"arch": "git",\
|
|
"command": "git",\
|
|
"comments": [],\
|
|
"deb_package": "git",\
|
|
"downloader": {},\
|
|
"downloader_str": "git",\
|
|
"extra_arch": null,\
|
|
"extra_deb": null,\
|
|
"help_option": "--version",\
|
|
"importance": 6,\
|
|
"in_debian": true,\
|
|
"is_kicad_plugin": false,\
|
|
"is_python": false,\
|
|
"name": "Git",\
|
|
"no_cmd_line_version": false,\
|
|
"no_cmd_line_version_old": false,\
|
|
"output": "diff",\
|
|
"plugin_dirs": null,\
|
|
"pypi_name": "Git",\
|
|
"role": [\
|
|
{\
|
|
"desc": "Compare with files in the repo",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "diff",\
|
|
"version": null\
|
|
},\
|
|
{\
|
|
"desc": "Find commit hash and/or date",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "kikit_present",\
|
|
"version": null\
|
|
},\
|
|
{\
|
|
"desc": "Compare with files in the repo",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "kiri",\
|
|
"version": null\
|
|
},\
|
|
{\
|
|
"desc": "Find commit hash and/or date",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "pcb_replace",\
|
|
"version": null\
|
|
},\
|
|
{\
|
|
"desc": "Find commit hash and/or date",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "sch_replace",\
|
|
"version": null\
|
|
},\
|
|
{\
|
|
"desc": "Find commit hash and/or date",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "set_text_variables",\
|
|
"version": null\
|
|
}\
|
|
],\
|
|
"tests": [],\
|
|
"url": "https://git-scm.com/",\
|
|
"url_down": null\
|
|
},\
|
|
"ImageMagick": {\
|
|
"arch": "imagemagick",\
|
|
"command": "convert",\
|
|
"comments": [],\
|
|
"deb_package": "imagemagick",\
|
|
"downloader": {},\
|
|
"downloader_str": "convert",\
|
|
"extra_arch": [\
|
|
"gsfonts"\
|
|
],\
|
|
"extra_deb": null,\
|
|
"help_option": "--version",\
|
|
"importance": 5,\
|
|
"in_debian": true,\
|
|
"is_kicad_plugin": false,\
|
|
"is_python": false,\
|
|
"name": "ImageMagick",\
|
|
"no_cmd_line_version": false,\
|
|
"no_cmd_line_version_old": false,\
|
|
"output": "blender_export",\
|
|
"plugin_dirs": null,\
|
|
"pypi_name": "ImageMagick",\
|
|
"role": [\
|
|
{\
|
|
"desc": "Automatically crop images",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "blender_export",\
|
|
"version": null\
|
|
},\
|
|
{\
|
|
"desc": "Create outputs preview",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "navigate_results",\
|
|
"version": null\
|
|
},\
|
|
{\
|
|
"desc": "Create monochrome prints and scaled PNG files",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "pcb_print",\
|
|
"version": null\
|
|
},\
|
|
{\
|
|
"desc": "Create JPG and BMP images",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "pcbdraw",\
|
|
"version": null\
|
|
},\
|
|
{\
|
|
"desc": "Automatically crop images",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "render_3d",\
|
|
"version": null\
|
|
}\
|
|
],\
|
|
"tests": [],\
|
|
"url": "https://imagemagick.org/",\
|
|
"url_down": "https://imagemagick.org/script/download.php"\
|
|
},\
|
|
"Interactive HTML BoM": {\
|
|
"arch": null,\
|
|
"command": "generate_interactive_bom.py",\
|
|
"comments": [],\
|
|
"deb_package": "interactive html bom",\
|
|
"downloader": {},\
|
|
"downloader_str": "pytool",\
|
|
"extra_arch": null,\
|
|
"extra_deb": null,\
|
|
"help_option": "--version",\
|
|
"importance": 10000,\
|
|
"in_debian": false,\
|
|
"is_kicad_plugin": true,\
|
|
"is_python": false,\
|
|
"name": "Interactive HTML BoM",\
|
|
"no_cmd_line_version": false,\
|
|
"no_cmd_line_version_old": true,\
|
|
"output": "ibom",\
|
|
"plugin_dirs": [\
|
|
"InteractiveHtmlBom",\
|
|
"InteractiveHtmlBom/InteractiveHtmlBom",\
|
|
"org_openscopeproject_InteractiveHtmlBom",\
|
|
"org_openscopeproject_InteractiveHtmlBom/InteractiveHtmlBom"\
|
|
],\
|
|
"pypi_name": "Interactive HTML BoM",\
|
|
"role": [\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "ibom",\
|
|
"version": [\
|
|
2,\
|
|
7,\
|
|
0\
|
|
]\
|
|
}\
|
|
],\
|
|
"tests": [],\
|
|
"url": "https://github.com/INTI-CMNB/InteractiveHtmlBom",\
|
|
"url_down": "https://github.com/INTI-CMNB/InteractiveHtmlBom/releases"\
|
|
},\
|
|
"KiBoM": {\
|
|
"arch": null,\
|
|
"command": "KiBOM_CLI.py",\
|
|
"comments": [],\
|
|
"deb_package": "kibom",\
|
|
"downloader": {},\
|
|
"downloader_str": "pytool",\
|
|
"extra_arch": null,\
|
|
"extra_deb": null,\
|
|
"help_option": "--version",\
|
|
"importance": 10000,\
|
|
"in_debian": false,\
|
|
"is_kicad_plugin": false,\
|
|
"is_python": false,\
|
|
"name": "KiBoM",\
|
|
"no_cmd_line_version": false,\
|
|
"no_cmd_line_version_old": false,\
|
|
"output": "kibom",\
|
|
"plugin_dirs": null,\
|
|
"pypi_name": "KiBoM",\
|
|
"role": [\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "kibom",\
|
|
"version": [\
|
|
1,\
|
|
8,\
|
|
0\
|
|
]\
|
|
}\
|
|
],\
|
|
"tests": [],\
|
|
"url": "https://github.com/INTI-CMNB/KiBoM",\
|
|
"url_down": "https://github.com/INTI-CMNB/KiBoM/releases"\
|
|
},\
|
|
"KiCad Automation tools": {\
|
|
"arch": null,\
|
|
"command": "pcbnew_do",\
|
|
"comments": [],\
|
|
"deb_package": "kicad automation tools",\
|
|
"downloader": {},\
|
|
"downloader_str": "pytool",\
|
|
"extra_arch": null,\
|
|
"extra_deb": null,\
|
|
"help_option": "--version",\
|
|
"importance": 150004,\
|
|
"in_debian": false,\
|
|
"is_kicad_plugin": false,\
|
|
"is_python": false,\
|
|
"name": "KiCad Automation tools",\
|
|
"no_cmd_line_version": false,\
|
|
"no_cmd_line_version_old": false,\
|
|
"output": "diff",\
|
|
"plugin_dirs": null,\
|
|
"pypi_name": "kiauto",\
|
|
"role": [\
|
|
{\
|
|
"desc": "Compare schematics",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "diff",\
|
|
"version": [\
|
|
2,\
|
|
2,\
|
|
0\
|
|
]\
|
|
},\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "dxf_sch_print",\
|
|
"version": [\
|
|
2,\
|
|
1,\
|
|
1\
|
|
]\
|
|
},\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "gencad",\
|
|
"version": [\
|
|
1,\
|
|
6,\
|
|
5\
|
|
]\
|
|
},\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "hpgl_sch_print",\
|
|
"version": [\
|
|
2,\
|
|
1,\
|
|
1\
|
|
]\
|
|
},\
|
|
{\
|
|
"desc": "Show KiAuto installation information",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "info",\
|
|
"version": [\
|
|
2,\
|
|
0,\
|
|
0\
|
|
]\
|
|
},\
|
|
{\
|
|
"desc": "Compare schematics",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "kiri",\
|
|
"version": [\
|
|
2,\
|
|
2,\
|
|
0\
|
|
]\
|
|
},\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "netlist",\
|
|
"version": [\
|
|
2,\
|
|
0,\
|
|
0\
|
|
]\
|
|
},\
|
|
{\
|
|
"desc": "Print the page frame in GUI mode",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "pcb_print",\
|
|
"version": [\
|
|
1,\
|
|
6,\
|
|
7\
|
|
]\
|
|
},\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "pdf_pcb_print",\
|
|
"version": [\
|
|
1,\
|
|
6,\
|
|
7\
|
|
]\
|
|
},\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "pdf_sch_print",\
|
|
"version": [\
|
|
2,\
|
|
1,\
|
|
1\
|
|
]\
|
|
},\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "ps_sch_print",\
|
|
"version": [\
|
|
2,\
|
|
1,\
|
|
1\
|
|
]\
|
|
},\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "render_3d",\
|
|
"version": [\
|
|
2,\
|
|
0,\
|
|
4\
|
|
]\
|
|
},\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "step",\
|
|
"version": [\
|
|
1,\
|
|
6,\
|
|
1\
|
|
]\
|
|
},\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "svg_pcb_print",\
|
|
"version": [\
|
|
1,\
|
|
6,\
|
|
7\
|
|
]\
|
|
},\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "svg_sch_print",\
|
|
"version": [\
|
|
2,\
|
|
1,\
|
|
1\
|
|
]\
|
|
},\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "vrml",\
|
|
"version": [\
|
|
2,\
|
|
1,\
|
|
0\
|
|
]\
|
|
},\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "run_drc",\
|
|
"version": [\
|
|
2,\
|
|
0,\
|
|
0\
|
|
]\
|
|
},\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "run_erc",\
|
|
"version": [\
|
|
2,\
|
|
2,\
|
|
1\
|
|
]\
|
|
},\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "update_xml",\
|
|
"version": [\
|
|
1,\
|
|
5,\
|
|
4\
|
|
]\
|
|
}\
|
|
],\
|
|
"tests": [],\
|
|
"url": "https://github.com/INTI-CMNB/KiAuto",\
|
|
"url_down": "https://github.com/INTI-CMNB/KiAuto/releases"\
|
|
},\
|
|
"KiCad PCB/SCH Diff": {\
|
|
"arch": null,\
|
|
"command": "kicad-diff.py",\
|
|
"comments": [],\
|
|
"deb_package": "kicad pcb/sch diff",\
|
|
"downloader": {},\
|
|
"downloader_str": "pytool",\
|
|
"extra_arch": null,\
|
|
"extra_deb": null,\
|
|
"help_option": "--version",\
|
|
"importance": 20000,\
|
|
"in_debian": false,\
|
|
"is_kicad_plugin": false,\
|
|
"is_python": false,\
|
|
"name": "KiCad PCB/SCH Diff",\
|
|
"no_cmd_line_version": false,\
|
|
"no_cmd_line_version_old": false,\
|
|
"output": "diff",\
|
|
"plugin_dirs": null,\
|
|
"pypi_name": "kidiff",\
|
|
"role": [\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "diff",\
|
|
"version": [\
|
|
2,\
|
|
5,\
|
|
3\
|
|
]\
|
|
},\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "kiri",\
|
|
"version": [\
|
|
2,\
|
|
5,\
|
|
1\
|
|
]\
|
|
}\
|
|
],\
|
|
"tests": [],\
|
|
"url": "https://github.com/INTI-CMNB/KiDiff",\
|
|
"url_down": "https://github.com/INTI-CMNB/KiDiff/releases"\
|
|
},\
|
|
"KiCost": {\
|
|
"arch": null,\
|
|
"command": "kicost",\
|
|
"comments": [],\
|
|
"deb_package": "kicost",\
|
|
"downloader": {},\
|
|
"downloader_str": "pytool",\
|
|
"extra_arch": null,\
|
|
"extra_deb": null,\
|
|
"help_option": "--version",\
|
|
"importance": 10001,\
|
|
"in_debian": false,\
|
|
"is_kicad_plugin": false,\
|
|
"is_python": false,\
|
|
"name": "KiCost",\
|
|
"no_cmd_line_version": false,\
|
|
"no_cmd_line_version_old": false,\
|
|
"output": "bom",\
|
|
"plugin_dirs": null,\
|
|
"pypi_name": "KiCost",\
|
|
"role": [\
|
|
{\
|
|
"desc": "Find components costs and specs",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "bom",\
|
|
"version": [\
|
|
1,\
|
|
1,\
|
|
8\
|
|
]\
|
|
},\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "kicost",\
|
|
"version": [\
|
|
1,\
|
|
1,\
|
|
7\
|
|
]\
|
|
}\
|
|
],\
|
|
"tests": [],\
|
|
"url": "https://github.com/hildogjr/KiCost",\
|
|
"url_down": "https://github.com/hildogjr/KiCost/releases"\
|
|
},\
|
|
"KiKit": {\
|
|
"arch": null,\
|
|
"command": "kikit",\
|
|
"comments": [\
|
|
"Official 1.3.0 release does not work, use my fork if 1.3.0 is the latest",\
|
|
"You can also try the official 1.4.0 release"\
|
|
],\
|
|
"deb_package": "kikit",\
|
|
"downloader": {},\
|
|
"downloader_str": "pytool",\
|
|
"extra_arch": null,\
|
|
"extra_deb": null,\
|
|
"help_option": "--version",\
|
|
"importance": 30100,\
|
|
"in_debian": false,\
|
|
"is_kicad_plugin": false,\
|
|
"is_python": false,\
|
|
"name": "KiKit",\
|
|
"no_cmd_line_version": false,\
|
|
"no_cmd_line_version_old": false,\
|
|
"output": "global",\
|
|
"plugin_dirs": null,\
|
|
"pypi_name": "KiKit",\
|
|
"role": [\
|
|
{\
|
|
"desc": "Separate multiboard projects",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "global",\
|
|
"version": [\
|
|
1,\
|
|
3,\
|
|
0,\
|
|
4\
|
|
]\
|
|
},\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "panelize",\
|
|
"version": [\
|
|
1,\
|
|
3,\
|
|
0,\
|
|
4\
|
|
]\
|
|
},\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "stencil_3d",\
|
|
"version": [\
|
|
1,\
|
|
3,\
|
|
0,\
|
|
4\
|
|
]\
|
|
},\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "stencil_for_jig",\
|
|
"version": [\
|
|
1,\
|
|
3,\
|
|
0,\
|
|
4\
|
|
]\
|
|
}\
|
|
],\
|
|
"tests": [],\
|
|
"url": "https://github.com/INTI-CMNB/KiKit",\
|
|
"url_down": "https://github.com/INTI-CMNB/KiKit/releases"\
|
|
},\
|
|
"LXML": {\
|
|
"arch": "python-lxml",\
|
|
"command": "lxml",\
|
|
"comments": [],\
|
|
"deb_package": "python3-lxml",\
|
|
"downloader": {},\
|
|
"downloader_str": "python",\
|
|
"extra_arch": null,\
|
|
"extra_deb": null,\
|
|
"help_option": "--version",\
|
|
"importance": 20000,\
|
|
"in_debian": true,\
|
|
"is_kicad_plugin": false,\
|
|
"is_python": true,\
|
|
"module_name": "lxml",\
|
|
"name": "LXML",\
|
|
"no_cmd_line_version": false,\
|
|
"no_cmd_line_version_old": false,\
|
|
"output": "pcb_print",\
|
|
"plugin_dirs": null,\
|
|
"pypi_name": "LXML",\
|
|
"role": [\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "pcb_print",\
|
|
"version": null\
|
|
},\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "pcbdraw",\
|
|
"version": null\
|
|
}\
|
|
],\
|
|
"tests": [],\
|
|
"url": null,\
|
|
"url_down": null\
|
|
},\
|
|
"Lark": {\
|
|
"arch": "python-lark",\
|
|
"command": "lark",\
|
|
"comments": [],\
|
|
"deb_package": "python3-lark",\
|
|
"downloader": null,\
|
|
"downloader_str": null,\
|
|
"extra_arch": null,\
|
|
"extra_deb": null,\
|
|
"help_option": "--version",\
|
|
"importance": 1000000,\
|
|
"in_debian": true,\
|
|
"is_kicad_plugin": false,\
|
|
"is_python": true,\
|
|
"module_name": "lark",\
|
|
"name": "Lark",\
|
|
"no_cmd_line_version": false,\
|
|
"no_cmd_line_version_old": false,\
|
|
"output": "global",\
|
|
"plugin_dirs": null,\
|
|
"pypi_name": "Lark",\
|
|
"role": [\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "global",\
|
|
"version": null\
|
|
}\
|
|
],\
|
|
"tests": [],\
|
|
"url": null,\
|
|
"url_down": null\
|
|
},\
|
|
"OpenSCAD": {\
|
|
"arch": "openscad",\
|
|
"command": "openscad",\
|
|
"comments": [],\
|
|
"deb_package": "openscad",\
|
|
"downloader": null,\
|
|
"downloader_str": null,\
|
|
"extra_arch": null,\
|
|
"extra_deb": null,\
|
|
"help_option": "--version",\
|
|
"importance": 20000,\
|
|
"in_debian": true,\
|
|
"is_kicad_plugin": false,\
|
|
"is_python": false,\
|
|
"name": "OpenSCAD",\
|
|
"no_cmd_line_version": false,\
|
|
"no_cmd_line_version_old": false,\
|
|
"output": "stencil_3d",\
|
|
"plugin_dirs": null,\
|
|
"pypi_name": "OpenSCAD",\
|
|
"role": [\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "stencil_3d",\
|
|
"version": null\
|
|
},\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "stencil_for_jig",\
|
|
"version": null\
|
|
}\
|
|
],\
|
|
"tests": [],\
|
|
"url": "https://openscad.org/",\
|
|
"url_down": "https://openscad.org/downloads.html"\
|
|
},\
|
|
"Pandoc": {\
|
|
"arch": "pandoc",\
|
|
"command": "pandoc",\
|
|
"comments": [\
|
|
"In CI/CD environments: the `kicad_auto_test` docker image contains it."\
|
|
],\
|
|
"deb_package": "pandoc",\
|
|
"downloader": null,\
|
|
"downloader_str": null,\
|
|
"extra_arch": [\
|
|
"texlive-core"\
|
|
],\
|
|
"extra_deb": [\
|
|
"texlive",\
|
|
"texlive-latex-base",\
|
|
"texlive-latex-recommended"\
|
|
],\
|
|
"help_option": "--version",\
|
|
"importance": 1,\
|
|
"in_debian": true,\
|
|
"is_kicad_plugin": false,\
|
|
"is_python": false,\
|
|
"name": "Pandoc",\
|
|
"no_cmd_line_version": false,\
|
|
"no_cmd_line_version_old": false,\
|
|
"output": "report",\
|
|
"plugin_dirs": null,\
|
|
"pypi_name": "Pandoc",\
|
|
"role": [\
|
|
{\
|
|
"desc": "Create PDF/ODF/DOCX files",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "report",\
|
|
"version": null\
|
|
}\
|
|
],\
|
|
"tests": [],\
|
|
"url": "https://pandoc.org/",\
|
|
"url_down": "https://github.com/jgm/pandoc/releases"\
|
|
},\
|
|
"PyYAML": {\
|
|
"arch": "python-yaml",\
|
|
"command": "pyyaml",\
|
|
"comments": [],\
|
|
"deb_package": "python3-yaml",\
|
|
"downloader": null,\
|
|
"downloader_str": null,\
|
|
"extra_arch": null,\
|
|
"extra_deb": null,\
|
|
"help_option": "--version",\
|
|
"importance": 1000000,\
|
|
"in_debian": true,\
|
|
"is_kicad_plugin": false,\
|
|
"is_python": true,\
|
|
"module_name": "yaml",\
|
|
"name": "PyYAML",\
|
|
"no_cmd_line_version": false,\
|
|
"no_cmd_line_version_old": false,\
|
|
"output": "global",\
|
|
"plugin_dirs": null,\
|
|
"pypi_name": "PyYAML",\
|
|
"role": [\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "global",\
|
|
"version": null\
|
|
}\
|
|
],\
|
|
"tests": [],\
|
|
"url": null,\
|
|
"url_down": null\
|
|
},\
|
|
"QRCodeGen": {\
|
|
"arch": null,\
|
|
"command": "qrcodegen",\
|
|
"comments": [],\
|
|
"deb_package": "python3-qrcodegen",\
|
|
"downloader": {},\
|
|
"downloader_str": "python",\
|
|
"extra_arch": null,\
|
|
"extra_deb": null,\
|
|
"help_option": "--version",\
|
|
"importance": 10000,\
|
|
"in_debian": true,\
|
|
"is_kicad_plugin": false,\
|
|
"is_python": true,\
|
|
"module_name": "qrcodegen",\
|
|
"name": "QRCodeGen",\
|
|
"no_cmd_line_version": false,\
|
|
"no_cmd_line_version_old": false,\
|
|
"output": "qr_lib",\
|
|
"plugin_dirs": null,\
|
|
"pypi_name": "QRCodeGen",\
|
|
"role": [\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "qr_lib",\
|
|
"version": null\
|
|
}\
|
|
],\
|
|
"tests": [],\
|
|
"url": null,\
|
|
"url_down": null\
|
|
},\
|
|
"RAR": {\
|
|
"arch": "rar(AUR)",\
|
|
"command": "rar",\
|
|
"comments": [],\
|
|
"deb_package": "rar",\
|
|
"downloader": {},\
|
|
"downloader_str": "rar",\
|
|
"extra_arch": null,\
|
|
"extra_deb": null,\
|
|
"help_option": "-?",\
|
|
"importance": 1,\
|
|
"in_debian": true,\
|
|
"is_kicad_plugin": false,\
|
|
"is_python": false,\
|
|
"name": "RAR",\
|
|
"no_cmd_line_version": false,\
|
|
"no_cmd_line_version_old": false,\
|
|
"output": "compress",\
|
|
"plugin_dirs": null,\
|
|
"pypi_name": "RAR",\
|
|
"role": [\
|
|
{\
|
|
"desc": "Compress in RAR format",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "compress",\
|
|
"version": null\
|
|
}\
|
|
],\
|
|
"tests": [],\
|
|
"url": "https://www.rarlab.com/",\
|
|
"url_down": "https://www.rarlab.com/download.htm"\
|
|
},\
|
|
"RSVG tools": {\
|
|
"arch": "librsvg",\
|
|
"command": "rsvg-convert",\
|
|
"comments": [],\
|
|
"deb_package": "librsvg2-bin",\
|
|
"downloader": {},\
|
|
"downloader_str": "rsvg",\
|
|
"extra_arch": null,\
|
|
"extra_deb": null,\
|
|
"help_option": "--version",\
|
|
"importance": 4,\
|
|
"in_debian": true,\
|
|
"is_kicad_plugin": false,\
|
|
"is_python": false,\
|
|
"name": "RSVG tools",\
|
|
"no_cmd_line_version": false,\
|
|
"no_cmd_line_version_old": false,\
|
|
"output": "navigate_results",\
|
|
"plugin_dirs": null,\
|
|
"pypi_name": "RSVG tools",\
|
|
"role": [\
|
|
{\
|
|
"desc": "Create outputs preview",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "navigate_results",\
|
|
"version": null\
|
|
},\
|
|
{\
|
|
"desc": "Create PNG icons",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "navigate_results",\
|
|
"version": null\
|
|
},\
|
|
{\
|
|
"desc": "Create PDF, PNG, PS and EPS formats",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "pcb_print",\
|
|
"version": null\
|
|
},\
|
|
{\
|
|
"desc": "Create PNG, JPG and BMP images",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "pcbdraw",\
|
|
"version": null\
|
|
}\
|
|
],\
|
|
"tests": [\
|
|
{\
|
|
"command": [\
|
|
"convert",\
|
|
"-list",\
|
|
"font"\
|
|
],\
|
|
"error": "Missing Helvetica font, try installing Ghostscript fonts",\
|
|
"search": "Helvetica"\
|
|
}\
|
|
],\
|
|
"url": "https://gitlab.gnome.org/GNOME/librsvg",\
|
|
"url_down": null\
|
|
},\
|
|
"Requests": {\
|
|
"arch": "python-requests",\
|
|
"command": "requests",\
|
|
"comments": [],\
|
|
"deb_package": "python3-requests",\
|
|
"downloader": null,\
|
|
"downloader_str": null,\
|
|
"extra_arch": null,\
|
|
"extra_deb": null,\
|
|
"help_option": "--version",\
|
|
"importance": 1000000,\
|
|
"in_debian": true,\
|
|
"is_kicad_plugin": false,\
|
|
"is_python": true,\
|
|
"module_name": "requests",\
|
|
"name": "Requests",\
|
|
"no_cmd_line_version": false,\
|
|
"no_cmd_line_version_old": false,\
|
|
"output": "global",\
|
|
"plugin_dirs": null,\
|
|
"pypi_name": "Requests",\
|
|
"role": [\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "global",\
|
|
"version": null\
|
|
}\
|
|
],\
|
|
"tests": [],\
|
|
"url": null,\
|
|
"url_down": null\
|
|
},\
|
|
"XLSXWriter": {\
|
|
"arch": "python-xlsxwriter",\
|
|
"command": "xlsxwriter",\
|
|
"comments": [],\
|
|
"deb_package": "python3-xlsxwriter",\
|
|
"downloader": {},\
|
|
"downloader_str": "python",\
|
|
"extra_arch": null,\
|
|
"extra_deb": null,\
|
|
"help_option": "--version",\
|
|
"importance": 1,\
|
|
"in_debian": true,\
|
|
"is_kicad_plugin": false,\
|
|
"is_python": true,\
|
|
"module_name": "xlsxwriter",\
|
|
"name": "XLSXWriter",\
|
|
"no_cmd_line_version": false,\
|
|
"no_cmd_line_version_old": false,\
|
|
"output": "bom",\
|
|
"plugin_dirs": null,\
|
|
"pypi_name": "XLSXWriter",\
|
|
"role": [\
|
|
{\
|
|
"desc": "Create XLSX files",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "bom",\
|
|
"version": [\
|
|
1,\
|
|
1,\
|
|
2\
|
|
]\
|
|
}\
|
|
],\
|
|
"tests": [],\
|
|
"url": null,\
|
|
"url_down": null\
|
|
},\
|
|
"Xvfb": {\
|
|
"arch": "xorg-server-xvfb",\
|
|
"command": "xvfb-run",\
|
|
"comments": [],\
|
|
"deb_package": "xvfb",\
|
|
"downloader": null,\
|
|
"downloader_str": null,\
|
|
"extra_arch": null,\
|
|
"extra_deb": null,\
|
|
"help_option": "--version",\
|
|
"importance": 20000,\
|
|
"in_debian": true,\
|
|
"is_kicad_plugin": false,\
|
|
"is_python": false,\
|
|
"name": "Xvfb",\
|
|
"no_cmd_line_version": true,\
|
|
"no_cmd_line_version_old": false,\
|
|
"output": "stencil_3d",\
|
|
"plugin_dirs": null,\
|
|
"pypi_name": "Xvfb",\
|
|
"role": [\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "stencil_3d",\
|
|
"version": null\
|
|
},\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "stencil_for_jig",\
|
|
"version": null\
|
|
}\
|
|
],\
|
|
"tests": [],\
|
|
"url": "https://www.x.org",\
|
|
"url_down": null\
|
|
},\
|
|
"Xvfbwrapper": {\
|
|
"arch": "python-xvfbwrapper",\
|
|
"command": "xvfbwrapper",\
|
|
"comments": [],\
|
|
"deb_package": "python3-xvfbwrapper",\
|
|
"downloader": {},\
|
|
"downloader_str": "python",\
|
|
"extra_arch": null,\
|
|
"extra_deb": null,\
|
|
"help_option": "--version",\
|
|
"importance": 20000,\
|
|
"in_debian": true,\
|
|
"is_kicad_plugin": false,\
|
|
"is_python": true,\
|
|
"module_name": "xvfbwrapper",\
|
|
"name": "Xvfbwrapper",\
|
|
"no_cmd_line_version": false,\
|
|
"no_cmd_line_version_old": false,\
|
|
"output": "stencil_3d",\
|
|
"plugin_dirs": null,\
|
|
"pypi_name": "Xvfbwrapper",\
|
|
"role": [\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "stencil_3d",\
|
|
"version": null\
|
|
},\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "stencil_for_jig",\
|
|
"version": null\
|
|
}\
|
|
],\
|
|
"tests": [],\
|
|
"url": null,\
|
|
"url_down": null\
|
|
},\
|
|
"markdown2": {\
|
|
"arch": "python-markdown2",\
|
|
"command": "markdown2",\
|
|
"comments": [],\
|
|
"deb_package": "python3-markdown2",\
|
|
"downloader": null,\
|
|
"downloader_str": null,\
|
|
"extra_arch": null,\
|
|
"extra_deb": null,\
|
|
"help_option": "--version",\
|
|
"importance": 10000,\
|
|
"in_debian": true,\
|
|
"is_kicad_plugin": false,\
|
|
"is_python": true,\
|
|
"module_name": "markdown2",\
|
|
"name": "markdown2",\
|
|
"no_cmd_line_version": false,\
|
|
"no_cmd_line_version_old": false,\
|
|
"output": "kikit_present",\
|
|
"plugin_dirs": null,\
|
|
"pypi_name": "markdown2",\
|
|
"role": [\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "kikit_present",\
|
|
"version": null\
|
|
}\
|
|
],\
|
|
"tests": [],\
|
|
"url": null,\
|
|
"url_down": null\
|
|
},\
|
|
"mistune": {\
|
|
"arch": "python-mistune",\
|
|
"command": "mistune",\
|
|
"comments": [],\
|
|
"deb_package": "python3-mistune",\
|
|
"downloader": null,\
|
|
"downloader_str": null,\
|
|
"extra_arch": null,\
|
|
"extra_deb": null,\
|
|
"help_option": "--version",\
|
|
"importance": 10000,\
|
|
"in_debian": true,\
|
|
"is_kicad_plugin": false,\
|
|
"is_python": true,\
|
|
"module_name": "mistune",\
|
|
"name": "mistune",\
|
|
"no_cmd_line_version": false,\
|
|
"no_cmd_line_version_old": false,\
|
|
"output": "populate",\
|
|
"plugin_dirs": null,\
|
|
"pypi_name": "mistune",\
|
|
"role": [\
|
|
{\
|
|
"desc": null,\
|
|
"mandatory": true,\
|
|
"max_version": null,\
|
|
"output": "populate",\
|
|
"version": null\
|
|
}\
|
|
],\
|
|
"tests": [],\
|
|
"url": null,\
|
|
"url_down": null\
|
|
},\
|
|
"numpy": {\
|
|
"arch": "python-numpy",\
|
|
"command": "numpy",\
|
|
"comments": [],\
|
|
"deb_package": "python3-numpy",\
|
|
"downloader": {},\
|
|
"downloader_str": "python",\
|
|
"extra_arch": null,\
|
|
"extra_deb": null,\
|
|
"help_option": "--version",\
|
|
"importance": 1,\
|
|
"in_debian": true,\
|
|
"is_kicad_plugin": false,\
|
|
"is_python": true,\
|
|
"module_name": "numpy",\
|
|
"name": "numpy",\
|
|
"no_cmd_line_version": false,\
|
|
"no_cmd_line_version_old": false,\
|
|
"output": "pcbdraw",\
|
|
"plugin_dirs": null,\
|
|
"pypi_name": "numpy",\
|
|
"role": [\
|
|
{\
|
|
"desc": "Automatically adjust SVG margin",\
|
|
"mandatory": false,\
|
|
"max_version": null,\
|
|
"output": "pcbdraw",\
|
|
"version": null\
|
|
}\
|
|
],\
|
|
"tests": [],\
|
|
"url": null,\
|
|
"url_down": null\
|
|
}\
|
|
}\
|
|
'
|
|
# Dirs to look for plugins
|
|
kicad_plugins_dirs = []
|
|
NOT_AVAIL = 'Not available'
|
|
UNKNOWN = '*UNKNOWN*'
|
|
if sys.stdout.isatty():
|
|
CSI = '\033['
|
|
RED = CSI+str(31)+'m'
|
|
GREEN = CSI+str(32)+'m'
|
|
YELLOW = CSI+str(33)+'m'
|
|
YELLOW2 = CSI+str(93)+'m'
|
|
RESET = CSI+str(39)+'m'
|
|
BRIGHT = CSI+";1;4"+'m'
|
|
NORMAL = CSI+'0'+'m'
|
|
else:
|
|
RED = GREEN = YELLOW = YELLOW2 = RESET = BRIGHT = NORMAL = ''
|
|
last_ok = False
|
|
last_cmd = None
|
|
tests_ok = True
|
|
tests_msg = ''
|
|
is_x86 = is_64 = is_linux = False
|
|
ver_re = re.compile(r'(\d+)\.(\d+)(?:\.(\d+))?(?:[\.-](\d+))?')
|
|
|
|
|
|
def check_tool_binary_python(name):
|
|
base = os.path.join(site.USER_BASE, 'bin')
|
|
full_name = os.path.join(base, name)
|
|
if not os.path.isfile(full_name) or not os.access(full_name, os.X_OK):
|
|
return None
|
|
return full_name
|
|
|
|
|
|
def check_tool_binary_local(name):
|
|
home = os.environ.get('HOME') or os.environ.get('username')
|
|
if home is None:
|
|
return None
|
|
home_bin = os.path.join(home, '.local', 'share', 'kibot', 'bin')
|
|
full_name = os.path.join(home_bin, name)
|
|
if not os.path.isfile(full_name) or not os.access(full_name, os.X_OK):
|
|
return None
|
|
return full_name
|
|
|
|
|
|
def look_for_command(command):
|
|
cmd_full = which(command)
|
|
if not cmd_full:
|
|
cmd_full = check_tool_binary_python(command)
|
|
if not cmd_full:
|
|
cmd_full = check_tool_binary_local(command)
|
|
return cmd_full
|
|
|
|
|
|
def run_command(cmd, only_first_line=False, pre_ver_text=None, no_err_2=False):
|
|
global last_ok
|
|
global last_cmd
|
|
cmd_full = look_for_command(cmd[0])
|
|
if not cmd_full:
|
|
last_ok = False
|
|
return NOT_AVAIL
|
|
cmd[0] = cmd_full
|
|
last_cmd = None
|
|
try:
|
|
res_run = subprocess.run(cmd, check=True, capture_output=True)
|
|
last_cmd = cmd[0]
|
|
except FileNotFoundError as e:
|
|
last_ok = False
|
|
return NOT_AVAIL
|
|
except subprocess.CalledProcessError as e:
|
|
if e.returncode != 2 or not no_err_2:
|
|
print('Failed to run %s, error %d' % (cmd[0], e.returncode))
|
|
if e.output:
|
|
print('Output from command: '+e.output.decode())
|
|
last_ok = False
|
|
return UNKNOWN
|
|
res = res_run.stdout.decode().strip()
|
|
if len(res) == 0:
|
|
res = res_run.stderr.decode().strip()
|
|
if only_first_line:
|
|
res = res.split('\n')[0]
|
|
pre_vers = (cmd[0]+' version ', cmd[0]+' ', pre_ver_text)
|
|
for pre_ver in pre_vers:
|
|
if pre_ver and res.startswith(pre_ver):
|
|
res = res[len(pre_ver):]
|
|
last_ok = True
|
|
return res
|
|
|
|
|
|
def simple_run_command(cmd):
|
|
res = run_command(cmd)
|
|
sev, ver = check_version(res, [{'mandatory': True, 'output': 'global', 'version': None}], no_ver=True)
|
|
return do_color(res, sev, version=ver)
|
|
|
|
|
|
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 which(cmd)
|
|
for dir in kicad_plugins_dirs:
|
|
for name in names:
|
|
fname = os.path.join(dir, name, cmd)
|
|
# print('Trying '+fname)
|
|
if os.path.isfile(fname):
|
|
# print('Using `{}` for `{}` ({})'.format(fname, cmd, name))
|
|
return fname
|
|
return cmd
|
|
|
|
|
|
@contextmanager
|
|
def hide_stderr():
|
|
""" Low level stderr suppression, used to hide KiCad bugs. """
|
|
newstderr = os.dup(2)
|
|
devnull = os.open(os.devnull, os.O_WRONLY)
|
|
os.dup2(devnull, 2)
|
|
os.close(devnull)
|
|
yield
|
|
os.dup2(newstderr, 2)
|
|
|
|
|
|
def do_int(v):
|
|
return int(v) if v is not None else 0
|
|
|
|
|
|
def check_tests(tests):
|
|
global tests_ok
|
|
global tests_msg
|
|
for t in tests:
|
|
cmd = t['command']
|
|
cmd_full = look_for_command(cmd[0])
|
|
if cmd_full is None:
|
|
tests_ok = False
|
|
tests_msg = 'Missing test tool `{}`'.format(cmd[0])
|
|
return True
|
|
cmd[0] = cmd_full
|
|
try:
|
|
cmd_output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
|
|
except FileNotFoundError as e:
|
|
tests_ok = False
|
|
tests_msg = 'Missing test tool `{}`'.format(cmd[0])
|
|
return True
|
|
except subprocess.CalledProcessError as e:
|
|
tests_ok = False
|
|
tests_msg = 'Failed to run %s, error %d' % (cmd[0], e.returncode)
|
|
if e.output:
|
|
tests_msg += '\nOutput from command: '+e.output.decode()
|
|
return True
|
|
res = cmd_output.decode().strip()
|
|
if not re.search(t['search'], res):
|
|
tests_ok = False
|
|
tests_msg = t['error']
|
|
return True
|
|
return False
|
|
|
|
|
|
def check_version(version, roles, no_ver=False, tests=None):
|
|
res = ver_re.search(version)
|
|
if res:
|
|
ver = list(map(do_int, res.groups()))
|
|
else:
|
|
ver = [0, 0, 0]
|
|
not_avail = version == NOT_AVAIL or version == UNKNOWN
|
|
global tests_ok
|
|
tests_ok = True
|
|
if tests and res and not not_avail:
|
|
not_avail = check_tests(tests)
|
|
severity = 0
|
|
for r in roles:
|
|
mandatory = r['mandatory']
|
|
glb = r['output'] == 'global'
|
|
this_sever = 0
|
|
max_version = r.get('max_version')
|
|
if not_avail or (r['version'] and ver < r['version']) or (max_version and ver >= max_version):
|
|
if mandatory:
|
|
this_sever = 4 if glb else 3
|
|
else:
|
|
this_sever = 2 if glb else 1
|
|
severity = max(severity, this_sever)
|
|
r['sev'] = this_sever
|
|
return severity, ver
|
|
|
|
|
|
def sev2color(severity):
|
|
if severity == 4:
|
|
return RED
|
|
elif severity == 3:
|
|
return YELLOW2
|
|
elif severity:
|
|
return YELLOW
|
|
else:
|
|
return GREEN
|
|
|
|
|
|
def do_color(msg, severity, version=None):
|
|
if version is not None and version != [0, 0, 0]:
|
|
if len(version) == 4 and version[3] == 0:
|
|
version = version[:-1]
|
|
ver_str = '.'.join(map(str, version))
|
|
if ver_str != msg:
|
|
msg = ver_str+' ('+msg+')'
|
|
return sev2color(severity)+msg+RESET
|
|
|
|
|
|
def error(msg):
|
|
print(sev2color(4)+'**> '+msg+RESET)
|
|
|
|
|
|
def do_bright(msg):
|
|
return BRIGHT+msg+NORMAL
|
|
|
|
|
|
def global2human(name):
|
|
return '`'+name+'`' if name != 'global' else 'general use'
|
|
|
|
|
|
def show_roles(roles):
|
|
needed = []
|
|
optional = []
|
|
for r in roles:
|
|
if r['mandatory']:
|
|
needed.append(r)
|
|
else:
|
|
optional.append(r)
|
|
r['output'] = global2human(r['output'])
|
|
if needed:
|
|
if len(needed) == 1:
|
|
color = sev2color(needed[0]['sev'])
|
|
name = needed[0]['output']
|
|
if name == 'general use':
|
|
print(color+' - Mandatory')
|
|
else:
|
|
print(color+' - Mandatory for '+name)
|
|
else:
|
|
need_s = sorted(needed, key=lambda x: x['output'])
|
|
print(RESET+' - Mandatory for: '+', '.join([sev2color(f['sev'])+f['output']+RESET for f in need_s]))
|
|
if optional:
|
|
if len(optional) == 1:
|
|
o = optional[0]
|
|
desc = o['desc'][0].lower()+o['desc'][1:]
|
|
print(sev2color(o['sev'])+' - Optional to {} for {}'.format(desc, o['output']))
|
|
else:
|
|
print(RESET+' - Optional to:')
|
|
for o in optional:
|
|
ver = ''
|
|
if o['version']:
|
|
ver = ' (v'+'.'.join(map(str, o['version']))+')'
|
|
print(sev2color(o['sev'])+' - {} for {}{}'.format(o['desc'], o['output'], ver))
|
|
|
|
|
|
def python_module(severity, name, deb_package, roles, arch):
|
|
if not severity:
|
|
return
|
|
print(sev2color(severity)+'* Python module `{}` not installed, too old or incompatible'.format(name))
|
|
if debian_support:
|
|
if deb_package is None:
|
|
deb_package = 'python3-'+name
|
|
print(' Install the `{0}` package, i.e.: `sudo apt-get install {0}`'.format(deb_package))
|
|
elif arch_support:
|
|
if arch is None:
|
|
arch = 'python-'+name
|
|
print(' Install the `{0}` package, i.e.: `sudo pacman -S {0}`'.format(arch))
|
|
elif pip_ok:
|
|
print(' run `{} install {}` as root,'.format(pip_command, name))
|
|
print(' or run `{} install --user {}` as a regular user'.format(pip_command, name))
|
|
else:
|
|
print(' Install the Package Installer for Python (pip) and run this script again')
|
|
show_roles(roles)
|
|
print(RESET)
|
|
|
|
|
|
def binary_tool(severity, name, url, url_down, deb_package, deb, extra_deb, roles, downloader, comments, arch, extra_arch):
|
|
if not severity:
|
|
return
|
|
print(sev2color(severity)+'* {} not installed or too old'.format(name))
|
|
if deb and debian_support:
|
|
if deb_package is None:
|
|
deb_package = name.lower()
|
|
print(' Install the `{0}` package, i.e.: `sudo apt-get install {0}`'.format(deb_package))
|
|
if extra_deb:
|
|
print(' You should also install the following packages: '+', '.join(extra_deb))
|
|
elif arch and arch_support:
|
|
if arch.endswith('(AUR)'):
|
|
print(' Install the `{0}` package, i.e.: `sudo yay -S {0}`'.format(arch[:-5]))
|
|
else:
|
|
print(' Install the `{0}` package, i.e.: `sudo pacman -S {0}`'.format(arch))
|
|
if extra_arch:
|
|
print(' You should also install the following packages: '+', '.join(extra_arch))
|
|
else:
|
|
print(' Visit: '+url)
|
|
if url_down:
|
|
print(' Download it from: '+url_down)
|
|
for c in comments:
|
|
print(' '+c)
|
|
if isinstance(downloader, str):
|
|
if downloader == 'pytool' and not pip_ok:
|
|
print(' Please install the Python Installer (pip).')
|
|
else:
|
|
print(' This tool might be automatically downloaded by KiBot.')
|
|
show_roles(roles)
|
|
print(RESET)
|
|
|
|
|
|
parser = argparse.ArgumentParser(description='KiBot installation checker')
|
|
parser.add_argument('--show-paths', '-p', help='Show paths to tools', action='store_true')
|
|
args = parser.parse_args()
|
|
|
|
# Force iBoM to avoid the use of graphical stuff
|
|
os.environ['INTERACTIVE_HTML_BOM_NO_DISPLAY'] = 'True'
|
|
|
|
# ######################################################################################################################
|
|
# Core tools
|
|
# ######################################################################################################################
|
|
|
|
print('KiBot installation checker\n')
|
|
|
|
print(do_bright('Core:'))
|
|
# Operating system
|
|
system = platform.system()
|
|
if system == 'Linux':
|
|
linux_version = simple_run_command(['uname', '-a'])
|
|
print('Linux: '+linux_version)
|
|
if args.show_paths:
|
|
print(' '+str(which('uname')))
|
|
os_ok = True
|
|
is_x86 = 'x86' in linux_version
|
|
is_64 = ('x86_64' in linux_version) or ('amd64' in linux_version)
|
|
is_linux = True
|
|
else:
|
|
print(system)
|
|
os_ok = False
|
|
# Python version
|
|
if sys.version_info >= (3, 6):
|
|
py_ok = True
|
|
sev = 0
|
|
else:
|
|
py_ok = False
|
|
sev = 4
|
|
print('Python: '+do_color(sys.version.replace('\n', ' '), sev))
|
|
if args.show_paths:
|
|
print(' '+os.__file__)
|
|
print(' '+str(which('python3')))
|
|
# KiCad
|
|
home = None
|
|
try:
|
|
import pcbnew
|
|
kicad_ok = True
|
|
# Fill the plug-in locations
|
|
# TODO: Windows? MacOSX?
|
|
kicad_share_path = '/usr/share/kicad'
|
|
if hasattr(pcbnew, 'GetKicadConfigPath'):
|
|
with hide_stderr():
|
|
kicad_conf_path = pcbnew.GetKicadConfigPath()
|
|
elif hasattr(pcbnew, 'GetSettingsManager'):
|
|
kicad_conf_path = pcbnew.GetSettingsManager().GetUserSettingsPath()
|
|
else:
|
|
kicad_conf_path = None
|
|
# /usr/share/kicad/*
|
|
kicad_plugins_dirs.append(os.path.join(kicad_share_path, 'scripting'))
|
|
kicad_plugins_dirs.append(os.path.join(kicad_share_path, 'scripting', 'plugins'))
|
|
kicad_plugins_dirs.append(os.path.join(kicad_share_path, '3rdparty', 'plugins')) # KiCad 6.0 PCM
|
|
# ~/.config/kicad/*
|
|
if kicad_conf_path:
|
|
kicad_plugins_dirs.append(os.path.join(kicad_conf_path, 'scripting'))
|
|
kicad_plugins_dirs.append(os.path.join(kicad_conf_path, 'scripting', 'plugins'))
|
|
# ~/.kicad_plugins and ~/.kicad
|
|
if 'HOME' in os.environ:
|
|
home = os.environ['HOME']
|
|
kicad_plugins_dirs.append(os.path.join(home, '.kicad_plugins'))
|
|
kicad_plugins_dirs.append(os.path.join(home, '.kicad', 'scripting'))
|
|
kicad_plugins_dirs.append(os.path.join(home, '.kicad', 'scripting', 'plugins'))
|
|
except FileNotFoundError:
|
|
kicad_ok = False
|
|
kicad_version = (0, 0, 0)
|
|
if kicad_ok:
|
|
try:
|
|
version = pcbnew.GetBuildVersion()
|
|
# KiCad version
|
|
m = re.search(r'(\d+)\.(\d+)\.(\d+)', version)
|
|
if m is None:
|
|
error("Unable to detect KiCad version, got: `{}`".format(version))
|
|
else:
|
|
kicad_version = (int(m.group(1)), int(m.group(2)), int(m.group(3)))
|
|
if kicad_version[0] >= 6 and home:
|
|
# KiCad 6.0 PCM
|
|
ver_dir = str(kicad_version[0])+'.'+str(kicad_version[1])
|
|
local_share = os.path.join(home, '.local', 'share', 'kicad', ver_dir)
|
|
kicad_plugins_dirs.append(os.path.join(local_share, 'scripting'))
|
|
kicad_plugins_dirs.append(os.path.join(local_share, 'scripting', 'plugins'))
|
|
kicad_plugins_dirs.append(os.path.join(local_share, '3rdparty', 'plugins')) # KiCad 6.0 PCM
|
|
except:
|
|
version = 'Older than 5.1.6'
|
|
else:
|
|
version = NOT_AVAIL
|
|
if kicad_version >= (5, 1, 6) and kicad_version < (7, 99):
|
|
sev = 0
|
|
else:
|
|
sev = 4
|
|
print('KiCad: '+do_color(version, sev))
|
|
if args.show_paths and kicad_ok:
|
|
print(' '+pcbnew.__file__)
|
|
print(' '+str(which('kicad')))
|
|
# KiBot version
|
|
try:
|
|
import kibot.__main__
|
|
version = kibot.__main__.__version__
|
|
kibot_ok = True
|
|
sev = 0
|
|
except:
|
|
version = NOT_AVAIL
|
|
kibot_ok = False
|
|
sev = 4
|
|
print('Kibot: '+do_color(version, sev))
|
|
if args.show_paths and kibot_ok:
|
|
print(' '+kibot.__main__.__file__)
|
|
print(' '+str(which('kibot')))
|
|
if kibot_ok and which('kibot') is None:
|
|
print(sev2color(4)+'* KiBot is installed but not available in your PATH')
|
|
import kibot
|
|
if '/lib/' in kibot.__file__:
|
|
v = re.sub(r'\/lib\/.*', '/bin/kibot', kibot.__file__)
|
|
if os.path.isfile(v):
|
|
print(' Try adding `{}` to your PATH'.format(v[:-5]))
|
|
print(' I.e.: export PATH=$PATH:'+v[:-5])
|
|
sys.exit(1)
|
|
|
|
dependencies = json.loads(deps)
|
|
print(do_bright('\nModules:'))
|
|
for name, d in dependencies.items():
|
|
if not d['is_python']:
|
|
continue
|
|
mod = None
|
|
try:
|
|
mod = importlib.import_module(d['module_name'])
|
|
if hasattr(mod, '__version__'):
|
|
version = mod.__version__
|
|
else:
|
|
version = 'Ok'
|
|
except:
|
|
version = NOT_AVAIL
|
|
sev, ver = check_version(version, d['role'])
|
|
d['sev'] = sev
|
|
version = version.split('\n')[0]
|
|
print(name+': '+do_color(version, sev, version=ver))
|
|
if args.show_paths and mod:
|
|
print(' '+mod.__file__)
|
|
|
|
print(do_bright('\nTools:'))
|
|
for name, d in dependencies.items():
|
|
if d['is_python']:
|
|
continue
|
|
command = d['command']
|
|
if d['is_kicad_plugin']:
|
|
command = search_as_plugin(command, d['plugin_dirs'])
|
|
if d['no_cmd_line_version']:
|
|
version = 'Ok ({})'.format(command) if which(command) is not None else NOT_AVAIL
|
|
else:
|
|
cmd = [command, d['help_option']]
|
|
if d['is_kicad_plugin'] and os.path.isfile(command):
|
|
# There is no point in adding the interpreter if the script isn't there
|
|
# It will just confuse run_command thinking we need to check Python
|
|
cmd.insert(0, 'python3')
|
|
version = run_command(cmd, no_err_2=d['no_cmd_line_version_old'])
|
|
sev, ver = check_version(version, d['role'], tests=d['tests'])
|
|
d['sev'] = sev
|
|
version = version.split('\n')[0]
|
|
pypi_name = d['pypi_name']
|
|
if pypi_name and pypi_name.lower() != name.lower():
|
|
name += ' ({})'.format(pypi_name)
|
|
print(name+': '+do_color(version, sev, version=ver))
|
|
if not tests_ok:
|
|
print('- '+do_color(tests_msg, sev))
|
|
if args.show_paths and last_cmd:
|
|
print(' '+last_cmd)
|
|
|
|
# ######################################################################################################################
|
|
# Recommendations
|
|
# ######################################################################################################################
|
|
|
|
print()
|
|
|
|
debian_support = False
|
|
if which('apt-get'):
|
|
debian_support = True
|
|
arch_support = False
|
|
if which('pacman'):
|
|
arch_support = True
|
|
pip_ok = False
|
|
if which('pip3'):
|
|
pip_ok = True
|
|
pip_command = 'pip3'
|
|
elif which('pip'):
|
|
pip_ok = True
|
|
pip_command = 'pip'
|
|
|
|
if not os_ok:
|
|
print(sev2color(4)+'* KiBot is currently tested under Linux')
|
|
if system == 'Darwin':
|
|
print(' MacOSX should be supported for KiCad 6.x')
|
|
elif system == 'Windows':
|
|
print(' Windows may work with some limitations for KiCad 6.x')
|
|
print(' Consider using a docker image, Windows docker can run Linux images (using virtualization)')
|
|
print(' You can also try WSL (Windows Subsystem for Linux)')
|
|
else:
|
|
print(' What OS are you using? Is KiCad available for it?')
|
|
print(' Please consult: https://github.com/INTI-CMNB/KiBot/issues')
|
|
print(RESET)
|
|
|
|
if not py_ok:
|
|
print(sev2color(4)+'* Install Python 3.6 or newer')
|
|
print(RESET)
|
|
|
|
if not kicad_ok:
|
|
print(sev2color(4)+'* Install KiCad 5.1.6 or newer')
|
|
if debian_support:
|
|
print(' Try `apt-get install kicad` as root')
|
|
else:
|
|
print(' Download it from: https://www.kicad.org/download/')
|
|
print(RESET)
|
|
|
|
if not kibot_ok:
|
|
print(sev2color(4)+'* Install KiBot!')
|
|
if debian_support:
|
|
print(' Follow the instructions here: https://set-soft.github.io/debian/')
|
|
elif pip_ok:
|
|
print(' run `{} install --no-compile kibot` as root,'.format(pip_command))
|
|
print(' or run `{} install --user --no-compile kibot` as a regular user'.format(pip_command))
|
|
else:
|
|
print(' Install the Package Installer for Python (pip) and run this script again')
|
|
print(RESET)
|
|
|
|
for name, d in dependencies.items():
|
|
if d['is_python']:
|
|
python_module(d['sev'], d['pypi_name'], d['deb_package'], d['role'], d['arch'])
|
|
else:
|
|
binary_tool(d['sev'], d['name'], d['url'], d['url_down'], d['deb_package'], d['in_debian'], d['extra_deb'],
|
|
d['role'], d['downloader_str'], d['comments'], d['arch'], d['extra_arch'])
|
|
|
|
if sys.stdout.isatty():
|
|
labels = ('ok', 'optional for an output', 'optional for general use', 'mandatory for an output', 'mandatory for general use')
|
|
text = ', '.join([sev2color(c)+l+RESET for c, l in enumerate(labels)])
|
|
print(do_bright('\nColor reference:')+' '+text)
|
|
|
|
print('\nDid this help? Please consider commenting it on https://github.com/INTI-CMNB/KiBot/discussions/categories/kibot-check')
|
|
|