skidl.tools.inject_labels module¶
Post-process a KiCad 8/9 schematic (.kicad_sch) generated by SKiDL to add global net labels at each pin position.
SKiDL’s generate_schematic() produces hierarchical schematics with
correct symbols and netlists, but without visible net labels on the pins.
This module reads the companion .net netlist, resolves pin-to-net
mappings, and injects (global_label ...) S-expressions at the world
coordinates of every connected pin.
- Features:
Parses KiCad S-expression schematics and netlists (no external deps)
Handles symbol rotation, mirror, and multi-unit sub-symbols
Deduplicates labels at identical positions (e.g. stacked USB-C GND pins)
Orients labels to point away from the symbol body
Converts auto-generated net names (
N$1,Net-(R1-1)) to readable form
Usage as CLI:
python -m skidl.tools.inject_labels schematic.kicad_sch netlist.net output.kicad_sch
Usage from Python:
from skidl.tools.inject_labels import inject_labels
inject_labels("power1.kicad_sch", "circuit.net", "power1_labeled.kicad_sch")
- skidl.tools.inject_labels.extract_instances(tree: list) list[dict][source]¶
Extract all
(symbol (lib_id ...) (at SX SY SROT) ...)instances.Returns a list of dicts with keys:
lib_id,ref,sx,sy,rotation,mirror_x,mirror_y.
- skidl.tools.inject_labels.extract_lib_pins(tree: list) dict[str, list[dict]][source]¶
Parse the
lib_symbolssection of the schematic.Returns
{lib_id: [pin_dict, ...]}where each pin_dict has keys:number,name,x,y,angle.Pins live in sub-symbols named
SYMBOLNAME_N_1(unit sub-symbols). We collect pins from all unit sub-symbols.
- skidl.tools.inject_labels.inject_labels(sch_path: str, net_path: str, out_path: str) int[source]¶
Read schematic + netlist, inject global labels at pin positions.
- Parameters:
sch_path – Path to a
.kicad_schfile (input).net_path – Path to a
.netnetlist file.out_path – Path for the labeled
.kicad_schfile (output).
- Returns:
Number of labels injected.
- skidl.tools.inject_labels.is_unnamed_net(name: str) bool[source]¶
Return True if the net name looks auto-generated / unnamed.
- skidl.tools.inject_labels.label_angle_from_position(sx: float, sy: float, wx: float, wy: float) float[source]¶
Compute label angle so it extends AWAY from the symbol body.
Returns one of 0, 90, 180, 270 (KiCad label angle convention).
- skidl.tools.inject_labels.make_global_label_sexp(net_name: str, x: float, y: float, angle: float) str[source]¶
Return a KiCad 8/9
(global_label ...)S-expression string.
- skidl.tools.inject_labels.parse_netlist(path: str) dict[tuple[str, str], str][source]¶
Return a mapping of
(component_ref, pin_number) -> net_namefrom a KiCad .net netlist file.
- skidl.tools.inject_labels.parse_sexp(text: str) list[source]¶
Parse a KiCad S-expression string into nested Python lists.
Atoms are kept as strings. Quoted strings have their quotes stripped. Numbers are NOT converted – everything stays as
strso we can round-trip without floating-point surprises.
- skidl.tools.inject_labels.pin_world_pos(sx: float, sy: float, rotation: float, mirror_x: bool, mirror_y: bool, px: float, py: float) tuple[float, float][source]¶
Transform a pin’s local offset to world coordinates.
Accounts for symbol placement, rotation (degrees), and mirror flags. KiCad Y-down coordinate system: positive rotation is clockwise.
