← 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.

John Lauer ·7a49187385 ·1mo ago ·parent 40ebe61
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