Skip to content

Commit 4f2c569

Browse files
brettjforsythclaude
andcommitted
Merge upstream PR wireviz#357: Add optional per-node tweak with name placeholder
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 parents b05407a + a3b0679 commit 4f2c569

3 files changed

Lines changed: 57 additions & 0 deletions

File tree

docs/syntax.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ tweak: # optional tweaking of .gv output
8585
# loops
8686
loops: <List> # every list item is itself a list of exactly two pins
8787
# on the connector that are to be shorted
88+
89+
# optional tweaking of .gv output executed for each instance of this connector
90+
tweak: # see below
91+
8892
```
8993

9094
## Cable attributes
@@ -148,6 +152,9 @@ tweak: # optional tweaking of .gv output
148152
show_wirecount: <bool> # defaults to true
149153
show_wirenumbers: <bool> # defaults to true for cables; false for bundles
150154

155+
# optional tweaking of .gv output executed for each instance of this cable
156+
tweak: # see below
157+
151158
```
152159

153160
## Connection sets
@@ -452,6 +459,13 @@ Alternatively items can be added to just the BOM by putting them in the section
452459
# This feature is experimental and might change
453460
# or be removed in future versions.
454461
462+
placeholder: <str> # Substring to be replaced with node name
463+
# An empty string as placeholder disable replacements.
464+
# When placeholder is absent, the global placeholder is used.
465+
# For tweak sections in connectors and cables, all substrings
466+
# matching the placeholder text will be replaced with the name
467+
# of connector/cable in all override and append entries.
468+
455469
override: # dict of .gv entries to override
456470
# Each entry is identified by its leading string
457471
# in lines beginning with a TAB character.

src/wireviz/DataClasses.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ def __post_init__(self):
7272

7373
@dataclass
7474
class Tweak:
75+
placeholder: Optional[PlainText] = None
7576
override: Optional[Dict[Designator, Dict[str, Optional[str]]]] = None
7677
append: Union[str, List[str], None] = None
7778

@@ -163,10 +164,13 @@ class Connector:
163164
loops: List[List[Pin]] = field(default_factory=list)
164165
ignore_in_bom: bool = False
165166
additional_components: List[AdditionalComponent] = field(default_factory=list)
167+
tweak: Optional[Tweak] = None
166168

167169
def __post_init__(self) -> None:
168170
if isinstance(self.image, dict):
169171
self.image = Image(**self.image)
172+
if self.tweak is not None:
173+
self.tweak = Tweak(**self.tweak)
170174

171175
self.ports_left = False
172176
self.ports_right = False
@@ -328,10 +332,13 @@ class Cable:
328332
show_wirenumbers: Optional[bool] = None
329333
ignore_in_bom: bool = False
330334
additional_components: List[AdditionalComponent] = field(default_factory=list)
335+
tweak: Optional[Tweak] = None
331336

332337
def __post_init__(self) -> None:
333338
if isinstance(self.image, dict):
334339
self.image = Image(**self.image)
340+
if self.tweak is not None:
341+
self.tweak = Tweak(**self.tweak)
335342

336343
if isinstance(self.gauge, str): # gauge and unit specified
337344
try:

src/wireviz/Harness.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
component_table_entry,
3030
generate_bom,
3131
get_additional_component_table,
32+
make_list,
3233
pn_info_string,
3334
)
3435
from wireviz.wv_colors import get_color_hex, translate_color
@@ -80,12 +81,47 @@ def __post_init__(self):
8081
self._bom = [] # Internal Cache for generated bom
8182
self.additional_bom_items = []
8283

84+
def extend_tweak(self, node: Union[Connector, Cable]) -> None:
85+
"""Extend self.tweak with node.tweak after replacing placeholders."""
86+
if node.tweak:
87+
ph = node.tweak.placeholder
88+
# An empty string is a legal value to avoid the global placeholder
89+
if ph is None: # This must therefore be a test for None!
90+
ph = self.tweak.placeholder # Use the global placeholder
91+
# Create function rph() to replace any placeholder with node name
92+
rph = (
93+
(lambda s: s.replace(ph, node.name) if isinstance(s, str) else s)
94+
if ph
95+
else lambda s: s # No-change-lambda if no placeholder
96+
)
97+
n_override = node.tweak.override or {}
98+
s_override = self.tweak.override or {}
99+
for id, n_dict in n_override.items():
100+
id = rph(id)
101+
s_dict = s_override.get(id, {})
102+
for k, v in n_dict.items():
103+
k, v = rph(k), rph(v)
104+
if k in s_dict and v != s_dict[k]:
105+
raise ValueError(
106+
f"{node.name}.tweak.override.{id}.{k}={v!r} conflicts"
107+
f" with tweak.override.{id}.{k}={s_dict[k]!r}"
108+
)
109+
s_dict[k] = v
110+
s_override[id] = s_dict # Never empty, because nothing deleted
111+
self.tweak.override = s_override or None
112+
self.tweak.append = (
113+
make_list(self.tweak.append)
114+
+ [rph(v) for v in make_list(node.tweak.append)]
115+
) or None
116+
83117
def add_connector(self, name: str, *args, **kwargs) -> None:
84118
check_old(f"Connector '{name}'", OLD_CONNECTOR_ATTR, kwargs)
85119
self.connectors[name] = Connector(name, *args, **kwargs)
120+
self.extend_tweak(self.connectors[name])
86121

87122
def add_cable(self, name: str, *args, **kwargs) -> None:
88123
self.cables[name] = Cable(name, *args, **kwargs)
124+
self.extend_tweak(self.cables[name])
89125

90126
def add_mate_pin(self, from_name, from_pin, to_name, to_pin, arrow_type) -> None:
91127
self.mates.append(MatePin(from_name, from_pin, to_name, to_pin, arrow_type))

0 commit comments

Comments
 (0)