Merge pull request #1 from aakatz3/refactor/csv-tsv

[refactor] Use the csv library to generate properly escaped TSV files
This commit is contained in:
Jason 2020-07-24 19:13:02 -04:00 committed by GitHub
commit 85c196f151
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 66 additions and 15 deletions

View File

@ -100,10 +100,11 @@ $ wireviz ~/path/to/file/mywire.yml
This will output the following files This will output the following files
``` ```
mywire.gv GraphViz output mywire.gv Raw GraphViz DOT file output of wiring diagram
mywire.svg Wiring diagram as vector image mywire.svg Wiring diagram as vector image
mywire.png Wiring diagram as raster image mywire.png Wiring diagram as raster image
mywire.bom.tsv BOM (bill of materials) as tab-separated text file mywire.bom.tsv BOM (bill of materials) as tab-separated text file
mywire.bom.csv BOM (bill of materials) as comma-separated, excel-format text file
mywire.html HTML page with wiring diagram and BOM embedded mywire.html HTML page with wiring diagram and BOM embedded
``` ```

View File

@ -3,9 +3,9 @@
from wireviz.DataClasses import Connector, Cable from wireviz.DataClasses import Connector, Cable
from graphviz import Graph from graphviz import Graph
from wireviz import wv_colors, wv_helper from wireviz import wv_colors, wv_helper, bom_helper
from wireviz.wv_colors import get_color_hex from wireviz.wv_colors import get_color_hex
from wireviz.wv_helper import awg_equiv, mm2_equiv, tuplelist2tsv, \ from wireviz.wv_helper import awg_equiv, mm2_equiv, \
nested_html_table, flatten2d, index_if_list, html_line_breaks, \ 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
from collections import Counter from collections import Counter
@ -67,7 +67,7 @@ class Harness:
font = 'arial' font = 'arial'
dot.attr('graph', rankdir='LR', dot.attr('graph', rankdir='LR',
ranksep='2', ranksep='2',
bgcolor='white', bgcolor=wv_colors.COLOR_BACKGROUND,
nodesep='0.33', nodesep='0.33',
fontname=font) fontname=font)
dot.attr('node', shape='record', dot.attr('node', shape='record',
@ -297,12 +297,12 @@ class Harness:
graph.save(filename=f'{filename}.gv') graph.save(filename=f'{filename}.gv')
# bom output # bom output
bom_list = self.bom_list() bom_list = self.bom_list()
with open_file_write(f'{filename}.bom.tsv') as file: # todo: support user choices of BOM format (probably also graphviz outputs, html outputs)
file.write(tuplelist2tsv(bom_list)) bom_helper.generate_bom_outputs(filename,bom_list, [bom_helper.WIREVIZ_TSV, bom_helper.EXCEL_CSV])
# HTML output # HTML output
with open_file_write(f'{filename}.html') as file: with open_file_write(f'{filename}.html') as file:
file.write('<!DOCTYPE html>\n') file.write('<!DOCTYPE html>\n')
file.write('<html><head><meta charset="UTF-8"></head><body style="font-family:Arial">') file.write(f'<html><head><meta charset="UTF-8"></head><body style="font-family:Arial;background-color:{wv_colors.COLOR_BACKGROUND}">')
file.write('<h1>Diagram</h1>') file.write('<h1>Diagram</h1>')
with open_file_read(f'{filename}.svg') as svg: with open_file_read(f'{filename}.svg') as svg:

49
src/wireviz/bom_helper.py Normal file
View File

@ -0,0 +1,49 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import csv
from wireviz import wv_helper
from wireviz.wv_helper import open_file_write
EXCEL_CSV = csv.excel
EXCEL_TSV = csv.excel_tab
UNIX_CSV = csv.unix_dialect
WIREVIZ_TSV = type('Wireviz BOM', (csv.Dialect, object), dict(
delimiter='\t',
doublequote=True,
escapechar=None,
lineterminator='\n',
quoting=0,
skipinitialspace=False,
strict=False,
quotechar='"'
))
csv.register_dialect('Wireviz BOM', WIREVIZ_TSV)
_csv_formats = { EXCEL_CSV, UNIX_CSV }
_tsv_formats = { EXCEL_TSV, WIREVIZ_TSV }
_csv_ext = '.bom.csv'
_tsv_ext = '.bom.tsv'
def generate_bom_outputs(base_filename, bomdata, formats=None):
if formats is None:
formats = [EXCEL_CSV, WIREVIZ_TSV]
elif isinstance(formats, csv.Dialect):
formats = [formats]
elif not isinstance(formats, list):
raise TypeError
expanded_csv_names = len(_csv_formats.intersection(set(formats))) > 1
expanded_tsv_names = len(_tsv_formats.intersection(set(formats))) > 1
for fmt in formats:
if fmt in _csv_formats:
file = csv.writer(open_file_write(base_filename + ("_" + fmt.__name__ if expanded_csv_names else "") + _csv_ext, fmt.lineterminator), fmt)
elif fmt in _tsv_formats:
file = csv.writer(open_file_write(base_filename + ("_"+fmt.__name__ if expanded_tsv_names else "") + _tsv_ext, fmt.lineterminator), fmt)
else:
raise KeyError("Unknown BOM Format Specified")
file.writerows(wv_helper.flatten2d(bomdata))
# TODO: Possibly refactor other BOM output operations, such as HTML, into here?

View File

@ -74,10 +74,11 @@ def build_tutorials():
file.write(f'![](tutorial{outfile_name}.png)\n\n') file.write(f'![](tutorial{outfile_name}.png)\n\n')
file.write(f'[Bill of Materials](tutorial{outfile_name}.bom.tsv)\n\n\n') file.write(f'[Bill of Materials - TSV](tutorial{outfile_name}.bom.tsv)\n\n')
file.write(f'[Bill of Materials - CSV](tutorial{outfile_name}.bom.csv)\n\n\n')
def clean_examples(): def clean_examples():
generated_extensions = ['.gv', '.png', '.svg', '.html', '.bom.tsv'] generated_extensions = ['.gv', '.png', '.svg', '.html', '.bom.tsv', '.bom.csv']
for filepath in [examples_path, demos_path, tutorials_path]: for filepath in [examples_path, demos_path, tutorials_path]:
print(filepath) print(filepath)

View File

@ -98,12 +98,13 @@ _color_ger = {
} }
color_default = '#ffffff' COLOR_DEFAULT = '#ffffff'
COLOR_BACKGROUND = '#ffffff'
def get_color_hex(input, pad=False): def get_color_hex(input, pad=False):
if input is None or input == '': if input is None or input == '':
return [color_default] return [COLOR_DEFAULT]
if len(input) == 4: # give wires with EXACTLY 2 colors that striped/banded look if len(input) == 4: # give wires with EXACTLY 2 colors that striped/banded look
input = input + input[:2] input = input + input[:2]
# hacky style fix: give single color wires a triple-up so that wires are the same size # hacky style fix: give single color wires a triple-up so that wires are the same size
@ -113,7 +114,7 @@ def get_color_hex(input, pad=False):
output = [_color_hex[input[i:i + 2]] for i in range(0, len(input), 2)] output = [_color_hex[input[i:i + 2]] for i in range(0, len(input), 2)]
except KeyError: except KeyError:
print("Unknown color specified") print("Unknown color specified")
output = [color_default] output = [COLOR_DEFAULT]
return output return output

View File

@ -113,8 +113,7 @@ def remove_line_breaks(inp):
return inp.replace('\n', ' ').rstrip() if isinstance(inp, str) else inp return inp.replace('\n', ' ').rstrip() if isinstance(inp, str) else inp
def open_file_read(filename): def open_file_read(filename):
# TODO: Intelligently determine encoding
return open(filename, 'r', encoding='UTF-8') return open(filename, 'r', encoding='UTF-8')
def open_file_write(filename): def open_file_write(filename, newline='\n'):
return open(filename, 'w', encoding='UTF-8') return open(filename, 'w', encoding='UTF-8', newline=newline)