New output to compute differences between PCBs and SCHs.

Fixes INTI-CMNB/KiAuto#14
This commit is contained in:
Salvador E. Tropea 2022-08-25 13:02:02 -03:00
parent 5134c252db
commit 464b72e8f1
20 changed files with 13795 additions and 3 deletions

View File

@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Added
- New output to compute differences between PCBs and SCHs.(INTI-CMNB/KiAuto#14)
- Try to download missing tools and Python modules.
The user also gets more information when something is missing.
It can be disabled from the command line.

View File

@ -83,6 +83,7 @@ For example, it's common that you might want for each board rev:
* Pick and place files
* PCB 3D model in STEP format
* PCB 3D render in PNG format
* Compare PCB/SCHs
You want to do this in a one-touch way, and make sure everything you need to
do so is securely saved in version control, not on the back of an old
@ -140,6 +141,9 @@ Notes:
[**KiBoM**](https://github.com/INTI-CMNB/KiBoM) v1.8.0 [![Tool](https://raw.githubusercontent.com/INTI-CMNB/KiBot/master/docs/images/llave-inglesa-22x22.png)](https://github.com/INTI-CMNB/KiBoM) ![Auto-download](https://raw.githubusercontent.com/INTI-CMNB/KiBot/master/docs/images/auto_download-22x22.png)
- Mandatory for `kibom`
[**KiCad PCB/SCH Diff**](https://github.com/INTI-CMNB/KiDiff) [![Tool](https://raw.githubusercontent.com/INTI-CMNB/KiBot/master/docs/images/llave-inglesa-22x22.png)](https://github.com/INTI-CMNB/KiDiff) ![Auto-download](https://raw.githubusercontent.com/INTI-CMNB/KiBot/master/docs/images/auto_download-22x22.png)
- Mandatory for `diff`
[**LXML**](https://pypi.org/project/LXML/) [![Python module](https://raw.githubusercontent.com/INTI-CMNB/KiBot/master/docs/images/Python-logo-notext-22x22.png)](https://pypi.org/project/LXML/) [![Debian](https://raw.githubusercontent.com/INTI-CMNB/KiBot/master/docs/images/debian-openlogo-22x22.png)](https://packages.debian.org/bullseye/python3-lxml) ![Auto-download](https://raw.githubusercontent.com/INTI-CMNB/KiBot/master/docs/images/auto_download-22x22.png)
- Mandatory for `pcb_print`
@ -159,6 +163,7 @@ Notes:
[**Git**](https://git-scm.com/) [![Tool](https://raw.githubusercontent.com/INTI-CMNB/KiBot/master/docs/images/llave-inglesa-22x22.png)](https://git-scm.com/) [![Debian](https://raw.githubusercontent.com/INTI-CMNB/KiBot/master/docs/images/debian-openlogo-22x22.png)](https://packages.debian.org/bullseye/git) ![Auto-download](https://raw.githubusercontent.com/INTI-CMNB/KiBot/master/docs/images/auto_download-22x22.png)
- Optional to:
- Compare with files in the repo for `diff`
- Find commit hash and/or date for `pcb_replace`
- Find commit hash and/or date for `sch_replace`
- Find commit hash and/or date for `set_text_variables`
@ -1477,6 +1482,54 @@ Notes:
Internally we use 10 for low priority, 90 for high priority and 50 for most outputs.
- `run_by_default`: [boolean=true] When enabled this output will be created when no specific outputs are requested.
* Diff
* Type: `diff`
* Description: Generates a PDF with the differences between two PCBs or schematics
* Valid keys:
- **`comment`**: [string=''] A comment for documentation purposes.
- **`dir`**: [string='./'] Output directory for the generated files.
If it starts with `+` the rest is concatenated to the default dir.
- **`layers`**: [list(dict)|list(string)|string] [all,selected,copper,technical,user]
List of PCB layers to use. When empty all available layers are used.
Note that if you want to support adding/removing layers you should specify a list here.
* Valid keys:
- `description`: [string=''] A description for the layer, for documentation purposes.
- `layer`: [string=''] Name of the layer. As you see it in KiCad.
- `suffix`: [string=''] Suffix used in file names related to this layer. Derived from the name if not specified.
- **`name`**: [string=''] Used to identify this particular output definition.
- **`options`**: [dict] Options for the `diff` output.
* Valid keys:
- **`output`**: [string='%f-%i%I%v.%x'] Filename for the output (%i=diff, %x=pdf). Affected by global options.
- `cache_dir`: [string=''] Directory to cache the intermediate files. Leave it blank to disable the cache.
- `diff_mode`: [string='red_green'] [red_green,stats] In the `red_green` mode added stuff is green and red when removed.
The `stats` mode is used to meassure the amount of difference. In this mode all
changes are red, but you can abort if the difference is bigger than certain threshold.
- `fuzz`: [number=5] [0,100] Color tolerance (fuzzyness) for the `stats` mode.
- `new`: [string=''] The file you want to compare. Leave it blank for the current PCB/SCH.
- `new_type`: [string='file'] [git,file] How to interpret the `new` name. Use `git` for a git hash, branch, etc.
Use `file` for a file name.
- `old`: [string='HEAD'] Reference file. When using git use `HEAD` to refer to the last commit.
Use `HEAD~` to refer the previous to the last commit.
As `HEAD` is for the whole repo you can use `KIBOT_LAST-n` to make
reference to the changes in the PCB/SCH. The `n` value is how many
changes in the history you want to go back. A 0 is the same as `HEAD`,
a 1 means the last time the PCB/SCH was changed, etc.
- `old_type`: [string='git'] [git,file] How to interpret the `old` name. Use `git` for a git hash, branch, etc.
Use `file` for a file name.
- `pcb`: [boolean=true] Compare the PCB, otherwise compare the schematic.
- `threshold`: [number=0] [0,1000000] Error threshold for the `stats` mode, 0 is no error. When specified a
difference bigger than the indicated value will make the diff fail.
- `category`: [string|list(string)=''] The category for this output. If not specified an internally defined category is used.
Categories looks like file system paths, i.e. PCB/fabrication/gerber.
- `disable_run_by_default`: [string|boolean] Use it to disable the `run_by_default` status of other output.
Useful when this output extends another and you don't want to generate the original.
Use the boolean true value to disable the output you are extending.
- `extends`: [string=''] Copy the `options` section from the indicated output.
- `output_id`: [string=''] Text to use for the %I expansion content. To differentiate variations of this output.
- `priority`: [number=50] [0,100] Priority for this output. High priority outputs are created first.
Internally we use 10 for low priority, 90 for high priority and 50 for most outputs.
- `run_by_default`: [boolean=true] When enabled this output will be created when no specific outputs are requested.
* Datasheets downloader
* Type: `download_datasheets`
* Description: Downloads the datasheets for the project

2
debian/control vendored
View File

@ -12,7 +12,7 @@ Architecture: all
Multi-Arch: foreign
Depends: ${misc:Depends}, ${python3:Depends}, python3-yaml, kicad (>= 5.1.6), python3-wxgtk4.0
Recommends: kibom.inti-cmnb (>= 1.8.0), kicost (>= 1.1.8), interactivehtmlbom.inti-cmnb (>= 2.4.1), pcbdraw (>= 0.9.0), imagemagick, librsvg2-bin, python3-xlsxwriter, rar, ghostscript, python3-lxml
Suggests: pandoc, texlive-latex-base, texlive-latex-recommended, git, poppler-utils
Suggests: pandoc, texlive-latex-base, texlive-latex-recommended, git, poppler-utils, kidiff
Description: KiCad Bot
KiBot is a program which helps you to automate the generation of KiCad
output documents easily, repeatable, and most of all, scriptably.

View File

@ -83,6 +83,7 @@ For example, it's common that you might want for each board rev:
* Pick and place files
* PCB 3D model in STEP format
* PCB 3D render in PNG format
* Compare PCB/SCHs
You want to do this in a one-touch way, and make sure everything you need to
do so is securely saved in version control, not on the back of an old

View File

@ -407,6 +407,43 @@ outputs:
# [string='%f-%i%I%v.%x'] Name for the generated archive (%i=name of the output %x=according to format). Affected by global options
output: '%f-%i%I%v.%x'
# `remove_files` is an alias for `move_files`
# Diff:
- name: 'diff_example'
comment: 'Generates a PDF with the differences between two PCBs or schematics'
type: 'diff'
dir: 'Example/diff_dir'
options:
# [string=''] Directory to cache the intermediate files. Leave it blank to disable the cache
cache_dir: ''
# [string='red_green'] [red_green,stats] In the `red_green` mode added stuff is green and red when removed.
# The `stats` mode is used to meassure the amount of difference. In this mode all
# changes are red, but you can abort if the difference is bigger than certain threshold
diff_mode: 'red_green'
# [number=5] [0,100] Color tolerance (fuzzyness) for the `stats` mode
fuzz: 5
# [string=''] The file you want to compare. Leave it blank for the current PCB/SCH
new: ''
# [string='file'] [git,file] How to interpret the `new` name. Use `git` for a git hash, branch, etc.
# Use `file` for a file name
new_type: 'file'
# [string='HEAD'] Reference file. When using git use `HEAD` to refer to the last commit.
# Use `HEAD~` to refer the previous to the last commit.
# As `HEAD` is for the whole repo you can use `KIBOT_LAST-n` to make
# reference to the changes in the PCB/SCH. The `n` value is how many
# changes in the history you want to go back. A 0 is the same as `HEAD`,
# a 1 means the last time the PCB/SCH was changed, etc
old: 'HEAD'
# [string='git'] [git,file] How to interpret the `old` name. Use `git` for a git hash, branch, etc.
# Use `file` for a file name
old_type: 'git'
# [string='%f-%i%I%v.%x'] Filename for the output (%i=diff, %x=pdf). Affected by global options
output: '%f-%i%I%v.%x'
# [boolean=true] Compare the PCB, otherwise compare the schematic
pcb: true
# [number=0] [0,1000000] Error threshold for the `stats` mode, 0 is no error. When specified a
# difference bigger than the indicated value will make the diff fail
threshold: 0
layers: all
# Datasheets downloader:
- name: 'download_datasheets_example'
comment: 'Downloads the datasheets for the project'

279
kibot/out_diff.py Normal file
View File

@ -0,0 +1,279 @@
# -*- 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)
"""
Dependencies:
- name: KiCad PCB/SCH Diff
role: mandatory
github: INTI-CMNB/KiDiff
command: kicad-diff.py
pypi: kidiff
downloader: pytool
id: KiDiff
- from: Git
role: Compare with files in the repo
"""
from hashlib import sha1
import os
from shutil import rmtree
from subprocess import run, CalledProcessError, STDOUT, PIPE
from tempfile import mkdtemp, NamedTemporaryFile
from .error import KiPlotConfigurationError
from .gs import GS
from .kiplot import load_any_sch
from .layer import Layer
from .misc import FAILED_EXECUTE
from .optionable import BaseOptions
from .macros import macros, document, output_class # noqa: F401
from . import log
logger = log.get_logger()
def debug_output(res):
if res.stdout:
logger.debug('- Output from command: '+res.stdout.decode())
def run_command(command, change_to=None):
logger.debug('Executing: '+str(command))
try:
res = run(command, check=True, stdout=PIPE, stderr=STDOUT, cwd=change_to)
except CalledProcessError as e:
logger.error('Running {} returned {}'.format(e.cmd, e.returncode))
debug_output(e)
exit(FAILED_EXECUTE)
debug_output(res)
return res.stdout.decode().rstrip()
class DiffOptions(BaseOptions):
def __init__(self):
with document:
self.output = GS.def_global_output
""" *Filename for the output (%i=diff, %x=pdf) """
self.pcb = True
""" Compare the PCB, otherwise compare the schematic """
self.old = 'HEAD'
""" Reference file. When using git use `HEAD` to refer to the last commit.
Use `HEAD~` to refer the previous to the last commit.
As `HEAD` is for the whole repo you can use `KIBOT_LAST-n` to make
reference to the changes in the PCB/SCH. The `n` value is how many
changes in the history you want to go back. A 0 is the same as `HEAD`,
a 1 means the last time the PCB/SCH was changed, etc """
self.old_type = 'git'
""" [git,file] How to interpret the `old` name. Use `git` for a git hash, branch, etc.
Use `file` for a file name """
self.new = ''
""" The file you want to compare. Leave it blank for the current PCB/SCH """
self.new_type = 'file'
""" [git,file] How to interpret the `new` name. Use `git` for a git hash, branch, etc.
Use `file` for a file name """
self.cache_dir = ''
""" Directory to cache the intermediate files. Leave it blank to disable the cache """
self.diff_mode = 'red_green'
""" [red_green,stats] In the `red_green` mode added stuff is green and red when removed.
The `stats` mode is used to meassure the amount of difference. In this mode all
changes are red, but you can abort if the difference is bigger than certain threshold """
self.fuzz = 5
""" [0,100] Color tolerance (fuzzyness) for the `stats` mode """
self.threshold = 0
""" [0,1000000] Error threshold for the `stats` mode, 0 is no error. When specified a
difference bigger than the indicated value will make the diff fail """
super().__init__()
self._expand_id = 'diff'
self._expand_ext = 'pdf'
def get_targets(self, out_dir):
return [self._parent.expand_filename(out_dir, self.output)]
def get_digest(self, file_path, restart=True):
logger.debug('Hashing '+file_path)
if restart:
self.h = sha1()
with open(file_path, 'rb') as file:
while True:
chunk = file.read(self.h.block_size)
if not chunk:
break
self.h.update(chunk)
return self.h.hexdigest()
def add_to_cache(self, name, hash):
cmd = [self.command, '--only_cache', '--old_file_hash', hash, '--cache_dir', self.cache_dir]
if self.incl_file:
cmd.extend(['--layers', self.incl_file])
if GS.debug_enabled:
cmd.insert(1, '-'+'v'*GS.debug_level)
cmd.extend([name, name])
run_command(cmd)
def cache_pcb(self, name):
if not name:
GS.check_pcb()
name = GS.pcb_file
hash = self.get_digest(name)
self.add_to_cache(name, hash)
return hash
def cache_sch(self, name):
if not name:
GS.check_sch()
name = GS.sch_file
# Schematics can have sub-sheets
sch = load_any_sch(name, os.path.splitext(os.path.basename(name))[0])
files = sch.get_files()
hash = self.get_digest(files[0])
if len(files) > 1:
for f in files[1:]:
hash = self.get_digest(f, restart=False)
hash = 'sch'+hash
self.add_to_cache(name, hash)
return hash
def cache_file(self, name=None):
return self.cache_pcb(name) if self.pcb else self.cache_sch(name)
def run_git(self, cmd):
return run_command([self.git_command]+cmd, change_to=self.repo_dir)
def undo_git(self):
if self.checkedout:
logger.debug('Restoring point '+self.branch)
self.run_git(['checkout', self.branch])
if self.stashed:
logger.debug('Restoring changes')
self.run_git(['stash', 'pop'])
def solve_git_name(self, name):
ori = name
if not name.startswith('KIBOT_LAST'):
return name
logger.debug('Finding '+name)
# The magic KIBOT_LAST
malformed = 'Malformed `KIBOT_LAST` value, must be `KIBOT_LAST-n`, not: '+ori
name = name[10:]
# How many changes?
num = 0
if name[0] != '-':
raise KiPlotConfigurationError(malformed)
try:
num = int(name[1:])
except ValueError:
raise KiPlotConfigurationError(malformed)
num = str(num)
# Return its hash
res = self.run_git(['log', '--pretty=format:%H', '--skip='+num, '-n', '1', '--', self.file])
logger.debug('- '+res)
return res
def cache_git(self, name):
self.stashed = False
self.checkedout = False
# Which file
if self.pcb:
GS.check_pcb()
self.file = GS.pcb_file
else:
GS.check_sch()
self.file = GS.sch_file
# Place where we know we have a repo
self.repo_dir = os.path.dirname(os.path.abspath(self.file))
try:
# Save current changes
logger.debug('Saving current changes')
self.run_git(['stash', 'push'])
self.stashed = True
# Find the current branch
self.branch = self.run_git(['rev-parse', '--abbrev-ref', 'HEAD'])
if self.branch == 'HEAD':
# Detached
self.branch = self.run_git(['rev-parse', 'HEAD'])
logger.debug('Current branch is '+self.branch)
# Checkout the target
name = self.solve_git_name(name)
logger.debug('Changing to '+name)
self.run_git(['checkout', name])
self.checkedout = True
# Populate the cache
hash = self.cache_file()
finally:
self.undo_git()
return hash
def cache_obj(self, name, type):
return self.cache_git(name) if type == 'git' else self.cache_file(name)
def create_layers_incl(self, layers):
incl_file = None
if self.pcb and not isinstance(layers, type):
layers = Layer.solve(layers)
logger.debug('Including layers:')
with NamedTemporaryFile(mode='w', suffix='.lst', delete=False) as f:
incl_file = f.name
for la in layers:
logger.debug('- {} ({})'.format(la.layer, la.id))
f.write(str(la.id)+'\n')
return incl_file
def run(self, name):
self.command = self.ensure_tool('KiDiff')
if self.old_type == 'git' or self.new_type == 'git':
self.git_command = self.ensure_tool('Git')
# Solve the cache dir
remove_cache = False
if not self.cache_dir:
self.cache_dir = mkdtemp()
remove_cache = True
# A valid name, not really used
file = GS.pcb_file or GS.sch_file
dir_name = os.path.dirname(name)
file_name = os.path.basename(name)
self.incl_file = None
try:
# List of layers
self.incl_file = self.create_layers_incl(self.layers)
# Populate the cache
old_hash = self.cache_obj(self.old, self.old_type)
new_hash = self.cache_obj(self.new, self.new_type)
# Compute the diff using the cache
cmd = [self.command, '--no_reader', '--new_file_hash', new_hash, '--old_file_hash', old_hash,
'--cache_dir', self.cache_dir, '--output_dir', dir_name, '--output_name', file_name,
'--diff_mode', self.diff_mode, '--fuzz', str(self.fuzz)]
if self.incl_file:
cmd.extend(['--layers', self.incl_file])
if self.threshold:
cmd.extend(['--threshold', str(self.threshold)])
cmd.extend([file, file])
if GS.debug_enabled:
cmd.insert(1, '-'+'v'*GS.debug_level)
run_command(cmd)
finally:
# Clean-up
if remove_cache:
rmtree(self.cache_dir)
if self.incl_file:
os.remove(self.incl_file)
@output_class
class Diff(BaseOutput): # noqa: F821
""" Diff
Generates a PDF with the differences between two PCBs or schematics """
def __init__(self):
super().__init__()
self._category = ['PCB/docs', 'Schematic/docs']
self._both_related = True
with document:
self.options = DiffOptions
""" *[dict] Options for the `diff` output """
self.layers = Layer
""" *[list(dict)|list(string)|string] [all,selected,copper,technical,user]
List of PCB layers to use. When empty all available layers are used.
Note that if you want to support adding/removing layers you should specify a list here """
def run(self, name):
self.options.layers = self.layers
super().run(name)

View File

@ -91,17 +91,23 @@ deps = '{\
"downloader_str": "git",\
"extra_deb": null,\
"help_option": "--version",\
"importance": 3,\
"importance": 4,\
"in_debian": true,\
"is_kicad_plugin": false,\
"is_python": false,\
"name": "Git",\
"no_cmd_line_version": false,\
"no_cmd_line_version_old": false,\
"output": "pcb_replace",\
"output": "diff",\
"plugin_dirs": null,\
"pypi_name": "Git",\
"roles": [\
{\
"desc": "Compare with files in the repo",\
"mandatory": false,\
"output": "diff",\
"version": null\
},\
{\
"desc": "Find commit hash and/or date",\
"mandatory": false,\
@ -380,6 +386,35 @@ deps = '{\
"url": "https://github.com/INTI-CMNB/KiAuto",\
"url_down": "https://github.com/INTI-CMNB/KiAuto/releases"\
},\
"KiCad PCB/SCH Diff": {\
"command": "kicad-diff.py",\
"comments": [],\
"deb_package": "kicad pcb/sch diff",\
"downloader": {},\
"downloader_str": "pytool",\
"extra_deb": null,\
"help_option": "--version",\
"importance": 10000,\
"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",\
"roles": [\
{\
"desc": null,\
"mandatory": true,\
"output": "diff",\
"version": null\
}\
],\
"url": "https://github.com/INTI-CMNB/KiDiff",\
"url_down": "https://github.com/INTI-CMNB/KiDiff/releases"\
},\
"KiCost": {\
"command": "kicost",\
"comments": [],\

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
light_control.sch

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
light_control.kicad_sch

Binary file not shown.

View File

@ -0,0 +1 @@
../5_1_6/light_control-diff.pdf

Binary file not shown.

View File

@ -1266,3 +1266,72 @@ def test_dont_stop_1(test_dir):
ctx.expect_out_file(pos_bot)
ctx.search_err('ERROR:Failed to create BoM')
ctx.clean_up(keep_project=True)
def test_diff_file_1(test_dir):
""" Difference between the current PCB and a reference file """
prj = 'light_control_diff'
yaml = 'diff_file_'+('k5' if context.ki5() else 'k6')
ctx = context.TestContext(test_dir, prj, yaml)
ctx.run()
ctx.compare_pdf(prj+'-diff.pdf', reference='light_control-diff.pdf')
ctx.clean_up(keep_project=True)
def test_diff_git_1(test_dir):
""" Difference between the current PCB and the git HEAD """
prj = 'light_control'
yaml = 'diff_git_1'
ctx = context.TestContext(test_dir, prj, yaml)
# Create a git repo
ctx.run_command(['git', 'init', '.'], chdir_out=True)
# Copy the "old" file
pcb = prj+'.kicad_pcb'
file = ctx.get_out_path(pcb)
shutil.copy2(ctx.board_file, file)
shutil.copy2(ctx.board_file.replace('.kicad_pcb', context.KICAD_SCH_EXT),
file.replace('.kicad_pcb', context.KICAD_SCH_EXT))
# Add it to the repo
ctx.run_command(['git', 'add', pcb], chdir_out=True)
ctx.run_command(['git', 'commit', '-m', 'Reference'], chdir_out=True)
# Copy the "new" file
shutil.copy2(ctx.board_file.replace(prj, prj+'_diff'), file)
# Run the test
ctx.run(extra=['-b', file], no_board_file=True)
ctx.compare_pdf(prj+'-diff.pdf')
ctx.clean_up(keep_project=True)
def test_diff_git_2(test_dir):
""" Difference between the two repo points """
prj = 'light_control'
yaml = 'diff_git_2'
ctx = context.TestContext(test_dir, prj, yaml)
# Create a git repo
ctx.run_command(['git', 'init', '.'], chdir_out=True)
# Copy the "old" file
pcb = prj+'.kicad_pcb'
file = ctx.get_out_path(pcb)
shutil.copy2(ctx.board_file, file)
shutil.copy2(ctx.board_file.replace('.kicad_pcb', context.KICAD_SCH_EXT),
file.replace('.kicad_pcb', context.KICAD_SCH_EXT))
# Add it to the repo
ctx.run_command(['git', 'add', pcb], chdir_out=True)
ctx.run_command(['git', 'commit', '-m', 'Reference'], chdir_out=True)
# Add an extra commit
dummy = ctx.get_out_path('dummy')
with open(dummy, 'wt') as f:
f.write('dummy\n')
ctx.run_command(['git', 'add', 'dummy'], chdir_out=True)
ctx.run_command(['git', 'commit', '-m', 'Dummy noise'], chdir_out=True)
# Copy the "new" file
shutil.copy2(ctx.board_file.replace(prj, prj+'_diff'), file)
# Add it to the repo
ctx.run_command(['git', 'add', pcb], chdir_out=True)
ctx.run_command(['git', 'commit', '-m', 'New version'], chdir_out=True)
# Now just wipe the current file
shutil.copy2(ctx.board_file.replace(prj, '3Rs'), file)
# Run the test
ctx.run(extra=['-b', file], no_board_file=True, extra_debug=True)
ctx.compare_pdf(prj+'-diff.pdf')
ctx.clean_up(keep_project=True)

View File

@ -329,6 +329,24 @@ class TestContext(object):
os.close(f_err)
self.err = self.err.decode()
def run_command(self, cmd, chdir_out=False):
if chdir_out:
cwd = os.getcwd()
os.chdir(self.output_dir)
logging.debug('Executing: '+str(cmd))
try:
res = subprocess.run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
logging.error('Running {} returned {}'.format(e.cmd, e.returncode))
if e.stdout:
logging.debug('- Output from command: '+e.stdout.decode())
raise
if res.stdout:
logging.debug('- Output from command: '+res.stdout.decode())
if chdir_out:
os.chdir(cwd)
return res.stdout.decode().rstrip()
def run(self, ret_val=None, extra=None, use_a_tty=False, filename=None, no_out_dir=False, no_board_file=False,
no_yaml_file=False, chdir_out=False, no_verbose=False, extra_debug=False, do_locale=False, kicost=False):
logging.debug('Running '+self.test_name)

View File

@ -0,0 +1,12 @@
kibot:
version: 1
outputs:
- name: 'diff_pcb'
comment: "PCB difference with reference file (KiCad 5)"
type: diff
layers: ['F.Cu', 'In1.Cu']
options:
old: tests/board_samples/kicad_5/light_control.kicad_pcb
old_type: file
cache_dir: .cache

View File

@ -0,0 +1,12 @@
kibot:
version: 1
outputs:
- name: 'diff_pcb'
comment: "PCB difference with reference file (KiCad 6)"
type: diff
layers: ['F.Cu', 'In1.Cu']
options:
old: tests/board_samples/kicad_6/light_control.kicad_pcb
old_type: file
cache_dir: .cache

View File

@ -0,0 +1,10 @@
kibot:
version: 1
outputs:
- name: 'diff_pcb'
comment: "PCB difference with git HEAD"
type: diff
layers: ['F.Cu', 'In1.Cu']
options:
cache_dir: .cache

View File

@ -0,0 +1,14 @@
kibot:
version: 1
outputs:
- name: 'diff_pcb'
comment: "PCB difference with git HEAD"
type: diff
layers: ['F.Cu', 'In1.Cu']
options:
old: KIBOT_LAST-1
old_type: git
new: HEAD
new_type: git
cache_dir: .cache