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

Add support for line breaks in certain fields #64

Merged
merged 6 commits into from
Jul 5, 2020
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 0 additions & 1 deletion examples/demo02.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ ferrules:
ferrule_crimp:
type: Crimp ferrule
subtype: 0.25 mm²
color: YE

connectors:
X1:
Expand Down
44 changes: 19 additions & 25 deletions src/wireviz/Harness.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from wireviz.DataClasses import Connector, Cable
from graphviz import Graph
from wireviz import wv_colors
from wireviz.wv_helper import awg_equiv, mm2_equiv, tuplelist2tsv, nested, flatten2d, index_if_list
from wireviz.wv_helper import awg_equiv, mm2_equiv, tuplelist2tsv, nested, nested_html_table, flatten2d, index_if_list, html_line_breaks, graphviz_line_breaks, remove_line_breaks
from collections import Counter
from typing import List

Expand Down Expand Up @@ -60,24 +60,18 @@ def create_graph(self):
for key, connector in self.connectors.items():
if connector.category == 'ferrule':

rows = [[connector.type, connector.subtype, connector.color, '<!-- colorbar -->' if connector.color else None],
rows = [[html_line_breaks(connector.type), html_line_breaks(connector.subtype), connector.color, '<!-- colorbar -->' if connector.color 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'IPN: {connector.internal_part_number}' if connector.internal_part_number else None],
[html_line_breaks(connector.notes)]]
rows = [list(filter(None, row)) for row in rows] # remove missing attributes

html = '<table border="0" cellspacing="0" cellpadding="0">'
for row in rows:
if len(row) > 0:
html = f'{html}<tr><td><table border="0" cellspacing="0" cellpadding="3" cellborder="1"><tr>'
for cell in row:
html = f'{html}<td>{cell}</td>'
html = f'{html}</tr></table></td></tr>'
html = f'{html}</table>'
html = nested_html_table(rows)

if connector.color: # add color bar next to color info, if present
colorbar = f'<td bgcolor="{wv_colors.translate_color(connector.color, "HEX")}" width="4"></td>'
html = html.replace('<td><!-- colorbar --></td>', colorbar)
colorbar = f' bgcolor="{wv_colors.translate_color(connector.color, "HEX")}" width="4"></td>' # leave out '<td' from string to preserve any existing attributes of the <td> tag
html = html.replace('><!-- colorbar --></td>', colorbar)

dot.node(key, label=f'<{html}>', shape='none', margin='0', style='filled', fillcolor='white')

Expand All @@ -86,8 +80,8 @@ def create_graph(self):
f'MPN: {connector.manufacturer_part_number}' if connector.manufacturer_part_number else '',
f'IPN: {connector.internal_part_number}' if connector.internal_part_number else '']

attributes = [connector.type,
connector.subtype,
attributes = [graphviz_line_breaks(connector.type),
graphviz_line_breaks(connector.subtype),
f'{connector.pincount}-pin' if connector.show_pincount else'']
pinouts = [[], [], []]
for pinnumber, pinname in zip(connector.pinnumbers, connector.pinout):
Expand All @@ -98,7 +92,7 @@ def create_graph(self):
pinouts[0].append(f'<p{pinnumber}l>{pinnumber}')
if connector.ports_right:
pinouts[2].append(f'<p{pinnumber}r>{pinnumber}')
label = [connector.name if connector.show_name else '', identification, attributes, pinouts, connector.notes]
label = [connector.name if connector.show_name else '', identification, attributes, pinouts, graphviz_line_breaks(connector.notes)]
dot.node(key, label=nested(label))

if len(connector.loops) > 0:
Expand Down Expand Up @@ -132,7 +126,7 @@ def create_graph(self):
f'IPN: {cable.internal_part_number}' if (cable.internal_part_number and not isinstance(cable.internal_part_number, list)) else '']
identification = list(filter(None, identification))

attributes = [f'{cable.type}' if cable.type else '',
attributes = [html_line_breaks(cable.type) if cable.type else '',
f'{len(cable.colors)}x' if cable.show_wirecount else '',
f'{cable.gauge} {cable.gauge_unit}{awg_fmt}' if cable.gauge else '',
'+ S' if cable.shield else '',
Expand All @@ -153,7 +147,7 @@ def create_graph(self):
html = f'{html}</tr></table></td></tr>' # end identification row
html = f'{html}<tr>' # attribute row
for attrib in attributes:
html = f'{html}<td>{attrib}</td>'
html = f'{html}<td balign="left">{attrib}</td>'
html = f'{html}</tr>' # attribute row
html = f'{html}</table></td></tr>' # name+attributes table

Expand Down Expand Up @@ -204,7 +198,7 @@ def create_graph(self):

html = f'{html}</td></tr>' # main table
if cable.notes:
html = f'{html}<tr><td cellpadding="3">{cable.notes}</td></tr>' # notes table
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

html = f'{html}</table>' # main table
Expand Down Expand Up @@ -308,8 +302,8 @@ def bom(self):
shared = next(iter(items.values()))
designators = list(items.keys())
designators.sort()
conn_type = f', {shared.type}' if shared.type else ''
conn_subtype = f', {shared.subtype}' if shared.subtype else ''
conn_type = f', {remove_line_breaks(shared.type)}' if shared.type else ''
conn_subtype = f', {remove_line_breaks(shared.subtype)}' if shared.subtype else ''
conn_pincount = f', {shared.pincount} pins' if shared.category != 'ferrule' else ''
conn_color = f', {shared.color}' if shared.color else ''
name = f'Connector{conn_type}{conn_subtype}{conn_pincount}{conn_color}'
Expand All @@ -328,7 +322,7 @@ def bom(self):
designators = list(items.keys())
designators.sort()
total_length = sum(i.length for i in items.values())
cable_type = f', {shared.type}' if shared.type else ''
cable_type = f', {remove_line_breaks(shared.type)}' if shared.type else ''
gauge_name = f' x {shared.gauge} {shared.gauge_unit}' if shared.gauge else ' wires'
shield_name = ' shielded' if shared.shield else ''
name = f'Cable{cable_type}, {shared.wirecount}{gauge_name}{shield_name}'
Expand All @@ -342,7 +336,7 @@ def bom(self):
if bundle.category == 'bundle':
# add each wire from each bundle to the wirelist
for index, color in enumerate(bundle.colors, 0):
wirelist.append({'gauge': bundle.gauge, 'gauge_unit': bundle.gauge_unit, 'length': bundle.length, 'color': color, 'designator': bundle.name,
wirelist.append({'type': bundle.type, 'gauge': bundle.gauge, 'gauge_unit': bundle.gauge_unit, 'length': bundle.length, 'color': color, 'designator': bundle.name,
Copy link
Collaborator Author

@formatc1702 formatc1702 Jul 5, 2020

Choose a reason for hiding this comment

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

We were ignoring the type for bundles. In general, I see no reason to.

'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)})
Expand All @@ -355,8 +349,8 @@ def bom(self):
designators = list(dict.fromkeys(designators)) # remove duplicates
designators.sort()
total_length = sum(i['length'] for i in items)
wire_type = f', {shared["type"]}' if 'type' in shared else ''
gauge_name = f', {shared["gauge"]} {shared["gauge_unit"]}' if 'gauge' in shared else ''
wire_type = f', {remove_line_breaks(shared["type"])}' if shared.get('type', None) else ''
gauge_name = f', {shared["gauge"]} {shared["gauge_unit"]}' if shared.get('gauge', None) else ''
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The new syntax catches both missing keys and keys with None as value.

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,
Expand Down
23 changes: 23 additions & 0 deletions src/wireviz/wv_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,20 @@ def nested(inp):
l.append(str(x))
return '|'.join(l)

def nested_html_table(rows):
# input: list of lists
# output: a parent table with one child table per parent list item
# purpose: create the appearance of one table, where cell widths are independent between rows
html = '<table border="0" cellspacing="0" cellpadding="0">'
for row in rows:
if len(row) > 0:
html = f'{html}<tr><td><table border="0" cellspacing="0" cellpadding="3" cellborder="1"><tr>'
for cell in row:
html = f'{html}<td balign="left">{cell}</td>'
html = f'{html}</tr></table></td></tr>'
html = f'{html}</table>'
return html


def int2tuple(inp):
if isinstance(inp, tuple):
Expand All @@ -69,3 +83,12 @@ def tuplelist2tsv(inp, header=None):
# Return the value indexed if it is a list, or simply the value otherwise.
def index_if_list(value, index):
return value[index] if isinstance(value, list) else value

def html_line_breaks(inp):
return inp.replace('\n', '<br />') if isinstance(inp, str) else inp

def graphviz_line_breaks(inp):
return inp.replace('\n', '\\l') if isinstance(inp, str) else inp # \l generates left-aligned new lines. http://www.graphviz.org/doc/info/attrs.html#k:escString

def remove_line_breaks(inp):
return inp.replace('\n', ' ').rstrip() if isinstance(inp, str) else inp
2 changes: 1 addition & 1 deletion tutorial/tutorial06.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ connectors:
subtype: female
F_10_1: # manually define a ferrule (with unique designator)
category: ferrule
type: Crimp ferrule
type: Ferrule, crimp
subtype: 1.0 mm²
color: YE

Expand Down