Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/short bom names #121

Merged
merged 6 commits into from
Jul 26, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/wireviz/DataClasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
class Connector:
name: str
manufacturer: Optional[str] = None
manufacturer_part_number: Optional[str] = None
internal_part_number: Optional[str] = None
mpn: Optional[str] = None
pn: Optional[str] = None
style: Optional[str] = None
category: Optional[str] = None
type: Optional[str] = None
Expand Down Expand Up @@ -80,8 +80,8 @@ def activate_pin(self, pin):
class Cable:
name: str
manufacturer: Optional[Union[str, List[str]]] = None
manufacturer_part_number: Optional[Union[str, List[str]]] = None
internal_part_number: Optional[Union[str, List[str]]] = None
mpn: Optional[Union[str, List[str]]] = None
pn: Optional[Union[str, List[str]]] = None
category: Optional[str] = None
type: Optional[str] = None
gauge: Optional[float] = None
Expand Down Expand Up @@ -140,7 +140,7 @@ def __post_init__(self):
self.wirecount = len(self.colors)

# if lists of part numbers are provided check this is a bundle and that it matches the wirecount.
for idfield in [self.manufacturer, self.manufacturer_part_number, self.internal_part_number]:
for idfield in [self.manufacturer, self.mpn, self.pn]:
if isinstance(idfield, list):
if self.category == "bundle":
# check the length
Expand Down
46 changes: 23 additions & 23 deletions src/wireviz/Harness.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
from wireviz.wv_colors import get_color_hex
from wireviz.wv_helper import awg_equiv, mm2_equiv, tuplelist2tsv, \
nested_html_table, flatten2d, index_if_list, html_line_breaks, \
graphviz_line_breaks, remove_line_breaks, open_file_read, open_file_write
graphviz_line_breaks, remove_line_breaks, open_file_read, open_file_write, \
manufacturer_info_field
from collections import Counter
from typing import List
from pathlib import Path
Expand Down Expand Up @@ -88,9 +89,8 @@ def create_graph(self) -> Graph:
for key, connector in self.connectors.items():

rows = [[connector.name if connector.show_name else None],
[connector.manufacturer,
f'MPN: {connector.manufacturer_part_number}' if connector.manufacturer_part_number else None,
f'IPN: {connector.internal_part_number}' if connector.internal_part_number else None],
[f'P/N: {connector.pn}' if connector.pn else None,
manufacturer_info_field(connector.manufacturer, connector.mpn)],
[html_line_breaks(connector.type),
html_line_breaks(connector.subtype),
f'{connector.pincount}-pin' if connector.show_pincount else None,
Expand Down Expand Up @@ -151,9 +151,9 @@ def create_graph(self) -> Graph:
elif cable.gauge_unit.upper() == 'AWG':
awg_fmt = f' ({mm2_equiv(cable.gauge)} mm\u00B2)'

identification = [cable.manufacturer if not isinstance(cable.manufacturer, list) else '',
f'MPN: {cable.manufacturer_part_number}' if (cable.manufacturer_part_number and not isinstance(cable.manufacturer_part_number, list)) else '',
f'IPN: {cable.internal_part_number}' if (cable.internal_part_number and not isinstance(cable.internal_part_number, list)) else '']
identification = [f'P/N: {cable.pn}' if (cable.pn and not isinstance(cable.pn, list)) else '',
manufacturer_info_field(cable.manufacturer if not isinstance(cable.manufacturer, list) else None,
cable.mpn if not isinstance(cable.mpn, list) else None)]
identification = list(filter(None, identification))

attributes = [html_line_breaks(cable.type) if cable.type else '',
Expand Down Expand Up @@ -210,12 +210,12 @@ def create_graph(self) -> Graph:
if(cable.category == 'bundle'): # for bundles individual wires can have part information
# create a list of wire parameters
wireidentification = []
if isinstance(cable.manufacturer, list):
wireidentification.append(cable.manufacturer[i - 1])
if isinstance(cable.manufacturer_part_number, list):
wireidentification.append(f'MPN: {cable.manufacturer_part_number[i - 1]}')
if isinstance(cable.internal_part_number, list):
wireidentification.append(f'IPN: {cable.internal_part_number[i - 1]}')
if isinstance(cable.pn, list):
wireidentification.append(f'P/N: {cable.pn[i - 1]}')
manufacturer_info = manufacturer_info_field(cable.manufacturer[i - 1] if isinstance(cable.manufacturer, list) else None,
cable.mpn[i - 1] if isinstance(cable.mpn, list) else None)
if manufacturer_info:
wireidentification.append(manufacturer_info)
# print parameters into a table row under the wire
if(len(wireidentification) > 0):
html = f'{html}<tr><td colspan="{len(p)}"><table border="0" cellspacing="0" cellborder="0"><tr>'
Expand Down Expand Up @@ -337,7 +337,7 @@ def bom(self):
bom_cables = []
bom_extra = []
# connectors
connector_group = lambda c: (c.type, c.subtype, c.pincount, c.manufacturer, c.manufacturer_part_number, c.internal_part_number)
connector_group = lambda c: (c.type, c.subtype, c.pincount, c.manufacturer, c.mpn, c.pn)
for group in Counter([connector_group(v) for v in self.connectors.values()]):
items = {k: v for k, v in self.connectors.items() if connector_group(v) == group}
shared = next(iter(items.values()))
Expand All @@ -349,14 +349,14 @@ def bom(self):
conn_color = f', {shared.color}' if shared.color else ''
name = f'Connector{conn_type}{conn_subtype}{conn_pincount}{conn_color}'
item = {'item': name, 'qty': len(designators), 'unit': '', 'designators': designators if shared.show_name else '',
'manufacturer': shared.manufacturer, 'manufacturer part number': shared.manufacturer_part_number, 'internal part number': shared.internal_part_number}
'manufacturer': shared.manufacturer, 'manufacturer part number': shared.mpn, 'part number': shared.pn}
bom_connectors.append(item)
bom_connectors = sorted(bom_connectors, key=lambda k: k['item']) # https://stackoverflow.com/a/73050
bom.extend(bom_connectors)
# cables
# TODO: If category can have other non-empty values than 'bundle', maybe it should be part of item name?
# The category needs to be included in cable_group to keep the bundles excluded.
cable_group = lambda c: (c.category, c.type, c.gauge, c.gauge_unit, c.wirecount, c.shield, c.manufacturer, c.manufacturer_part_number, c.internal_part_number)
cable_group = lambda c: (c.category, c.type, c.gauge, c.gauge_unit, c.wirecount, c.shield, c.manufacturer, c.mpn, c.pn)
for group in Counter([cable_group(v) for v in self.cables.values() if v.category != 'bundle']):
items = {k: v for k, v in self.cables.items() if cable_group(v) == group}
shared = next(iter(items.values()))
Expand All @@ -368,7 +368,7 @@ def bom(self):
shield_name = ' shielded' if shared.shield else ''
name = f'Cable{cable_type}, {shared.wirecount}{gauge_name}{shield_name}'
item = {'item': name, 'qty': round(total_length, 3), 'unit': 'm', 'designators': designators,
'manufacturer': shared.manufacturer, 'manufacturer part number': shared.manufacturer_part_number, 'internal part number': shared.internal_part_number}
'manufacturer': shared.manufacturer, 'manufacturer part number': shared.mpn, 'part number': shared.pn}
bom_cables.append(item)
# bundles (ignores wirecount)
wirelist = []
Expand All @@ -379,10 +379,10 @@ def bom(self):
for index, color in enumerate(bundle.colors, 0):
wirelist.append({'type': bundle.type, 'gauge': bundle.gauge, 'gauge_unit': bundle.gauge_unit, 'length': bundle.length, 'color': color, 'designator': bundle.name,
'manufacturer': index_if_list(bundle.manufacturer, index),
'manufacturer part number': index_if_list(bundle.manufacturer_part_number, index),
'internal part number': index_if_list(bundle.internal_part_number, index)})
'manufacturer part number': index_if_list(bundle.mpn, index),
'part number': index_if_list(bundle.pn, index)})
# join similar wires from all the bundles to a single BOM item
wire_group = lambda w: (w.get('type', None), w['gauge'], w['gauge_unit'], w['color'], w['manufacturer'], w['manufacturer part number'], w['internal part number'])
wire_group = lambda w: (w.get('type', None), w['gauge'], w['gauge_unit'], w['color'], w['manufacturer'], w['manufacturer part number'], w['part number'])
for group in Counter([wire_group(v) for v in wirelist]):
items = [v for v in wirelist if wire_group(v) == group]
shared = items[0]
Expand All @@ -395,7 +395,7 @@ def bom(self):
gauge_color = f', {shared["color"]}' if 'color' in shared != '' else ''
name = f'Wire{wire_type}{gauge_name}{gauge_color}'
item = {'item': name, 'qty': round(total_length, 3), 'unit': 'm', 'designators': designators,
'manufacturer': shared['manufacturer'], 'manufacturer part number': shared['manufacturer part number'], 'internal part number': shared['internal part number']}
'manufacturer': shared['manufacturer'], 'manufacturer part number': shared['manufacturer part number'], 'part number': shared['part number']}
bom_cables.append(item)
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)
Expand All @@ -405,7 +405,7 @@ def bom(self):
if isinstance(item.get('designators', None), List):
item['designators'].sort() # sort designators if a list is provided
item = {'item': name, 'qty': item.get('qty', None), 'unit': item.get('unit', None), 'designators': item.get('designators', None),
'manufacturer': item.get('manufacturer', None), 'manufacturer part number': item.get('manufacturer_part_number', None), 'internal part number': item.get('internal_part_number', None)}
'manufacturer': item.get('manufacturer', None), 'manufacturer part number': item.get('mpn', None), 'part number': item.get('pn', None)}
bom_extra.append(item)
bom_extra = sorted(bom_extra, key=lambda k: k['item'])
bom.extend(bom_extra)
Expand All @@ -414,7 +414,7 @@ def bom(self):
def bom_list(self):
bom = self.bom()
keys = ['item', 'qty', 'unit', 'designators'] # these BOM columns will always be included
for fieldname in ['manufacturer', 'manufacturer part number', 'internal part number']: # these optional BOM columns will only be included if at least one BOM item actually uses them
for fieldname in ['manufacturer', 'manufacturer part number', 'part number']: # these optional BOM columns will only be included if at least one BOM item actually uses them
if any(fieldname in x and x.get(fieldname, None) for x in bom):
keys.append(fieldname)
bom_list = []
Expand Down
10 changes: 9 additions & 1 deletion src/wireviz/wv_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,12 @@ def open_file_read(filename):
return open(filename, 'r', encoding='UTF-8')

def open_file_write(filename):
return open(filename, 'w', encoding='UTF-8')
return open(filename, 'w', encoding='UTF-8')


def manufacturer_info_field(manufacturer, mpn):
if manufacturer:
part_number_component = f': {mpn}' if mpn else ''
return(f'{manufacturer}{part_number_component}')
else:
return(f'MPN: {mpn}' if mpn else None)
Copy link
Collaborator

@formatc1702 formatc1702 Jul 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about this?

if manufacturer or mpn:
  return f'{manufacturer if manufacturer else "MPN"}{": " + str(mpn) if mpn else ""}'
else
  return None

It should return the same four options:
None (nothing specified)
{manufacturer} (no MPN specified)
MPN: {mpn} (no manufacturer specified)
{manufacturer}: {mpn} (both specified)

IMHO a bit cleaner and easier to understand.
The str() functions allows using + to concatenate strings without errors if mpn is passed as an int.

Copy link
Collaborator

@kvid kvid Jul 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@formatc1702 How about this alternative instead?

    if manufacturer:
        return f'{manufacturer}: {mpn}' if mpn else manufacturer
    else:
        return f'MPN: {mpn}' if mpn else None

Edit: It's closer to the original, except without a variable and without parentheses around the return expressions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That looks like a much tider way to implement that, have swapped to that implementation in the latest commits

1 change: 1 addition & 0 deletions tutorial/tutorial08.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
* Part number information can be added to parts
* Only provided fields will be added to the diagram and bom
* Bundles can have part information specified by wire
* Additional parts can be added to the bom
27 changes: 19 additions & 8 deletions tutorial/tutorial08.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ connectors:
type: Molex KK 254
pincount: 4
subtype: female
manufacturer: Molex
manufacturer_part_number: 22013047
manufacturer: Molex # set manufacter name
mpn: 22013047 # set manufacturer part number
X2:
<<: *template1 # reuse template
internal_part_number: CON4
pn: CON4 # set an internal part number
X3:
<<: *template1 # reuse template

Expand All @@ -18,16 +18,16 @@ cables:
gauge: 0.25 mm2
color_code: IEC
manufacturer: CablesCo
manufacturer_part_number: ABC123
internal_part_number: CAB1
mpn: ABC123
pn: CAB1
W2:
category: bundle
length: 1
gauge: 0.25 mm2
colors: [YE, BK, BK, RD]
manufacturer: [WiresCo,WiresCo,WiresCo,WiresCo]
manufacturer_part_number: [W1-YE,W1-BK,W1-BK,W1-RD]
internal_part_number: [WIRE1,WIRE2,WIRE2,WIRE3]
manufacturer: [WiresCo,WiresCo,WiresCo,WiresCo] # set a manufacter per wire
mpn: [W1-YE,W1-BK,W1-BK,W1-RD]
pn: [WIRE1,WIRE2,WIRE2,WIRE3]


connections:
Expand All @@ -39,3 +39,14 @@ connections:
- X1: [1-4]
- W2: [1-4]
- X3: [1-4]

additional_bom_items:
- # define an additional item to add to the bill of materials
description: Label, pinout information
qty: 2
designators:
- X2
- X3
manufacturer: generic company
mpn: Label1
pn: Label-ID-1