app
KiCad - the KiCad Bridge
Public Made by Adomby adom
Reference implementation of the KiCad bridge: multi-instance Python server, forward path via kicad-cli, reverse path via in-process plugin. Most complex of the three bundled bridges.
← Commit history
0.9.284: kicad_set_design_rules: response separates fabRuleViolations (DRC items citing one of the fab's rules by name) from otherViolations, and carries drcSummary; the copper layer count is read per layer entry, not per line, so a one-line (layers ...) block no longer infers 1 layer.
1 file changed
+21−5
handlers/design_rules.py+21−5@@ -176,10 +176,25 @@ def handle_set_design_rules(kicad_info: dict, args: dict) -> dict: except Exception as e: # pylint: disable=broad-except drc = {"success": False, "error": f"DRC did not run: {e}"} out["drc"] = drc- viol = ((drc.get("drc") or {}).get("summary") or {}) if isinstance(drc, dict) else {}- out["_hint"] = (f"Rules staged as {dru_target.name} (KiCad loads <board stem>.kicad_dru automatically; an open PCB editor picks it up on the next DRC run). "- f"DRC ran with them: {json.dumps(viol) if viol else (drc.get('_hint') or drc.get('error') or 'see drc')}"- ). strip()+ data = (drc.get("data") or {}) if isinstance(drc, dict) else {}+ summary = data.get("summary") or {}+ viols = data.get("violations") or []+ # The violations that cite one of the fab's rules by name are the ones+ # this verb exists for; list them separately from the board's own errors+ # (a missing outline, dangling tracks) so the caller sees the fab's+ # limits applied, measured (2026-09-03 on ConfRoomROG: "Track width+ # (rule 'min-track-width' min width 0.1000 mm; actual 0.0500 mm)").+ from_rules = [v for v in viols if "(rule '" in str(v.get("description") or "")]+ out["drcSummary"] = summary+ out["fabRuleViolations"] = [{"type": v.get("type"), "severity": v.get("severity"),+ "description": v.get("description")} for v in from_rules[:40]]+ out["otherViolations"] = len(viols) - len(from_rules)+ if drc.get("success") is False and not viols:+ out["_hint"] = f"Rules staged as {dru_target.name}, but DRC did not run: {drc.get('error') or drc.get('_hint')}"+ else:+ out["_hint"] = (f"Rules staged as {dru_target.name} (KiCad loads <board stem>.kicad_dru automatically; an open PCB editor applies it on its next DRC run). "+ f"DRC with these rules: {len(from_rules)} violation(s) cite the fab's rules, {out['otherViolations']} other; "+ f"totals {json.dumps(summary) if summary else 'n/a'}.") else: out["_hint"] = f"Rules staged as {dru_target.name}. Run kicad_lint_board or kicad_run_drc on the board to apply them." return out@@ -203,7 +218,8 @@ def _board_copper_layers(board_path: Path) -> int | None: break j += 1 block = head[i:j]- n = sum(1 for ln in block.splitlines() if '.Cu"' in ln and ("signal" in ln or "power" in ln or "mixed" in ln or "jumper" in ln))+ import re+ n = len(re.findall(r'\(\d+\s+"[^"]+\.Cu"\s+(?:signal|power|mixed|jumper)', block)) return n or None except Exception: # pylint: disable=broad-except return None