Skip to content

Commit

Permalink
[DRC/ERC][Added] Individual directory for reports
Browse files Browse the repository at this point in the history
- Also joined ignore_unconnected and erc_warnings options
- Deprecated separated options

Closes #562
  • Loading branch information
set-soft committed Jan 18, 2024
1 parent c04f7e5 commit 2385013
Show file tree
Hide file tree
Showing 10 changed files with 169 additions and 41 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `download_lcsc` option to disable LCSC 3D model download (See #415)
- Problems when creating a colored resistor, but we didn't have a cache yet
(i.e. no model downloaded) #553
- Preflights:
- Individual directory for the ERC and DRC reports (#562)
- BoM:
- Support for ${field} expansion. (#471)
- LCSC links (SchrodingersGat/KiBoM#190)
Expand Down
10 changes: 6 additions & 4 deletions docs/samples/generic_plot.kibot.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ preflight:
# The original PCB remains unchanged. If you need to abort when the zone fill
# creates significant changes to a layer use the CheckZoneFill internal template.
check_zone_fills: true
# [boolean=false] Option for `run_erc`. ERC warnings are considered errors.
# [boolean=false] **Deprecated**, use the `warnings_as_errors` option from `run_erc`.
# Option for `run_erc`. ERC warnings are considered errors.
erc_warnings: false
# [boolean=false] Fill all zones again and save the PCB.
fill_zones: true
Expand All @@ -40,7 +41,8 @@ preflight:
- filter: 'Filter description'
error: '10'
regex: 'Regular expression to match'
# [boolean=false] Option for `run_drc`. Ignores the unconnected nets. Useful if you didn't finish the routing.
# [boolean=false] **Deprecated**, use the `ignore_unconnected` option from `run_drc`.
# Option for `run_drc`. Ignores the unconnected nets. Useful if you didn't finish the routing.
# It will also ignore KiCad 6 warnings.
ignore_unconnected: false
# [dict] Replaces tags in the PCB. I.e. to insert the git hash or last revision date.
Expand All @@ -53,15 +55,15 @@ preflight:
command: 'git log -1 --format="%h" "$KIBOT_PCB_NAME"'
before: 'Git hash: <'
after: '>'
# [boolean=false] Runs the DRC (Distance Rules Check). To ensure we have a valid PCB.
# [boolean=false|dict] Runs the DRC (Distance Rules Check). To ensure we have a valid PCB.
# The report file name is controlled by the global output pattern (%i=drc %x=txt).
# Note that the KiCad 6+ *Test for parity between PCB and schematic* option is not supported.
# If you need to check the parity use the `update_xml` preflight.
# KiCad 6 introduced `warnings` they are currently counted be the `unconnected` counter of KiBot.
# This will change in the future.
# If you use DRC exclusions please consult the `drc_exclusions_workaround` global option.
run_drc: true
# [boolean=false] Runs the ERC (Electrical Rules Check). To ensure the schematic is electrically correct.
# [boolean=false|dict] Runs the ERC (Electrical Rules Check). To ensure the schematic is electrically correct.
# The report file name is controlled by the global output pattern (%i=erc %x=txt).
run_erc: true
# [dict] Replaces tags in the schematic. I.e. to insert the git hash or last revision date.
Expand Down
25 changes: 21 additions & 4 deletions docs/source/configuration/sup_preflights.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ Supported preflights
- **check_zone_fills**: :index:`: <pair: preflights; check_zone_fills>` [boolean=false] Zones are filled before doing any operation involving PCB layers.
The original PCB remains unchanged. If you need to abort when the zone fill
creates significant changes to a layer use the CheckZoneFill internal template.
- **erc_warnings**: :index:`: <pair: preflights; erc_warnings>` [boolean=false] Option for `run_erc`. ERC warnings are considered errors.
- **erc_warnings**: :index:`: <pair: preflights; erc_warnings>` [boolean=false] **Deprecated**, use the `warnings_as_errors` option from `run_erc`.
Option for `run_erc`. ERC warnings are considered errors.
- **fill_zones**: :index:`: <pair: preflights; fill_zones>` [boolean=false] Fill all zones again and save the PCB.
- **filters**: :index:`: <pair: preflights; filters>` [list(dict)] A list of entries to filter out ERC/DRC messages.
Note that ignored errors will become KiBot warnings (i.e. `(W058) ...`). |br|
Expand All @@ -50,7 +51,8 @@ Supported preflights
- ``regex`` :index:`: <pair: preflight - filters; regex>` [string=''] Regular expression to match the text for the error we want to exclude.
- *regexp* :index:`: <pair: preflight - filters; regexp>` Alias for regex.

- **ignore_unconnected**: :index:`: <pair: preflights; ignore_unconnected>` [boolean=false] Option for `run_drc`. Ignores the unconnected nets. Useful if you didn't finish the routing.
- **ignore_unconnected**: :index:`: <pair: preflights; ignore_unconnected>` [boolean=false] **Deprecated**, use the `ignore_unconnected` option from `run_drc`.
Option for `run_drc`. Ignores the unconnected nets. Useful if you didn't finish the routing. |br|
It will also ignore KiCad 6 warnings.
- **pcb_replace**: :index:`: <pair: preflights; pcb_replace>` [dict] Replaces tags in the PCB. I.e. to insert the git hash or last revision date.
This is useful for KiCad 5, use `set_text_variables` when using KiCad 6. |br|
Expand Down Expand Up @@ -79,15 +81,30 @@ Supported preflights
- ``text`` :index:`: <pair: preflight - pcb_replace - replace_tags; text>` [string=''] Text to insert instead of the tag.


- **run_drc**: :index:`: <pair: preflights; run_drc>` [boolean=false] Runs the DRC (Distance Rules Check). To ensure we have a valid PCB.
- **run_drc**: :index:`: <pair: preflights; run_drc>` [boolean=false|dict] Runs the DRC (Distance Rules Check). To ensure we have a valid PCB.
The report file name is controlled by the global output pattern (%i=drc %x=txt). |br|
Note that the KiCad 6+ *Test for parity between PCB and schematic* option is not supported. |br|
If you need to check the parity use the `update_xml` preflight. |br|
KiCad 6 introduced `warnings` they are currently counted be the `unconnected` counter of KiBot. |br|
This will change in the future. |br|
If you use DRC exclusions please consult the `drc_exclusions_workaround` global option.
- **run_erc**: :index:`: <pair: preflights; run_erc>` [boolean=false] Runs the ERC (Electrical Rules Check). To ensure the schematic is electrically correct.

- Valid keys:

- ``dir`` :index:`: <pair: preflight - run_drc; dir>` [string=''] Sub-directory for the report.
- ``enabled`` :index:`: <pair: preflight - run_drc; enabled>` [boolean=true] Enable the DRC. This is the replacement for the boolean value.
- ``ignore_unconnected`` :index:`: <pair: preflight - run_drc; ignore_unconnected>` [boolean=false] Ignores the unconnected nets. Useful if you didn't finish the routing.
It will also ignore KiCad 6 warnings.

- **run_erc**: :index:`: <pair: preflights; run_erc>` [boolean=false|dict] Runs the ERC (Electrical Rules Check). To ensure the schematic is electrically correct.
The report file name is controlled by the global output pattern (%i=erc %x=txt).

- Valid keys:

- ``dir`` :index:`: <pair: preflight - run_erc; dir>` [string=''] Sub-directory for the report.
- ``enabled`` :index:`: <pair: preflight - run_erc; enabled>` [boolean=true] Enable the ERC. This is the replacement for the boolean value.
- ``warnings_as_errors`` :index:`: <pair: preflight - run_erc; warnings_as_errors>` [boolean=false] ERC warnings are considered errors.

- **sch_replace**: :index:`: <pair: preflights; sch_replace>` [dict] Replaces tags in the schematic. I.e. to insert the git hash or last revision date.
This is useful for KiCad 5, use `set_text_variables` when using KiCad 6. |br|
This preflight modifies the schematics. Even when a back-up is done use it carefully.
Expand Down
3 changes: 2 additions & 1 deletion kibot/pre_erc_warnings.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@

@pre_class
class ERC_Warnings(BasePreFlight): # noqa: F821
""" [boolean=false] Option for `run_erc`. ERC warnings are considered errors """
""" [boolean=false] **Deprecated**, use the `warnings_as_errors` option from `run_erc`.
Option for `run_erc`. ERC warnings are considered errors """
def __init__(self, name, value):
super().__init__(name, value)
if not isinstance(value, bool):
Expand Down
3 changes: 2 additions & 1 deletion kibot/pre_ignore_unconnected.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@

@pre_class
class Ignore_Unconnected(BasePreFlight): # noqa: F821
""" [boolean=false] Option for `run_drc`. Ignores the unconnected nets. Useful if you didn't finish the routing.
""" [boolean=false] **Deprecated**, use the `ignore_unconnected` option from `run_drc`.
Option for `run_drc`. Ignores the unconnected nets. Useful if you didn't finish the routing.
It will also ignore KiCad 6 warnings """
def __init__(self, name, value):
super().__init__(name, value)
Expand Down
53 changes: 41 additions & 12 deletions kibot/pre_run_drc.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020-2023 Salvador E. Tropea
# Copyright (c) 2020-2023 Instituto Nacional de Tecnología Industrial
# License: GPL-3.0
# Copyright (c) 2020-2024 Salvador E. Tropea
# Copyright (c) 2020-2024 Instituto Nacional de Tecnología Industrial
# License: AGPL-3.0
# Project: KiBot (formerly KiPlot)
"""
Dependencies:
Expand All @@ -10,7 +10,7 @@
version: 2.0.0
"""
import os
from .macros import macros, pre_class # noqa: F401
from .macros import macros, document, pre_class # noqa: F401
from .error import KiPlotConfigurationError
from .gs import GS
from .optionable import Optionable
Expand All @@ -22,9 +22,24 @@
logger = get_logger(__name__)


class Run_DRCOptions(Optionable):
""" DRC options """
def __init__(self):
super().__init__()
with document:
self.enabled = True
""" Enable the DRC. This is the replacement for the boolean value """
self.dir = ''
""" Sub-directory for the report """
self.ignore_unconnected = False
""" Ignores the unconnected nets. Useful if you didn't finish the routing.
It will also ignore KiCad 6 warnings """
self._unknown_is_error = True


@pre_class
class Run_DRC(BasePreFlight): # noqa: F821
""" [boolean=false] Runs the DRC (Distance Rules Check). To ensure we have a valid PCB.
""" [boolean=false|dict] Runs the DRC (Distance Rules Check). To ensure we have a valid PCB.
The report file name is controlled by the global output pattern (%i=drc %x=txt).
Note that the KiCad 6+ *Test for parity between PCB and schematic* option is not supported.
If you need to check the parity use the `update_xml` preflight.
Expand All @@ -33,9 +48,19 @@ class Run_DRC(BasePreFlight): # noqa: F821
If you use DRC exclusions please consult the `drc_exclusions_workaround` global option """
def __init__(self, name, value):
super().__init__(name, value)
if not isinstance(value, bool):
raise KiPlotConfigurationError('must be boolean')
self._enabled = value
if isinstance(value, bool):
self._enabled = value
self._dir = ''
self._ignore_unconnected = False
elif isinstance(value, dict):
f = Run_DRCOptions()
f.set_tree(value)
f.config(self)
self._enabled = f.enabled
self._dir = f.dir
self._ignore_unconnected = f.ignore_unconnected
else:
raise KiPlotConfigurationError('must be boolean or dict')
self._pcb_related = True
self._expand_id = 'drc'
self._expand_ext = 'txt'
Expand All @@ -48,7 +73,11 @@ def get_targets(self):
out_dir = self.expand_dirname(GS.out_dir)
if GS.global_dir and GS.global_use_dir_for_preflights:
out_dir = os.path.join(out_dir, self.expand_dirname(GS.global_dir))
return [os.path.abspath(os.path.join(out_dir, name))]
return [os.path.abspath(os.path.join(out_dir, self._dir, name))]

@classmethod
def get_doc(cls):
return cls.__doc__, Run_DRCOptions

def run(self):
command = self.ensure_tool('KiAuto')
Expand All @@ -62,14 +91,14 @@ def run(self):
output = self.get_targets()[0]
os.makedirs(os.path.dirname(output), exist_ok=True)
logger.debug('DRC report: '+output)
cmd = [command, 'run_drc', '-o', output]
cmd = [command, 'run_drc', '-o', os.path.basename(output)]
if GS.filter_file:
cmd.extend(['-f', GS.filter_file])
if GS.global_drc_exclusions_workaround:
cmd.append('-F')
if BasePreFlight.get_option('ignore_unconnected'): # noqa: F821
if self._ignore_unconnected or BasePreFlight.get_option('ignore_unconnected'): # noqa: F821
cmd.append('-i')
cmd.extend([GS.pcb_file, self.expand_dirname(GS.out_dir)])
cmd.extend([GS.pcb_file, os.path.dirname(output)])
# If we are in verbose mode enable debug in the child
cmd = self.add_extra_options(cmd)
logger.info('- Running the DRC')
Expand Down
61 changes: 44 additions & 17 deletions kibot/pre_run_erc.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020-2023 Salvador E. Tropea
# Copyright (c) 2020-2023 Instituto Nacional de Tecnología Industrial
# License: GPL-3.0
# Copyright (c) 2020-2024 Salvador E. Tropea
# Copyright (c) 2020-2024 Instituto Nacional de Tecnología Industrial
# License: AGPL-3.0
# Project: KiBot (formerly KiPlot)
"""
Dependencies:
Expand All @@ -13,7 +13,7 @@
import os
from shutil import move
from tempfile import NamedTemporaryFile
from .macros import macros, pre_class # noqa: F401
from .macros import macros, document, pre_class # noqa: F401
from .gs import GS
from .optionable import Optionable
from .kiplot import load_sch
Expand All @@ -24,15 +24,39 @@
logger = get_logger(__name__)


class Run_ERCOptions(Optionable):
""" ERC options """
def __init__(self):
super().__init__()
with document:
self.enabled = True
""" Enable the ERC. This is the replacement for the boolean value """
self.dir = ''
""" Sub-directory for the report """
self.warnings_as_errors = False
""" ERC warnings are considered errors """
self._unknown_is_error = True


@pre_class
class Run_ERC(BasePreFlight): # noqa: F821
""" [boolean=false] Runs the ERC (Electrical Rules Check). To ensure the schematic is electrically correct.
""" [boolean=false|dict] Runs the ERC (Electrical Rules Check). To ensure the schematic is electrically correct.
The report file name is controlled by the global output pattern (%i=erc %x=txt) """
def __init__(self, name, value):
super().__init__(name, value)
if not isinstance(value, bool):
raise KiPlotConfigurationError('must be boolean')
self._enabled = value
if isinstance(value, bool):
self._enabled = value
self._dir = ''
self._warnings_as_errors = False
elif isinstance(value, dict):
f = Run_ERCOptions()
f.set_tree(value)
f.config(self)
self._enabled = f.enabled
self._dir = f.dir
self._warnings_as_errors = f.warnings_as_errors
else:
raise KiPlotConfigurationError('must be boolean or dict')
self._sch_related = True
self._expand_id = 'erc'
self._expand_ext = 'txt'
Expand All @@ -45,33 +69,36 @@ def get_targets(self):
out_dir = self.expand_dirname(GS.out_dir)
if GS.global_dir and GS.global_use_dir_for_preflights:
out_dir = os.path.join(out_dir, self.expand_dirname(GS.global_dir))
return [os.path.abspath(os.path.join(out_dir, name))]
return [os.path.abspath(os.path.join(out_dir, self._dir, name))]

@classmethod
def get_doc(cls):
return cls.__doc__, Run_ERCOptions

def run(self):
command = self.ensure_tool('KiAuto')
# The schematic is loaded only before executing an output related to it.
# But here we need data from it.
output = self.get_targets()[0]
os.makedirs(os.path.dirname(output), exist_ok=True)
# Workaround for KiCad 7 odd behavior: it forces a file extension
# Note: One thing is adding the extension before you enter a name, other is add something you removed on purpose
with NamedTemporaryFile(mode='w', delete=False, suffix='.rpt', prefix='erc_report') as f:
tmp_name = f.name
logger.debug('ERC report: '+tmp_name)
cmd = [command, 'run_erc', '-o', tmp_name, '-g', str(GS.global_erc_grid)]
if BasePreFlight.get_option('erc_warnings'): # noqa: F821
cmd = [command, 'run_erc', '-o', os.path.basename(tmp_name), '-g', str(GS.global_erc_grid)]
if self._warnings_as_errors or BasePreFlight.get_option('erc_warnings'): # noqa: F821
cmd.append('-w')
if GS.filter_file:
cmd.extend(['-f', GS.filter_file])
cmd.extend([GS.sch_file, self.expand_dirname(GS.out_dir)])
cmd.extend([GS.sch_file, os.path.dirname(tmp_name)])
# If we are in verbose mode enable debug in the child
cmd = self.add_extra_options(cmd)
logger.info('- Running the ERC')
ret = self.exec_with_retry(cmd)
# Move the report to the desired name
output = self.get_targets()[0]
os.makedirs(os.path.dirname(output), exist_ok=True)
try:
move(tmp_name, output)
except FileNotFoundError:
pass
logger.error(' Oops!')
if ret:
if ret > 127:
ret = -(256-ret)
Expand Down
27 changes: 25 additions & 2 deletions tests/test_plot/test_preflight.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,19 @@ def test_erc_warning_2(test_dir):
ctx.clean_up(keep_project=context.ki7())


@pytest.mark.slow
@pytest.mark.eeschema
def test_erc_warning_3(test_dir):
""" Using an SCH with ERC warnings as errors """
prj = 'warning-project'
ctx = context.TestContextSCH(test_dir, 'erc_warning/'+prj, 'erc_no_w_2', 'def_dir')
ctx.run(ERC_ERROR)
# Check all outputs are there
ctx.expect_out_file(prj+'-erc.txt', sub=True)
ctx.search_err(r"ERROR:1 ERC errors detected")
ctx.clean_up(keep_project=context.ki7())


@pytest.mark.slow
@pytest.mark.eeschema
@pytest.mark.skipif(not context.ki7(), reason="KiCad 7 off grid check")
Expand Down Expand Up @@ -129,8 +142,8 @@ def test_drc_filter_2(test_dir):
ctx.clean_up(keep_project=True)


def test_drc_unco(test_dir):
""" Check we can ignore unconnected nets """
def test_drc_unco_1(test_dir):
""" Check we can ignore unconnected nets. Old style """
prj = 'warning-project'
ctx = context.TestContext(test_dir, prj, 'drc_unco', '')
ctx.run()
Expand All @@ -139,6 +152,16 @@ def test_drc_unco(test_dir):
ctx.clean_up()


def test_drc_unco_2(test_dir):
""" Check we can ignore unconnected nets. New style """
prj = 'warning-project'
ctx = context.TestContext(test_dir, prj, 'drc_unco_2', 'def_dir')
ctx.run()
# Check all outputs are there
ctx.expect_out_file(prj+'-drc.txt', sub=True)
ctx.clean_up()


def test_drc_error(test_dir):
""" Check we catch DRC errors """
prj = 'warning-project'
Expand Down
8 changes: 8 additions & 0 deletions tests/yaml_samples/drc_unco_2.kibot.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Example KiBot config file
kibot:
version: 1

preflight:
run_drc:
dir: def_dir
ignore_unconnected: true
Loading

0 comments on commit 2385013

Please sign in to comment.