Allow pin labels in loop definitions (fixes #432)
Some checks are pending
Create Examples / build (ubuntu-22.04, 3.7) (push) Waiting to run
Create Examples / build (ubuntu-22.04, 3.8) (push) Waiting to run
Create Examples / build (ubuntu-latest, 3.10) (push) Waiting to run
Create Examples / build (ubuntu-latest, 3.11) (push) Waiting to run
Create Examples / build (ubuntu-latest, 3.12) (push) Waiting to run
Create Examples / build (ubuntu-latest, 3.9) (push) Waiting to run

Loops now accept pin labels (from pinlabels) in addition to pin
numbers, matching the behavior of the connections section. Labels
are resolved to pin numbers during __post_init__ via the new
Connector.resolve_pin() method, which handles ambiguity checking.
This commit is contained in:
Ryan Malloy 2026-02-13 00:42:09 -07:00
parent e4fe099f8c
commit f5c1b1c87f

View File

@ -203,23 +203,55 @@ class Connector:
# hide pincount for simple (1 pin) connectors by default # hide pincount for simple (1 pin) connectors by default
self.show_pincount = self.style != "simple" self.show_pincount = self.style != "simple"
for loop in self.loops: for i, loop in enumerate(self.loops):
# TODO: allow using pin labels in addition to pin numbers, just like when defining regular connections
# TODO: include properties of wire used to create the loop # TODO: include properties of wire used to create the loop
if len(loop) != 2: if len(loop) != 2:
raise Exception("Loops must be between exactly two pins!") raise Exception("Loops must be between exactly two pins!")
resolved = []
for pin in loop: for pin in loop:
if pin not in self.pins: pin = self.resolve_pin(pin)
raise Exception( resolved.append(pin)
f'Unknown loop pin "{pin}" for connector "{self.name}"!'
)
# Make sure loop connected pins are not hidden. # Make sure loop connected pins are not hidden.
self.activate_pin(pin, None) self.activate_pin(pin, None)
self.loops[i] = resolved
for i, item in enumerate(self.additional_components): for i, item in enumerate(self.additional_components):
if isinstance(item, dict): if isinstance(item, dict):
self.additional_components[i] = AdditionalComponent(**item) self.additional_components[i] = AdditionalComponent(**item)
def resolve_pin(self, pin: Pin) -> Pin:
"""Resolve a pin identifier to its canonical pin number.
Accepts pin numbers (from self.pins) or pin labels (from
self.pinlabels). Raises if ambiguous or not found.
"""
in_pins = pin in self.pins
in_labels = pin in self.pinlabels if self.pinlabels else False
if in_pins and in_labels:
# present in both lists — check for ambiguity
if self.pins.index(pin) != self.pinlabels.index(pin):
raise Exception(
f'"{pin}" in connector "{self.name}" exists in both '
f"pins and pinlabels at different positions."
)
return pin # same position, no ambiguity
if in_labels:
if self.pinlabels.count(pin) > 1:
raise Exception(
f'Pin label "{pin}" in connector "{self.name}" '
f"is defined more than once."
)
return self.pins[self.pinlabels.index(pin)]
if in_pins:
return pin
raise Exception(
f'Unknown pin "{pin}" for connector "{self.name}"!'
)
def activate_pin(self, pin: Pin, side: Side) -> None: def activate_pin(self, pin: Pin, side: Side) -> None:
self.visible_pins[pin] = True self.visible_pins[pin] = True
if side == Side.LEFT: if side == Side.LEFT: