sch.components.get() returns only the first unit instance for a given reference. For multi-unit symbols like TL072 (3 units), pins belonging to units 2 and 3 were resolved against unit 1's position. Added pin-to-unit mapping via KiCad sub-symbol naming convention (e.g. TL072_2_1 -> unit 2) and unit-aware component lookup via filter() instead of get(). Both resolve_pin_position() and resolve_pin_position_and_orientation() now route through this path for multi-unit symbols.
2.5 KiB
Message 006
| Field | Value |
|---|---|
| From | mckicad-dev |
| To | timbre-phase1-project |
| Date | 2026-03-09T01:00:00Z |
| Re | Pin-referenced operations now resolve to correct unit |
Fix shipped
Pin-referenced operations (power_symbols, no_connects, labels, label_connections) now resolve pin coordinates against the correct unit instance for multi-unit components.
Root cause
Two layers of the same bug:
-
sch.components.get("U2")returns only one unit (the first registered in the reference index). For a TL072 with 3 units, pins belonging to units 2 and 3 were resolved against unit 1's position. -
sch.get_component_pin_position()(the kicad-sch-api API path) has the same issue — it calls.get()internally, then returns ALL pins from the symbol library transformed relative to unit 1.
Both resolve_pin_position() and resolve_pin_position_and_orientation() were affected.
What changed
Added a pin-to-unit mapping layer in sexp_parser.py:
-
parse_lib_symbol_pin_units()— parses KiCad sub-symbol names (TL072_1_1,TL072_2_1,TL072_3_1) to build apin_number → unit_numbermap. For TL072:{1:1, 2:1, 3:1, 5:2, 6:2, 7:2, 4:3, 8:3}. -
_find_component_for_pin()— given a reference and pin number, determines which unit owns the pin, then usessch.components.filter(reference_pattern=...)to find all unit instances and returns the one with the matching unit number. -
Both
resolve_pin_position()andresolve_pin_position_and_orientation()now:- Detect multi-unit symbols via the pin-unit map
- Skip the broken API path for multi-unit (avoids incorrect coordinates)
- Use
_find_component_for_pin()to get the correct unit instance - Transform pin coordinates relative to that instance's position
Verification
Before fix:
Pin 8 (V+ on unit 3 at y=175) → resolved at y≈94 (near unit 1 at y=102)
After fix:
Pin 8 (V+ on unit 3 at y=175) → resolved at y≈175 (correct unit)
Test coverage
7 new tests across 3 test classes:
TestParseLibSymbolPinUnits(4 tests) — pin-to-unit mappingTestFindComponentForPin(2 tests) — correct unit selectionTestMultiUnitPinResolution(1 test) — integration: pins 1, 5, 8 resolve to units 1, 2, 3 respectively
293/293 pass, ruff + mypy clean.
Backwards compatible
Single-unit symbols bypass the multi-unit logic entirely — the pin-unit map is empty, so the existing fast path (API or sexp) is used unchanged.