7
7
from wireviz .wv_helper import int2tuple , aspect_ratio
8
8
from wireviz import wv_colors
9
9
10
+ # Literal type aliases below are commented to avoid requiring python 3.8
11
+ ConnectorMultiplier = str # = Literal['pincount', 'populated']
12
+ CableMultiplier = str # = Literal['wirecount', 'terminations', 'length', 'total_length']
13
+
10
14
11
15
@dataclass
12
16
class Image :
@@ -43,6 +47,21 @@ def __post_init__(self, gv_dir):
43
47
if self .width :
44
48
self .height = self .width / aspect_ratio (gv_dir .joinpath (self .src ))
45
49
50
+ @dataclass
51
+ class AdditionalComponent :
52
+ type : str
53
+ subtype : Optional [str ] = None
54
+ manufacturer : Optional [str ] = None
55
+ mpn : Optional [str ] = None
56
+ pn : Optional [str ] = None
57
+ qty : float = 1
58
+ unit : Optional [str ] = None
59
+ qty_multiplier : Union [ConnectorMultiplier , CableMultiplier , None ] = None
60
+
61
+ @property
62
+ def description (self ) -> str :
63
+ return self .type .rstrip () + (f', { self .subtype .rstrip ()} ' if self .subtype else '' )
64
+
46
65
47
66
@dataclass
48
67
class Connector :
@@ -65,6 +84,8 @@ class Connector:
65
84
hide_disconnected_pins : bool = False
66
85
autogenerate : bool = False
67
86
loops : List [Any ] = field (default_factory = list )
87
+ ignore_in_bom : bool = False
88
+ additional_components : List [AdditionalComponent ] = field (default_factory = list )
68
89
69
90
def __post_init__ (self ):
70
91
@@ -114,9 +135,23 @@ def __post_init__(self):
114
135
if len (loop ) != 2 :
115
136
raise Exception ('Loops must be between exactly two pins!' )
116
137
138
+ for i , item in enumerate (self .additional_components ):
139
+ if isinstance (item , dict ):
140
+ self .additional_components [i ] = AdditionalComponent (** item )
141
+
117
142
def activate_pin (self , pin ):
118
143
self .visible_pins [pin ] = True
119
144
145
+ def get_qty_multiplier (self , qty_multiplier : Optional [ConnectorMultiplier ]) -> int :
146
+ if not qty_multiplier :
147
+ return 1
148
+ elif qty_multiplier == 'pincount' :
149
+ return self .pincount
150
+ elif qty_multiplier == 'populated' :
151
+ return sum (self .visible_pins .values ())
152
+ else :
153
+ raise ValueError (f'invalid qty multiplier parameter for connector { qty_multiplier } ' )
154
+
120
155
121
156
@dataclass
122
157
class Cable :
@@ -139,6 +174,8 @@ class Cable:
139
174
color_code : Optional [str ] = None
140
175
show_name : bool = True
141
176
show_wirecount : bool = True
177
+ ignore_in_bom : bool = False
178
+ additional_components : List [AdditionalComponent ] = field (default_factory = list )
142
179
143
180
def __post_init__ (self ):
144
181
@@ -196,6 +233,9 @@ def __post_init__(self):
196
233
else :
197
234
raise Exception ('lists of part data are only supported for bundles' )
198
235
236
+ for i , item in enumerate (self .additional_components ):
237
+ if isinstance (item , dict ):
238
+ self .additional_components [i ] = AdditionalComponent (** item )
199
239
200
240
def connect (self , from_name , from_pin , via_pin , to_name , to_pin ):
201
241
from_pin = int2tuple (from_pin )
@@ -207,6 +247,20 @@ def connect(self, from_name, from_pin, via_pin, to_name, to_pin):
207
247
# self.connections.append((from_name, from_pin[i], via_pin[i], to_name, to_pin[i]))
208
248
self .connections .append (Connection (from_name , from_pin [i ], via_pin [i ], to_name , to_pin [i ]))
209
249
250
+ def get_qty_multiplier (self , qty_multiplier : Optional [CableMultiplier ]) -> float :
251
+ if not qty_multiplier :
252
+ return 1
253
+ elif qty_multiplier == 'wirecount' :
254
+ return self .wirecount
255
+ elif qty_multiplier == 'terminations' :
256
+ return len (self .connections )
257
+ elif qty_multiplier == 'length' :
258
+ return self .length
259
+ elif qty_multiplier == 'total_length' :
260
+ return self .length * self .wirecount
261
+ else :
262
+ raise ValueError (f'invalid qty multiplier parameter for cable { qty_multiplier } ' )
263
+
210
264
211
265
@dataclass
212
266
class Connection :
0 commit comments