fix(add_mounting_hole): set FPID and restrict NPTH pad to mask layers (#154)

`BoardOutlineCommands.add_mounting_hole` produced footprints with an empty
library:name id (`(footprint "" ...)` in the .kicad_pcb), which KiCad's GUI
Move tool refuses to select — users couldn't drag the resulting MHs in the
editor. It also emitted the pad with the default `*.Cu` + `*.Mask` LSET on
NPTHs; with `padDiameter > diameter` that creates phantom copper annular
rings on every Cu layer and trips clearance DRC against neighbouring nets.

Repro: call `add_mounting_hole` with `position={x:117,y:84.5,unit:"mm"},
diameter:3.2, padDiameter:3.5`. The resulting MH is unselectable and DRC
reports phantom F.Cu pad shorts to neighbouring component pads.

Changes:

- Set a real FPID via `module.SetFPID(pcbnew.LIB_ID(lib, name))`. Default
  is `MountingHole:MountingHole_<diameter:g>mm` (e.g. 3.2 → 3.2mm); a new
  optional `footprintLibId` parameter overrides.
- For NPTH (the default `plated:false`), restrict the pad's LSET to
  `F.Mask` + `B.Mask` only. PTH path is unchanged — the default Cu+Mask
  LSET is correct there.
- Update the schema in `tool_schemas.py`: previously advertised
  `x`/`y`/`diameter` at the top level, but the impl reads
  `position={x,y,unit}`, `padDiameter`, `plated`. Schema now matches the
  implementation and exposes the new `footprintLibId` param.
- New `tests/test_add_mounting_hole.py` regression suite (7 tests) asserting
  SetFPID is invoked with non-empty lib:name (default + override forms),
  NPTH SetLayerSet excludes any Cu layer, and PTH does not call
  SetLayerSet (preserves default Cu+Mask).
This commit is contained in:
Matthew Runo
2026-05-18 11:05:10 -07:00
committed by GitHub
parent ff6ae63b8c
commit 4740013d24
3 changed files with 249 additions and 5 deletions

View File

@@ -266,19 +266,46 @@ BOARD_TOOLS = [
{
"name": "add_mounting_hole",
"title": "Add Mounting Hole",
"description": "Adds a mounting hole (non-plated through hole) at the specified position with given diameter.",
"description": "Adds a mounting hole at the specified position with given diameter. Defaults to non-plated (NPTH) with mask-only pad layers; set plated=true for a PTH with copper pad.",
"inputSchema": {
"type": "object",
"properties": {
"x": {"type": "number", "description": "X coordinate in millimeters"},
"y": {"type": "number", "description": "Y coordinate in millimeters"},
"position": {
"type": "object",
"description": "Position of the mounting hole",
"properties": {
"x": {"type": "number", "description": "X coordinate"},
"y": {"type": "number", "description": "Y coordinate"},
"unit": {
"type": "string",
"enum": ["mm", "inch"],
"default": "mm",
"description": "Unit for x/y (default mm)",
},
},
"required": ["x", "y"],
},
"diameter": {
"type": "number",
"description": "Hole diameter in millimeters",
"description": "Hole (drill) diameter in millimeters",
"minimum": 0.1,
},
"padDiameter": {
"type": "number",
"description": "Pad diameter in millimeters (defaults to diameter + 1mm). For NPTH this only affects the solder-mask opening, not copper.",
"minimum": 0.1,
},
"plated": {
"type": "boolean",
"default": False,
"description": "True for plated through-hole (PTH) with copper pad; false (default) for NPTH (mask only).",
},
"footprintLibId": {
"type": "string",
"description": "Optional library:name FPID (e.g. 'MountingHole:MountingHole_3.2mm'). Defaults to MountingHole:MountingHole_<diameter>mm. A non-empty FPID is required for the footprint to be selectable in KiCad's GUI Move tool.",
},
},
"required": ["x", "y", "diameter"],
"required": ["position", "diameter"],
},
},
{