From c2d96e8e4c7392da77c719fcd8eb30603d0f037c Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Mon, 20 Jul 2020 19:55:24 -0400 Subject: [PATCH 1/5] Add more robust routines for BOM file output --- src/wireviz/Harness.py | 8 +++---- src/wireviz/bom_helper.py | 42 +++++++++++++++++++++++++++++++++++ src/wireviz/build_examples.py | 5 +++-- src/wireviz/wv_helper.py | 4 ++-- 4 files changed, 51 insertions(+), 8 deletions(-) create mode 100644 src/wireviz/bom_helper.py diff --git a/src/wireviz/Harness.py b/src/wireviz/Harness.py index b980483..c0b598b 100644 --- a/src/wireviz/Harness.py +++ b/src/wireviz/Harness.py @@ -3,9 +3,9 @@ from wireviz.DataClasses import Connector, Cable 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_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, \ graphviz_line_breaks, remove_line_breaks, open_file_read, open_file_write from collections import Counter @@ -297,8 +297,8 @@ class Harness: graph.save(filename=f'{filename}.gv') # bom output bom_list = self.bom_list() - with open_file_write(f'{filename}.bom.tsv') as file: - file.write(tuplelist2tsv(bom_list)) + # todo: support user choices of BOM format (probably also graphviz outputs, html outputs) + bom_helper.generate_bom_outputs(filename,bom_list,bom_helper.WIREVIZ_TSV, bom_helper.EXCEL_CSV) # HTML output with open_file_write(f'{filename}.html') as file: file.write('\n') diff --git a/src/wireviz/bom_helper.py b/src/wireviz/bom_helper.py new file mode 100644 index 0000000..d1e704f --- /dev/null +++ b/src/wireviz/bom_helper.py @@ -0,0 +1,42 @@ +#!/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, *argv): + expanded_csv_names = len(_csv_formats.intersection(set(argv))) > 1 + expanded_tsv_names = len(_tsv_formats.intersection(set(argv))) > 1 + for fmt in argv: + 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? \ No newline at end of file diff --git a/src/wireviz/build_examples.py b/src/wireviz/build_examples.py index ee59ded..9238e7d 100755 --- a/src/wireviz/build_examples.py +++ b/src/wireviz/build_examples.py @@ -74,10 +74,11 @@ def build_tutorials(): 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(): - 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]: print(filepath) diff --git a/src/wireviz/wv_helper.py b/src/wireviz/wv_helper.py index 024c3ef..966080c 100644 --- a/src/wireviz/wv_helper.py +++ b/src/wireviz/wv_helper.py @@ -116,5 +116,5 @@ def open_file_read(filename): # TODO: Intelligently determine encoding return open(filename, 'r', encoding='UTF-8') -def open_file_write(filename): - return open(filename, 'w', encoding='UTF-8') \ No newline at end of file +def open_file_write(filename, newline='\n'): + return open(filename, 'w', encoding='UTF-8', newline=newline) \ No newline at end of file From a6344933feed8d48c26fcade2e071fbbfdb3c69e Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Mon, 20 Jul 2020 20:22:57 -0400 Subject: [PATCH 2/5] Fix todo in file read --- src/wireviz/wv_helper.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wireviz/wv_helper.py b/src/wireviz/wv_helper.py index 966080c..17aede0 100644 --- a/src/wireviz/wv_helper.py +++ b/src/wireviz/wv_helper.py @@ -113,8 +113,8 @@ def remove_line_breaks(inp): return inp.replace('\n', ' ').rstrip() if isinstance(inp, str) else inp def open_file_read(filename): - # TODO: Intelligently determine encoding + # TODO: Intelligently determine encoding (UnicodeDammit, Chardet, cchardet are not very reliable in testing) return open(filename, 'r', encoding='UTF-8') def open_file_write(filename, newline='\n'): - return open(filename, 'w', encoding='UTF-8', newline=newline) \ No newline at end of file + return open(filename, 'w', encoding='UTF-8', newline=newline) From 5b8b043a70610b5790d1a6df914042413f6247f0 Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Mon, 20 Jul 2020 20:53:00 -0400 Subject: [PATCH 3/5] Update README.md Add csv file to generated outputs --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ed2b4df..903e4ac 100644 --- a/README.md +++ b/README.md @@ -99,10 +99,11 @@ $ wireviz ~/path/to/file/mywire.yml 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.png Wiring diagram as raster image 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 ``` From 6b3a89edebb08271235a6f7703f40c0147589536 Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Fri, 24 Jul 2020 15:35:58 -0400 Subject: [PATCH 4/5] Addressed review comments --- src/wireviz/Harness.py | 2 +- src/wireviz/bom_helper.py | 15 +++++++++++---- src/wireviz/wv_helper.py | 1 - 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/wireviz/Harness.py b/src/wireviz/Harness.py index c0b598b..80d250a 100644 --- a/src/wireviz/Harness.py +++ b/src/wireviz/Harness.py @@ -298,7 +298,7 @@ class Harness: # bom output bom_list = self.bom_list() # todo: support user choices of BOM format (probably also graphviz outputs, html outputs) - bom_helper.generate_bom_outputs(filename,bom_list,bom_helper.WIREVIZ_TSV, bom_helper.EXCEL_CSV) + bom_helper.generate_bom_outputs(filename,bom_list, [bom_helper.WIREVIZ_TSV, bom_helper.EXCEL_CSV]) # HTML output with open_file_write(f'{filename}.html') as file: file.write('\n') diff --git a/src/wireviz/bom_helper.py b/src/wireviz/bom_helper.py index d1e704f..218b413 100644 --- a/src/wireviz/bom_helper.py +++ b/src/wireviz/bom_helper.py @@ -26,10 +26,17 @@ _tsv_formats = { EXCEL_TSV, WIREVIZ_TSV } _csv_ext = '.bom.csv' _tsv_ext = '.bom.tsv' -def generate_bom_outputs(base_filename, bomdata, *argv): - expanded_csv_names = len(_csv_formats.intersection(set(argv))) > 1 - expanded_tsv_names = len(_tsv_formats.intersection(set(argv))) > 1 - for fmt in argv: +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) diff --git a/src/wireviz/wv_helper.py b/src/wireviz/wv_helper.py index 17aede0..703eb8c 100644 --- a/src/wireviz/wv_helper.py +++ b/src/wireviz/wv_helper.py @@ -113,7 +113,6 @@ def remove_line_breaks(inp): return inp.replace('\n', ' ').rstrip() if isinstance(inp, str) else inp def open_file_read(filename): - # TODO: Intelligently determine encoding (UnicodeDammit, Chardet, cchardet are not very reliable in testing) return open(filename, 'r', encoding='UTF-8') def open_file_write(filename, newline='\n'): From bac99f0d807b27dca6f37413e3bbf6435aaa0abb Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Fri, 24 Jul 2020 15:57:32 -0400 Subject: [PATCH 5/5] Add ability to specify default color --- src/wireviz/Harness.py | 4 ++-- src/wireviz/wv_colors.py | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/wireviz/Harness.py b/src/wireviz/Harness.py index 80d250a..2792c2c 100644 --- a/src/wireviz/Harness.py +++ b/src/wireviz/Harness.py @@ -67,7 +67,7 @@ class Harness: font = 'arial' dot.attr('graph', rankdir='LR', ranksep='2', - bgcolor='white', + bgcolor=wv_colors.COLOR_BACKGROUND, nodesep='0.33', fontname=font) dot.attr('node', shape='record', @@ -302,7 +302,7 @@ class Harness: # HTML output with open_file_write(f'{filename}.html') as file: file.write('\n') - file.write('') + file.write(f'') file.write('

Diagram

') with open_file_read(f'{filename}.svg') as svg: diff --git a/src/wireviz/wv_colors.py b/src/wireviz/wv_colors.py index 9e49d42..e7b7c6d 100644 --- a/src/wireviz/wv_colors.py +++ b/src/wireviz/wv_colors.py @@ -98,12 +98,13 @@ _color_ger = { } -color_default = '#ffffff' +COLOR_DEFAULT = '#ffffff' +COLOR_BACKGROUND = '#ffffff' def get_color_hex(input, pad=False): 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 input = input + input[:2] # 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)] except KeyError: print("Unknown color specified") - output = [color_default] + output = [COLOR_DEFAULT] return output