Skip to content

Commit

Permalink
Added support for cables to have extra components
Browse files Browse the repository at this point in the history
  • Loading branch information
Tyler-Ward committed Jul 21, 2020
1 parent d7922ca commit 158bb49
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 19 deletions.
1 change: 1 addition & 0 deletions src/wireviz/DataClasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ class Cable:
show_name: bool = True
show_wirecount: bool = True
ignore_in_bom: bool = False
additional_components: List[Any] = None

def __post_init__(self):

Expand Down
123 changes: 104 additions & 19 deletions src/wireviz/Harness.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,25 +113,25 @@ def create_graph(self) -> Graph:
'<!-- connector table -->']
if connector.additional_components is not None:
rows.append(["Additional components"])
for extra in connector.additional_components:
if 'qty' in extra:
if isinstance(extra['qty'], int) or isinstance(extra['qty'], float):
qty = extra['qty']
else: # check for special quantities
if extra['qty'] == 'pincount':
qty = connector.pincount
elif extra['qty'] == 'connectioncount':
qty = sum(1 for value in connector.visible_pins.values() if value is True)
else:
raise ValueError('invalid aty parameter')
else:
qty = 1
rows.append([extra["type"], qty])
rows.append([extra["manufacturer"],
f'MPN: {extra["manufacturer_part_number"]}' if "manufacturer_part_number" in extra else None,
f'IPN: {extra["internal_part_number"]}' if "internal_part_number" in extra else None],)
rows.append([html_line_breaks(connector.notes)])
html = nested_html_table(rows)
for extra in connector.additional_components:
if 'qty' in extra:
if isinstance(extra['qty'], int) or isinstance(extra['qty'], float):
qty = extra['qty']
else: # check for special quantities
if extra['qty'] == 'pincount':
qty = connector.pincount
elif extra['qty'] == 'connectioncount':
qty = sum(1 for value in connector.visible_pins.values() if value is True)
else:
raise ValueError('invalid aty parameter')
else:
qty = 1
rows.append([extra["type"], qty])
rows.append([extra["manufacturer"],
f'MPN: {extra["manufacturer_part_number"]}' if "manufacturer_part_number" in extra else None,
f'IPN: {extra["internal_part_number"]}' if "internal_part_number" in extra else None],)
rows.append([html_line_breaks(connector.notes)])
html = nested_html_table(rows)

pinouts = []
for pinnumber, pinname in zip(connector.pinnumbers, connector.pinout):
Expand Down Expand Up @@ -263,6 +263,44 @@ def create_graph(self) -> Graph:
html = f'{html}</table>' # conductor table

html = f'{html}</td></tr>' # main table

if cable.additional_components is not None:
html = f'{html}<tr><td cellpadding="3" border="1" balign="left">Additional components</td></tr>' # notes table
for extra in cable.additional_components:
if 'qty' in extra:
if isinstance(extra['qty'], int) or isinstance(extra['qty'], float):
qty = extra['qty']
else: # check for special quantities
if extra['qty'] == 'wirecount':
qty = cable.wirecount
elif extra['qty'] == 'terminations':
qty = len(cable.connections)
elif extra['qty'] == 'length':
qty = cable.length
elif extra['qty'] == 'total_length':
qty = cable.length * cable.wirecount
else:
raise ValueError('invalid aty parameter {}'.format(extra["qty"]))
else:
qty = 1

html = f'{html}<tr><td colspan="{len(attributes)}" border="1" cellpadding="0"><table border="0" cellspacing="0" cellpadding="3" cellborder="1"><tr>'
html = f'{html}<td sides="R">{extra["type"]}</td>'
html = f'{html}<td border="0">{qty}</td>'
html = f'{html}</tr></table></td></tr>'

identification = [extra.get("manufacturer", None),
f'MPN: {extra["manufacturer_part_number"]}' if "manufacturer_part_number" in extra else None,
f'IPN: {extra["internal_part_number"]}' if "internal_part_number" in extra else None]
identification = list(filter(None, identification))
if(len(identification) > 0): # print an identification row if values specified
html = f'{html}<tr><td colspan="{len(attributes)}" border="1" cellpadding="0"><table border="0" cellspacing="0" cellpadding="3" cellborder="1"><tr>'
for attrib in identification[0:-1]:
html = f'{html}<td sides="R">{attrib}</td>' # all columns except last have a border on the right (sides="R")
if len(identification) > 0:
html = f'{html}<td border="0">{identification[-1]}</td>' # last column has no border on the right because the enclosing table borders it
html = f'{html}</tr></table></td></tr>' # end identification row

if cable.notes:
html = f'{html}<tr><td cellpadding="3" balign="left">{html_line_breaks(cable.notes)}</td></tr>' # notes table
html = f'{html}<tr><td>&nbsp;</td></tr>' # spacer at the end
Expand Down Expand Up @@ -363,6 +401,7 @@ def bom(self):
bom_connectors = []
bom_connectors_extra = []
bom_cables = []
bom_cables_extra = []
bom_extra = []
# connectors
connector_group = lambda c: (c.type, c.subtype, c.pincount, c.manufacturer, c.manufacturer_part_number, c.internal_part_number)
Expand Down Expand Up @@ -471,6 +510,52 @@ def bom(self):
bom_cables = sorted(bom_cables, key=lambda k: k['item']) # sort list of dicts by their values (https://stackoverflow.com/a/73050)
bom.extend(bom_cables)

cables_extra = []
for cable in self.cables.values():
if cable.additional_components:
for part in cable.additional_components:
if 'qty' in part:
if isinstance(part['qty'], int) or isinstance(part['qty'], float):
qty = part['qty']
else: # check for special quantities
if part['qty'] == 'wirecount':
qty = cable.wirecount
elif part['qty'] == 'terminations':
qty = len(cable.connections)
elif part['qty'] == 'length':
qty = cable.length
elif part['qty'] == 'total_length':
qty = cable.length * cable.wirecount
else:
raise ValueError('invalid aty parameter')
else:
qty = 1
cables_extra.append(
{
'type': part.get('type', None),
'qty': qty,
'unit': part.get('unit', None),
'manufacturer': part.get('manufacturer', None),
'manufacturer part number': part.get('manufacturer_part_number', None),
'internal part number': part.get('internal_part_number', None),
'designator': connector.name
}
)
cables_extra_group = lambda ce: (ce['type'], ce['qty'], ce['unit'], ce['manufacturer'], ce['manufacturer part number'], ce['internal part number'])
for group in Counter([connector_extra_group(v) for v in cables_extra]):
items = [v for v in cables_extra if connector_extra_group(v) == group]
shared = items[0]
designators = [i['designator'] for i in items]
designators = list(dict.fromkeys(designators)) # remove duplicates
designators.sort()
total_qty = sum(i['qty'] for i in items)

item = {'item': shared['type'], 'qty': round(total_qty, 3), 'unit': shared['unit'], 'designators': designators,
'manufacturer': shared['manufacturer'], 'manufacturer part number': shared['manufacturer part number'], 'internal part number': shared['internal part number']}
bom_cables_extra.append(item)
bom_cables_extra = sorted(bom_cables_extra, key=lambda k: k['item']) # sort list of dicts by their values (https://stackoverflow.com/a/73050)
bom.extend(bom_cables_extra)

for item in self.additional_bom_items:
name = item['description'] if item.get('description', None) else ''
if isinstance(item.get('designators', None), List):
Expand Down

0 comments on commit 158bb49

Please sign in to comment.