diff --git a/.github/workflows/pythonapp.yml b/.github/workflows/pythonapp.yml index 893df32f9..42162bdf7 100644 --- a/.github/workflows/pythonapp.yml +++ b/.github/workflows/pythonapp.yml @@ -5,27 +5,17 @@ name: Python application on: push: - branches: [ master ] - tags-ignore: - - "v*" + paths: + - '**.py' + - 'src/kiplot' + - 'tests/**' + - '.github/workflows/pythonapp.yml' pull_request: - branches: [ master ] - -# on: -# push: -# paths: -# - '**.py' -# - 'src/kiplot' -# - 'tests/**' -# - '.github/workflows/pythonapp.yml' -# tags-ignore: -# - "v*" -# pull_request: -# paths: -# - '**.py' -# - 'src/kiplot' -# - 'tests/**' -# - '.github/workflows/pythonapp.yml' + paths: + - '**.py' + - 'src/kiplot' + - 'tests/**' + - '.github/workflows/pythonapp.yml' jobs: test: diff --git a/CHANGELOG.md b/CHANGELOG.md index 66d302c76..cfec159c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added - Tolerate config files without outputs +- Mechanism to filter ERC/DRC errors ### Fixed - All pcbnew plot formats generated gerber job files diff --git a/README.md b/README.md index d78f7f3b2..2c086d188 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,53 @@ preflight: ignore_unconnected: false ``` +### Filtering DRC/ERC errors + +Sometimes KiCad reports DRC or ERC errors that you can't get rid off. This could be just because you are part of a team including lazzy people that doesn't want to take the extra effort to solve some errors that aren't in fact errors, just small violations made on purpose. In this case you could exclude some known errors. + +For this you must declare `filters` entry in the `preflight` section. Then you can add as many `filter` entries as you want. Each filter entry has an optional description and defines to which error type is applied (`number`) and a regular expression that the error must match to be ignored (`regex`). Like this: + +``` + filters: + - filter: 'Optional filter description' + number: Numeric_error_type + regex: 'Expression to match' +``` + +Here is an example, suppose you are getting the following errors: + +``` +** Found 1 DRC errors ** +ErrType(4): Track too close to pad + @(177.185 mm, 78.315 mm): Track 1.000 mm [Net-(C3-Pad1)] on F.Cu, length: 1.591 mm + @(177.185 mm, 80.715 mm): Pad 2 of C3 on F.Cu and others + +** Found 1 unconnected pads ** +ErrType(2): Unconnected items + @(177.185 mm, 73.965 mm): Pad 2 of C4 on F.Cu and others + @(177.185 mm, 80.715 mm): Pad 2 of C3 on F.Cu and others +``` + +And you want to ignore them. You can add the following filters: + +``` + filters: + - filter: 'Ignore C3 pad 2 too close to anything' + number: 4 + regex: 'Pad 2 of C3' + - filter: 'Ignore unconnected pad 2 of C4' + number: 2 + regex: 'Pad 2 of C4' +``` + +If you need to match text from two different lines in the error message try using `(?s)TEXT(.*)TEXT_IN_OTHER_LINE`. + +If you have two or more different options for a text to match try using `(OPTION1|OPTION2)`. + +A complete Python regular expressions explanation is out the scope of this manual. For a complete reference consult the [Python manual](https://docs.python.org/3/library/re.html). + +**Important note**: this will create a file named *kiplot_errors.filter* in the output directory. + ### The *outputs* section In this section you put all the things that you want to generate. This section contains one or more **outputs**. Each output contain the following data: diff --git a/kiplot/config_reader.py b/kiplot/config_reader.py index f464288fe..1c5298402 100644 --- a/kiplot/config_reader.py +++ b/kiplot/config_reader.py @@ -537,6 +537,26 @@ def _parse_output(self, o_obj): return o_cfg + def _parse_filters(self, filters, cfg): + for filter in filters: + if 'filter' in filter: + comment = filter['filter'] + if 'number' in filter: + number = filter['number'] + if number is None: + config_error("empty 'number' in 'filter' definition ("+str(filter)+")") + else: + config_error("missing 'number' for 'filter' definition ("+str(filter)+")") + if 'regex' in filter: + regex = filter['regex'] + if regex is None: + config_error("empty 'regex' in 'filter' definition ("+str(filter)+")") + else: + config_error("missing 'regex' for 'filter' definition ("+str(filter)+")") + cfg.add_filter(comment, number, regex) + else: + config_error("'filters' section of 'preflight' must contain 'filter' definitions (not "+str(filter)+")") + def _parse_preflight(self, pf, cfg): logger.debug("Parsing preflight options: {}".format(pf)) @@ -556,6 +576,9 @@ def _parse_preflight(self, pf, cfg): if 'ignore_unconnected' in pf: cfg.ignore_unconnected = pf['ignore_unconnected'] + if 'filters' in pf: + self._parse_filters(pf['filters'], cfg) + def read(self, fstream): """ Read a file object into a config object diff --git a/kiplot/kiplot.py b/kiplot/kiplot.py index 090a92c46..d668ffaa7 100644 --- a/kiplot/kiplot.py +++ b/kiplot/kiplot.py @@ -68,7 +68,7 @@ def check_script(cmd, url, version=None): def check_eeschema_do(file): - check_script(misc.CMD_EESCHEMA_DO, misc.URL_EESCHEMA_DO, '1.1.1') + check_script(misc.CMD_EESCHEMA_DO, misc.URL_EESCHEMA_DO, '1.4.0') sch_file = os.path.splitext(file)[0] + '.sch' if not os.path.isfile(sch_file): logger.error('Missing schematic file: ' + sch_file) @@ -157,17 +157,26 @@ def _preflight_checks(self, brd_file, skip_pre): else: logger.error('Unknown action to skip: '+skip) exit(misc.EXIT_BAD_ARGS) + # Create the filters file + filter_file = None + if (self.cfg.run_erc or self.cfg.run_drc) and self.cfg.filters: + filter_file = os.path.join(self.cfg.outdir, 'kiplot_errors.filter') + with open(filter_file, 'w') as f: + f.write(self.cfg.filters) if self.cfg.run_erc: - self._run_erc(brd_file) + self._run_erc(brd_file, filter_file) if self.cfg.update_xml: self._update_xml(brd_file) if self.cfg.run_drc: self._run_drc(brd_file, self.cfg.ignore_unconnected, - self.cfg.check_zone_fills) + self.cfg.check_zone_fills, filter_file) - def _run_erc(self, brd_file): + def _run_erc(self, brd_file, filter_file): sch_file = check_eeschema_do(brd_file) - cmd = [misc.CMD_EESCHEMA_DO, 'run_erc', sch_file, self.cfg.outdir] + cmd = [misc.CMD_EESCHEMA_DO, 'run_erc'] + if filter_file: + cmd.extend(['-f', filter_file]) + cmd.extend([sch_file, self.cfg.outdir]) # If we are in verbose mode enable debug in the child if logger.getEffectiveLevel() <= logging.DEBUG: cmd.insert(1, '-vv') @@ -196,9 +205,12 @@ def _update_xml(self, brd_file): logger.error('Failed to update the BoM, error %d', ret) exit(misc.BOM_ERROR) - def _run_drc(self, brd_file, ignore_unconnected, check_zone_fills): - check_script(misc.CMD_PCBNEW_RUN_DRC, misc.URL_PCBNEW_RUN_DRC, '1.3.1') - cmd = [misc.CMD_PCBNEW_RUN_DRC, 'run_drc', brd_file, self.cfg.outdir] + def _run_drc(self, brd_file, ignore_unconnected, check_zone_fills, filter_file): + check_script(misc.CMD_PCBNEW_RUN_DRC, misc.URL_PCBNEW_RUN_DRC, '1.4.0') + cmd = [misc.CMD_PCBNEW_RUN_DRC, 'run_drc'] + if filter_file: + cmd.extend(['-f', filter_file]) + cmd.extend([brd_file, self.cfg.outdir]) # If we are in verbose mode enable debug in the child if logger.getEffectiveLevel() <= logging.DEBUG: cmd.insert(1, '-vv') @@ -407,8 +419,6 @@ def _do_position_plot_ascii(self, board, plot_ctrl, output, columns, modulesStr, maxSizes): to = output.options.type_options outdir = plot_ctrl.GetPlotOptions().GetOutputDirectory() - if not os.path.exists(outdir): - os.makedirs(outdir) name = os.path.splitext(os.path.basename(board.GetFileName()))[0] topf = None diff --git a/kiplot/plot_config.py b/kiplot/plot_config.py index da3909aac..0bb39e5d6 100644 --- a/kiplot/plot_config.py +++ b/kiplot/plot_config.py @@ -1,6 +1,9 @@ import pcbnew from . import error +from . import log + +logger = log.get_logger(__name__) class KiPlotConfigurationError(error.KiPlotError): @@ -504,10 +507,19 @@ def __init__(self): self.update_xml = False self.ignore_unconnected = False self.run_erc = False + self.filters = None def add_output(self, new_op): self._outputs.append(new_op) + def add_filter(self, comment, number, regex): + logger.debug("Adding DRC/ERC filter '{}','{}','{}'".format(comment, number, regex)) + if self.filters is None: + self.filters = '' + if comment: + self.filters += '# '+comment+'\n' + self.filters += '{},{}\n'.format(number, regex) + def validate(self): errs = [] for o in self._outputs: diff --git a/tests/board_samples/fail-project.kicad_pcb b/tests/board_samples/fail-project.kicad_pcb new file mode 100644 index 000000000..c2563fad9 --- /dev/null +++ b/tests/board_samples/fail-project.kicad_pcb @@ -0,0 +1,396 @@ +(kicad_pcb (version 20171130) (host pcbnew 5.1.0) + + (general + (thickness 1.6) + (drawings 4) + (tracks 17) + (zones 0) + (modules 6) + (nets 6) + ) + + (page A4) + (layers + (0 F.Cu signal) + (31 B.Cu signal) + (32 B.Adhes user) + (33 F.Adhes user) + (34 B.Paste user) + (35 F.Paste user) + (36 B.SilkS user) + (37 F.SilkS user) + (38 B.Mask user) + (39 F.Mask user) + (40 Dwgs.User user) + (41 Cmts.User user) + (42 Eco1.User user) + (43 Eco2.User user) + (44 Edge.Cuts user) + (45 Margin user) + (46 B.CrtYd user) + (47 F.CrtYd user) + (48 B.Fab user) + (49 F.Fab user) + ) + + (setup + (last_trace_width 0.25) + (trace_clearance 0.2) + (zone_clearance 0.508) + (zone_45_only no) + (trace_min 0.2) + (via_size 0.8) + (via_drill 0.4) + (via_min_size 0.4) + (via_min_drill 0.3) + (uvia_size 0.3) + (uvia_drill 0.1) + (uvias_allowed no) + (uvia_min_size 0.2) + (uvia_min_drill 0.1) + (edge_width 0.05) + (segment_width 0.2) + (pcb_text_width 0.3) + (pcb_text_size 1.5 1.5) + (mod_edge_width 0.12) + (mod_text_size 1 1) + (mod_text_width 0.15) + (pad_size 1.524 1.524) + (pad_drill 0.762) + (pad_to_mask_clearance 0.051) + (solder_mask_min_width 0.25) + (aux_axis_origin 0 0) + (visible_elements FFFFFF7F) + (pcbplotparams + (layerselection 0x010fc_ffffffff) + (usegerberextensions false) + (usegerberattributes false) + (usegerberadvancedattributes false) + (creategerberjobfile false) + (excludeedgelayer true) + (linewidth 0.100000) + (plotframeref false) + (viasonmask false) + (mode 1) + (useauxorigin false) + (hpglpennumber 1) + (hpglpenspeed 20) + (hpglpendiameter 15.000000) + (psnegative false) + (psa4output false) + (plotreference true) + (plotvalue true) + (plotinvisibletext false) + (padsonsilk false) + (subtractmaskfromsilk false) + (outputformat 1) + (mirror false) + (drillshape 1) + (scaleselection 1) + (outputdirectory "")) + ) + + (net 0 "") + (net 1 /Power/VCC) + (net 2 GND) + (net 3 "Net-(C2-Pad1)") + (net 4 "Net-(C3-Pad1)") + (net 5 "Net-(C3-Pad2)") + + (net_class Default "This is the default net class." + (clearance 0.2) + (trace_width 0.25) + (via_dia 0.8) + (via_drill 0.4) + (uvia_dia 0.3) + (uvia_drill 0.1) + (add_net /Power/VCC) + (add_net GND) + (add_net "Net-(C2-Pad1)") + (add_net "Net-(C3-Pad1)") + (add_net "Net-(C3-Pad2)") + ) + + (module Capacitor_SMD:C_0402_1005Metric (layer F.Cu) (tedit 5B301BBE) (tstamp 5CA72801) + (at 164.775001 80.505001 90) + (descr "Capacitor SMD 0402 (1005 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: http://www.tortai-tech.com/upload/download/2011102023233369053.pdf), generated with kicad-footprint-generator") + (tags capacitor) + (path /5CA71704/5CA745A6) + (attr smd) + (fp_text reference C1 (at 0 -1.17 90) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value C (at 0 1.17 90) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -0.5 0.25) (end -0.5 -0.25) (layer F.Fab) (width 0.1)) + (fp_line (start -0.5 -0.25) (end 0.5 -0.25) (layer F.Fab) (width 0.1)) + (fp_line (start 0.5 -0.25) (end 0.5 0.25) (layer F.Fab) (width 0.1)) + (fp_line (start 0.5 0.25) (end -0.5 0.25) (layer F.Fab) (width 0.1)) + (fp_line (start -0.93 0.47) (end -0.93 -0.47) (layer F.CrtYd) (width 0.05)) + (fp_line (start -0.93 -0.47) (end 0.93 -0.47) (layer F.CrtYd) (width 0.05)) + (fp_line (start 0.93 -0.47) (end 0.93 0.47) (layer F.CrtYd) (width 0.05)) + (fp_line (start 0.93 0.47) (end -0.93 0.47) (layer F.CrtYd) (width 0.05)) + (fp_text user %R (at 0 0 90) (layer F.Fab) + (effects (font (size 0.25 0.25) (thickness 0.04))) + ) + (pad 1 smd roundrect (at -0.485 0 90) (size 0.59 0.64) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 1 /Power/VCC)) + (pad 2 smd roundrect (at 0.485 0 90) (size 0.59 0.64) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 2 GND)) + (model ${KISYS3DMOD}/Capacitor_SMD.3dshapes/C_0402_1005Metric.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Capacitor_SMD:C_0402_1005Metric (layer F.Cu) (tedit 5B301BBE) (tstamp 5CA72810) + (at 170.18 80.020001 90) + (descr "Capacitor SMD 0402 (1005 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: http://www.tortai-tech.com/upload/download/2011102023233369053.pdf), generated with kicad-footprint-generator") + (tags capacitor) + (path /5CA75BC1/5CA76352) + (attr smd) + (fp_text reference C2 (at 0 -1.17 90) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value C (at 0 1.17 90) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text user %R (at 0 0 90) (layer F.Fab) + (effects (font (size 0.25 0.25) (thickness 0.04))) + ) + (fp_line (start 0.93 0.47) (end -0.93 0.47) (layer F.CrtYd) (width 0.05)) + (fp_line (start 0.93 -0.47) (end 0.93 0.47) (layer F.CrtYd) (width 0.05)) + (fp_line (start -0.93 -0.47) (end 0.93 -0.47) (layer F.CrtYd) (width 0.05)) + (fp_line (start -0.93 0.47) (end -0.93 -0.47) (layer F.CrtYd) (width 0.05)) + (fp_line (start 0.5 0.25) (end -0.5 0.25) (layer F.Fab) (width 0.1)) + (fp_line (start 0.5 -0.25) (end 0.5 0.25) (layer F.Fab) (width 0.1)) + (fp_line (start -0.5 -0.25) (end 0.5 -0.25) (layer F.Fab) (width 0.1)) + (fp_line (start -0.5 0.25) (end -0.5 -0.25) (layer F.Fab) (width 0.1)) + (pad 2 smd roundrect (at 0.485 0 90) (size 0.59 0.64) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 2 GND)) + (pad 1 smd roundrect (at -0.485 0 90) (size 0.59 0.64) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 3 "Net-(C2-Pad1)")) + (model ${KISYS3DMOD}/Capacitor_SMD.3dshapes/C_0402_1005Metric.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Connector_JST:JST_JWPF_B02B-JWPF-SK-R_1x02_P2.00mm_Vertical (layer F.Cu) (tedit 5B772B89) (tstamp 5CA7282D) + (at 154.94 80.01) + (descr "JST JWPF series connector, B02B-JWPF-SK-R (http://www.jst-mfg.com/product/pdf/eng/eJWPF1.pdf), generated with kicad-footprint-generator") + (tags "connector JST JWPF side entry") + (path /5CA71704/5CA714F2) + (fp_text reference P1 (at -1.35 -3.7) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value CONN_01X02 (at -1.35 5.7) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_arc (start 1.7 -1.5) (end 1.7 -2.5) (angle 90) (layer F.Fab) (width 0.1)) + (fp_arc (start 1.7 3.5) (end 2.7 3.5) (angle 90) (layer F.Fab) (width 0.1)) + (fp_arc (start 1.81 -1.61) (end 1.81 -2.61) (angle 90) (layer F.SilkS) (width 0.12)) + (fp_arc (start 1.81 3.61) (end 2.81 3.61) (angle 90) (layer F.SilkS) (width 0.12)) + (fp_line (start -5.9 -3) (end -5.9 5) (layer F.CrtYd) (width 0.05)) + (fp_line (start -5.9 5) (end 3.2 5) (layer F.CrtYd) (width 0.05)) + (fp_line (start 3.2 5) (end 3.2 -3) (layer F.CrtYd) (width 0.05)) + (fp_line (start 3.2 -3) (end -5.9 -3) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.7 -2.5) (end -5.4 -2.5) (layer F.Fab) (width 0.1)) + (fp_line (start -5.4 -2.5) (end -5.4 4.5) (layer F.Fab) (width 0.1)) + (fp_line (start -5.4 4.5) (end 1.7 4.5) (layer F.Fab) (width 0.1)) + (fp_line (start 2.7 -1.5) (end 2.7 3.5) (layer F.Fab) (width 0.1)) + (fp_line (start 1.81 -2.61) (end -5.51 -2.61) (layer F.SilkS) (width 0.12)) + (fp_line (start -5.51 -2.61) (end -5.51 4.61) (layer F.SilkS) (width 0.12)) + (fp_line (start -5.51 4.61) (end 1.81 4.61) (layer F.SilkS) (width 0.12)) + (fp_line (start 2.81 -1.61) (end 2.81 3.61) (layer F.SilkS) (width 0.12)) + (fp_line (start -5.75 -1.35) (end -5.75 -2.85) (layer F.SilkS) (width 0.12)) + (fp_line (start -5.75 -2.85) (end -4.25 -2.85) (layer F.SilkS) (width 0.12)) + (fp_line (start -0.375 -1.9) (end 0.375 -1.9) (layer F.Fab) (width 0.1)) + (fp_line (start 0.375 -1.9) (end 0 -1.15) (layer F.Fab) (width 0.1)) + (fp_line (start 0 -1.15) (end -0.375 -1.9) (layer F.Fab) (width 0.1)) + (fp_text user %R (at -4.7 1 90) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (pad 1 thru_hole roundrect (at 0 0) (size 2 1.3) (drill 1) (layers *.Cu *.Mask) (roundrect_rratio 0.192308) + (net 2 GND)) + (pad 2 thru_hole oval (at 0 2) (size 2 1.3) (drill 1) (layers *.Cu *.Mask) + (net 1 /Power/VCC)) + (pad "" np_thru_hole circle (at -1.5 4.05) (size 1.15 1.15) (drill 1.15) (layers *.Cu *.Mask)) + (model ${KISYS3DMOD}/Connector_JST.3dshapes/JST_JWPF_B02B-JWPF-SK-R_1x02_P2.00mm_Vertical.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistor_SMD:R_0402_1005Metric (layer F.Cu) (tedit 5B301BBD) (tstamp 5CA7283C) + (at 167.64 83.82) + (descr "Resistor SMD 0402 (1005 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: http://www.tortai-tech.com/upload/download/2011102023233369053.pdf), generated with kicad-footprint-generator") + (tags resistor) + (path /5CA75BC1/5CA75C86) + (attr smd) + (fp_text reference R1 (at 0 -1.17) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value R (at 0 1.17) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -0.5 0.25) (end -0.5 -0.25) (layer F.Fab) (width 0.1)) + (fp_line (start -0.5 -0.25) (end 0.5 -0.25) (layer F.Fab) (width 0.1)) + (fp_line (start 0.5 -0.25) (end 0.5 0.25) (layer F.Fab) (width 0.1)) + (fp_line (start 0.5 0.25) (end -0.5 0.25) (layer F.Fab) (width 0.1)) + (fp_line (start -0.93 0.47) (end -0.93 -0.47) (layer F.CrtYd) (width 0.05)) + (fp_line (start -0.93 -0.47) (end 0.93 -0.47) (layer F.CrtYd) (width 0.05)) + (fp_line (start 0.93 -0.47) (end 0.93 0.47) (layer F.CrtYd) (width 0.05)) + (fp_line (start 0.93 0.47) (end -0.93 0.47) (layer F.CrtYd) (width 0.05)) + (fp_text user %R (at 0 0) (layer F.Fab) + (effects (font (size 0.25 0.25) (thickness 0.04))) + ) + (pad 1 smd roundrect (at -0.485 0) (size 0.59 0.64) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 1 /Power/VCC)) + (pad 2 smd roundrect (at 0.485 0) (size 0.59 0.64) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 3 "Net-(C2-Pad1)")) + (model ${KISYS3DMOD}/Resistor_SMD.3dshapes/R_0402_1005Metric.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Capacitor_SMD:CP_Elec_3x5.3 (layer F.Cu) (tedit 5B303299) (tstamp 5CA71E81) + (at 177.185001 82.214999 90) + (descr "SMT capacitor, aluminium electrolytic, 3x5.3, Cornell Dubilier Electronics ") + (tags "Capacitor Electrolytic") + (path /5CA75BC1/5CA7214E) + (attr smd) + (fp_text reference C3 (at 0 -2.7 90) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value CP (at 0 2.7 90) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_circle (center 0 0) (end 1.5 0) (layer F.Fab) (width 0.1)) + (fp_line (start 1.65 -1.65) (end 1.65 1.65) (layer F.Fab) (width 0.1)) + (fp_line (start -0.825 -1.65) (end 1.65 -1.65) (layer F.Fab) (width 0.1)) + (fp_line (start -0.825 1.65) (end 1.65 1.65) (layer F.Fab) (width 0.1)) + (fp_line (start -1.65 -0.825) (end -1.65 0.825) (layer F.Fab) (width 0.1)) + (fp_line (start -1.65 -0.825) (end -0.825 -1.65) (layer F.Fab) (width 0.1)) + (fp_line (start -1.65 0.825) (end -0.825 1.65) (layer F.Fab) (width 0.1)) + (fp_line (start -1.110469 -0.8) (end -0.810469 -0.8) (layer F.Fab) (width 0.1)) + (fp_line (start -0.960469 -0.95) (end -0.960469 -0.65) (layer F.Fab) (width 0.1)) + (fp_line (start 1.76 1.76) (end 1.76 1.06) (layer F.SilkS) (width 0.12)) + (fp_line (start 1.76 -1.76) (end 1.76 -1.06) (layer F.SilkS) (width 0.12)) + (fp_line (start -0.870563 -1.76) (end 1.76 -1.76) (layer F.SilkS) (width 0.12)) + (fp_line (start -0.870563 1.76) (end 1.76 1.76) (layer F.SilkS) (width 0.12)) + (fp_line (start -1.570563 -1.06) (end -0.870563 -1.76) (layer F.SilkS) (width 0.12)) + (fp_line (start -1.570563 1.06) (end -0.870563 1.76) (layer F.SilkS) (width 0.12)) + (fp_line (start -2.375 -1.435) (end -2 -1.435) (layer F.SilkS) (width 0.12)) + (fp_line (start -2.1875 -1.6225) (end -2.1875 -1.2475) (layer F.SilkS) (width 0.12)) + (fp_line (start 1.9 -1.9) (end 1.9 -1.05) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.9 -1.05) (end 2.85 -1.05) (layer F.CrtYd) (width 0.05)) + (fp_line (start 2.85 -1.05) (end 2.85 1.05) (layer F.CrtYd) (width 0.05)) + (fp_line (start 2.85 1.05) (end 1.9 1.05) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.9 1.05) (end 1.9 1.9) (layer F.CrtYd) (width 0.05)) + (fp_line (start -0.93 1.9) (end 1.9 1.9) (layer F.CrtYd) (width 0.05)) + (fp_line (start -0.93 -1.9) (end 1.9 -1.9) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.78 1.05) (end -0.93 1.9) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.78 -1.05) (end -0.93 -1.9) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.78 -1.05) (end -2.85 -1.05) (layer F.CrtYd) (width 0.05)) + (fp_line (start -2.85 -1.05) (end -2.85 1.05) (layer F.CrtYd) (width 0.05)) + (fp_line (start -2.85 1.05) (end -1.78 1.05) (layer F.CrtYd) (width 0.05)) + (fp_text user %R (at 0 0 90) (layer F.Fab) + (effects (font (size 0.6 0.6) (thickness 0.09))) + ) + (pad 1 smd rect (at -1.5 0 90) (size 2.2 1.6) (layers F.Cu F.Paste F.Mask) + (net 4 "Net-(C3-Pad1)")) + (pad 2 smd rect (at 1.5 0 90) (size 2.2 1.6) (layers F.Cu F.Paste F.Mask) + (net 5 "Net-(C3-Pad2)")) + (model ${KISYS3DMOD}/Capacitor_SMD.3dshapes/CP_Elec_3x5.3.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Capacitor_SMD:CP_Elec_3x5.3 (layer F.Cu) (tedit 5B303299) (tstamp 5CA71EA5) + (at 177.185001 75.464999 90) + (descr "SMT capacitor, aluminium electrolytic, 3x5.3, Cornell Dubilier Electronics ") + (tags "Capacitor Electrolytic") + (path /5CA75BC1/5CA735B9) + (attr smd) + (fp_text reference C4 (at 0 -2.7 90) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value CP (at 0 2.7 90) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text user %R (at 0 0 90) (layer F.Fab) + (effects (font (size 0.6 0.6) (thickness 0.09))) + ) + (fp_line (start -2.85 1.05) (end -1.78 1.05) (layer F.CrtYd) (width 0.05)) + (fp_line (start -2.85 -1.05) (end -2.85 1.05) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.78 -1.05) (end -2.85 -1.05) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.78 -1.05) (end -0.93 -1.9) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.78 1.05) (end -0.93 1.9) (layer F.CrtYd) (width 0.05)) + (fp_line (start -0.93 -1.9) (end 1.9 -1.9) (layer F.CrtYd) (width 0.05)) + (fp_line (start -0.93 1.9) (end 1.9 1.9) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.9 1.05) (end 1.9 1.9) (layer F.CrtYd) (width 0.05)) + (fp_line (start 2.85 1.05) (end 1.9 1.05) (layer F.CrtYd) (width 0.05)) + (fp_line (start 2.85 -1.05) (end 2.85 1.05) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.9 -1.05) (end 2.85 -1.05) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.9 -1.9) (end 1.9 -1.05) (layer F.CrtYd) (width 0.05)) + (fp_line (start -2.1875 -1.6225) (end -2.1875 -1.2475) (layer F.SilkS) (width 0.12)) + (fp_line (start -2.375 -1.435) (end -2 -1.435) (layer F.SilkS) (width 0.12)) + (fp_line (start -1.570563 1.06) (end -0.870563 1.76) (layer F.SilkS) (width 0.12)) + (fp_line (start -1.570563 -1.06) (end -0.870563 -1.76) (layer F.SilkS) (width 0.12)) + (fp_line (start -0.870563 1.76) (end 1.76 1.76) (layer F.SilkS) (width 0.12)) + (fp_line (start -0.870563 -1.76) (end 1.76 -1.76) (layer F.SilkS) (width 0.12)) + (fp_line (start 1.76 -1.76) (end 1.76 -1.06) (layer F.SilkS) (width 0.12)) + (fp_line (start 1.76 1.76) (end 1.76 1.06) (layer F.SilkS) (width 0.12)) + (fp_line (start -0.960469 -0.95) (end -0.960469 -0.65) (layer F.Fab) (width 0.1)) + (fp_line (start -1.110469 -0.8) (end -0.810469 -0.8) (layer F.Fab) (width 0.1)) + (fp_line (start -1.65 0.825) (end -0.825 1.65) (layer F.Fab) (width 0.1)) + (fp_line (start -1.65 -0.825) (end -0.825 -1.65) (layer F.Fab) (width 0.1)) + (fp_line (start -1.65 -0.825) (end -1.65 0.825) (layer F.Fab) (width 0.1)) + (fp_line (start -0.825 1.65) (end 1.65 1.65) (layer F.Fab) (width 0.1)) + (fp_line (start -0.825 -1.65) (end 1.65 -1.65) (layer F.Fab) (width 0.1)) + (fp_line (start 1.65 -1.65) (end 1.65 1.65) (layer F.Fab) (width 0.1)) + (fp_circle (center 0 0) (end 1.5 0) (layer F.Fab) (width 0.1)) + (pad 2 smd rect (at 1.5 0 90) (size 2.2 1.6) (layers F.Cu F.Paste F.Mask) + (net 5 "Net-(C3-Pad2)")) + (pad 1 smd rect (at -1.5 0 90) (size 2.2 1.6) (layers F.Cu F.Paste F.Mask) + (net 4 "Net-(C3-Pad1)")) + (model ${KISYS3DMOD}/Capacitor_SMD.3dshapes/CP_Elec_3x5.3.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (gr_line (start 187.96 69.85) (end 142.24 69.85) (layer F.SilkS) (width 0.12)) + (gr_line (start 187.96 91.44) (end 187.96 69.85) (layer F.SilkS) (width 0.12)) + (gr_line (start 142.24 91.44) (end 187.96 91.44) (layer F.SilkS) (width 0.12)) + (gr_line (start 142.24 69.85) (end 142.24 91.44) (layer F.SilkS) (width 0.12)) + + (segment (start 167.155 83.37) (end 165.1 81.315) (width 0.25) (layer F.Cu) (net 1)) + (segment (start 167.155 83.82) (end 167.155 83.37) (width 0.25) (layer F.Cu) (net 1)) + (segment (start 165.1 81.315) (end 164.775001 80.990001) (width 0.25) (layer F.Cu) (net 1)) + (segment (start 156.75 82.01) (end 154.94 82.01) (width 0.25) (layer F.Cu) (net 1)) + (segment (start 157.769999 80.990001) (end 156.75 82.01) (width 0.25) (layer F.Cu) (net 1)) + (segment (start 164.775001 80.990001) (end 157.769999 80.990001) (width 0.25) (layer F.Cu) (net 1)) + (segment (start 164.765 80.01) (end 164.775001 80.020001) (width 0.25) (layer F.Cu) (net 2)) + (segment (start 154.94 80.01) (end 164.765 80.01) (width 0.25) (layer F.Cu) (net 2)) + (segment (start 165.260001 79.535001) (end 170.18 79.535001) (width 0.25) (layer F.Cu) (net 2)) + (segment (start 164.775001 80.020001) (end 165.260001 79.535001) (width 0.25) (layer F.Cu) (net 2)) + (segment (start 170.18 81.765) (end 168.125 83.82) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 170.18 80.505001) (end 170.18 81.765) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 177.185001 83.414999) (end 177.185001 83.714999) (width 0.25) (layer F.Cu) (net 4)) + (segment (start 176.06 82.289998) (end 177.185001 83.414999) (width 0.25) (layer F.Cu) (net 4)) + (segment (start 177.185001 78.314999) (end 176.06 79.44) (width 1) (layer F.Cu) (net 4)) + (segment (start 176.06 79.44) (end 176.06 82.289998) (width 0.25) (layer F.Cu) (net 4)) + (segment (start 177.185001 76.964999) (end 177.185001 78.314999) (width 0.25) (layer F.Cu) (net 4)) + +) diff --git a/tests/test_plot/test_preflight.py b/tests/test_plot/test_preflight.py index 692ebc0f1..12560e6d3 100644 --- a/tests/test_plot/test_preflight.py +++ b/tests/test_plot/test_preflight.py @@ -39,6 +39,16 @@ def test_drc(): ctx.clean_up() +def test_drc_filter(): + prj = 'fail-project' + ctx = context.TestContext('DRC_Filter', prj, 'drc_filter', '') + ctx.run() + # Check all outputs are there + ctx.expect_out_file('drc_result.rpt') + ctx.expect_out_file('kiplot_errors.filter') + ctx.clean_up() + + def test_update_xml(): prj = 'bom' ctx = context.TestContext('Update_XML', prj, 'update_xml', '') diff --git a/tests/yaml_samples/drc_filter.kiplot.yaml b/tests/yaml_samples/drc_filter.kiplot.yaml new file mode 100644 index 000000000..b7b9d9fc2 --- /dev/null +++ b/tests/yaml_samples/drc_filter.kiplot.yaml @@ -0,0 +1,15 @@ +# Example KiPlot config file +kiplot: + version: 1 + +preflight: + run_drc: true + filters: + - filter: 'Ignore C3 pad 2 too close to anything' + number: 4 + regex: 'Pad 2 of C3' + - filter: 'Ignore unconnected pad 2 of C4' + number: 2 + regex: 'Pad 2 of C4' + +