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

Modify CLI interface #123

Closed
wants to merge 41 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
4aac32b
Merge branch 'dev'
17o2 Jun 28, 2020
8326ddd
Merge branch 'dev'
17o2 Jun 28, 2020
7458118
Merge branch 'dev'
17o2 Jun 29, 2020
8b09fac
Merge branch 'dev'
17o2 Jun 29, 2020
fffb354
Merge branch 'dev'
17o2 Jun 30, 2020
83b1c9b
Add type hinting in several, but not all, places.
slightlynybbled Jul 15, 2020
38938fc
Fix type hinting
slightlynybbled Jul 15, 2020
8f6b8a7
Add initial contribution guidelines
slightlynybbled Jul 15, 2020
8c33b9f
Merge branch 'dev' of github.com:slightlynybbled/WireViz into dev
slightlynybbled Jul 16, 2020
83929a1
Fix utf-8 encoding problem in BOM portion of HTML files.
slightlynybbled Jul 16, 2020
35fcd11
Translate encountered instances of "\n" to "<br>" within the html-gen…
slightlynybbled Jul 16, 2020
be10908
Change '<sup></sup>' to '&sup2;'
slightlynybbled Jul 17, 2020
5a7bc73
Removing '\\n' character, as requested.
slightlynybbled Jul 20, 2020
665d795
Merge branch 'master' of github.com:slightlynybbled/WireViz into dev
slightlynybbled Jul 20, 2020
c2d96e8
Add more robust routines for BOM file output
aakatz3 Jul 20, 2020
a634493
Fix todo in file read
aakatz3 Jul 21, 2020
5b8b043
Update README.md
aakatz3 Jul 21, 2020
379a4cf
Merge branch 'dev' of github.com:slightlynybbled/WireViz into dev
slightlynybbled Jul 24, 2020
54da2f2
Add click to make CLI easier
slightlynybbled Jul 24, 2020
4fe84b4
Remove unused dependency
slightlynybbled Jul 24, 2020
028f295
Updating setup.py to include `click`
slightlynybbled Jul 24, 2020
3009a17
Better document string
slightlynybbled Jul 24, 2020
6b3a89e
Addressed review comments
aakatz3 Jul 24, 2020
bac99f0
Add ability to specify default color
aakatz3 Jul 24, 2020
e207ee2
Merge branch 'refactor/add-default-color-param' into refactor/csv-tsv
aakatz3 Jul 24, 2020
85c196f
Merge pull request #1 from aakatz3/refactor/csv-tsv
slightlynybbled Jul 24, 2020
bbf92bb
Remove unused function
slightlynybbled Jul 24, 2020
126f525
Add `html` sttribute to `Harness`, using it in the `parse` function
slightlynybbled Jul 25, 2020
2d9c6e6
Add skeleton of csv file outputs.
slightlynybbled Jul 25, 2020
1f535bc
Add html to document string
slightlynybbled Jul 25, 2020
8ba17d8
Remove unnecessary method
slightlynybbled Jul 25, 2020
def8f13
Fill out each BOM attribute, enable BOM output in various formats.
slightlynybbled Jul 25, 2020
4747f2e
Refactor `bom()` and `bom_list` methods into private methods.
slightlynybbled Jul 25, 2020
f64fac0
Remove unused parameter
slightlynybbled Jul 25, 2020
4e1d716
Add placeholder for gv output
slightlynybbled Jul 25, 2020
6cb8617
Add better help string
slightlynybbled Jul 25, 2020
5197298
More concise saving of data
slightlynybbled Jul 25, 2020
52f79fe
Refactoring to build the examples
slightlynybbled Jul 25, 2020
50ff1a0
Separated into `cli()` and `main()` to enable build script to call `m…
slightlynybbled Jul 25, 2020
97e77f5
Fix `build_examples.py`
slightlynybbled Jul 25, 2020
448c4e6
Merge branch 'dev' of https://github.com/formatc1702/WireViz into dev
slightlynybbled Jul 28, 2020
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
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,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
```

Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.
click
graphviz
pyyaml
setuptools
12 changes: 8 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,20 @@

project_name = 'wireviz'

# utility function to read the requirements.txt file
with open('requirements.txt', 'r') as f:
requirements = f.readlines()
requirements = [r.strip() for r in requirements]
requirements = [r for r in requirements if r != '.']

# Utility function to read the README file.
# Used for the long_description. It's nice, because now 1) we have a top level
# README file and 2) it's easier to type in the README file than to put a raw
# string in below ...
def read(fname):
return open(os.path.join(os.path.dirname(__file__), fname)).read()


setup(
name=project_name,
version='0.1',
Expand All @@ -21,10 +28,7 @@ def read(fname):
description='Easily document cables and wiring harnesses',
long_description=read(os.path.join(os.path.dirname(__file__), 'README.md')),
long_description_content_type='text/markdown',
install_requires=[
'pyyaml',
'graphviz',
],
install_requires=requirements,
license='GPLv3',
keywords='cable connector hardware harness wiring wiring-diagram wiring-harness',
url='https://github.com/formatc1702/WireViz',
Expand Down
133 changes: 84 additions & 49 deletions src/wireviz/Harness.py
Original file line number Diff line number Diff line change
Expand Up @@ -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, \
manufacturer_info_field
Expand Down Expand Up @@ -68,7 +68,7 @@ def create_graph(self) -> Graph:
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',
Expand Down Expand Up @@ -276,6 +276,11 @@ def create_graph(self) -> Graph:

return dot

@property
def gv(self):
# self.create_graph().save()
raise NotImplementedError

@property
def png(self):
from io import BytesIO
Expand All @@ -294,50 +299,80 @@ def svg(self):
data.seek(0)
return data.read()

def output(self, filename: (str, Path), view: bool = False, cleanup: bool = True, fmt: tuple = ('pdf', )) -> None:
# graphical output
graph = self.create_graph()
for f in fmt:
graph.format = f
graph.render(filename=filename, view=view, cleanup=cleanup)
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))
# HTML output
with open_file_write(f'{filename}.html') as file:
file.write('<!DOCTYPE html>\n')
file.write('<html><head><meta charset="UTF-8"></head><body style="font-family:Arial">')

file.write('<h1>Diagram</h1>')
with open_file_read(f'{filename}.svg') as svg:
file.write(re.sub(
'^<[?]xml [^?>]*[?]>[^<]*<!DOCTYPE [^>]*>',
'<!-- XML and DOCTYPE declarations from SVG file removed -->',
svg.read(1024), 1))
for svgdata in svg:
file.write(svgdata)

file.write('<h1>Bill of Materials</h1>')
listy = flatten2d(bom_list)
file.write('<table style="border:1px solid #000000; font-size: 14pt; border-spacing: 0px">')
file.write('<tr>')
for item in listy[0]:
file.write(f'<th align="left" style="border:1px solid #000000; padding: 8px">{item}</th>')
file.write('</tr>')
for row in listy[1:]:
file.write('<tr>')
for i, item in enumerate(row):
item_str = item.replace('\u00b2', '&sup2;')
align = 'align="right"' if listy[0][i] == 'Qty' else ''
file.write(f'<td {align} style="border:1px solid #000000; padding: 4px">{item_str}</td>')
file.write('</tr>')
file.write('</table>')

file.write('</body></html>')

def bom(self):
@property
def html(self):
bom_list = self._bom_list()
string = ''

string += '<!DOCTYPE html>\n'
string += f'<html><head><meta charset="UTF-8"></head><body style="font-family:Arial;background-color:{wv_colors.COLOR_BACKGROUND}">'

string += '<h1>Diagram</h1>'

svg = self.svg.decode('utf-8')
svg = re.sub(
'^<[?]xml [^?>]*[?]>[^<]*<!DOCTYPE [^>]*>',
'<!-- XML and DOCTYPE declarations from SVG file removed -->',
svg)
for svgdata in svg:
string += svgdata

string += '<h1>Bill of Materials</h1>'
listy = flatten2d(bom_list)
string += '<table style="border:1px solid #000000; font-size: 14pt; border-spacing: 0px">'
string += '<tr>'
for item in listy[0]:
string += f'<th align="left" style="border:1px solid #000000; padding: 8px">{item}</th>'
string += '</tr>'
for row in listy[1:]:
string += '<tr>'
for i, item in enumerate(row):
item_str = item.replace('\u00b2', '&sup2;')
align = 'align="right"' if listy[0][i] == 'Qty' else ''
string += f'<td {align} style="border:1px solid #000000; padding: 4px">{item_str}</td>'
string += '</tr>'
string += '</table>'

string += '</body></html>'

return bytes(string, encoding='utf-8')

@property
def csv(self):
return bom_helper.generate_bom_outputs(
self._bom_list(),
'csv'
)

@property
def csv_excel(self):
return bom_helper.generate_bom_outputs(
self._bom_list(),
'csv_excel'
)

@property
def csv_unix(self):
return bom_helper.generate_bom_outputs(
self._bom_list(),
'csv_unix'
)

@property
def tsv(self):
return bom_helper.generate_bom_outputs(
self._bom_list(),
'tsv'
)

@property
def tsv_excel(self):
return bom_helper.generate_bom_outputs(
self._bom_list(),
'tsv_excel'
)

def _bom(self):
bom = []
bom_connectors = []
bom_cables = []
Expand Down Expand Up @@ -417,8 +452,8 @@ def bom(self):
bom.extend(bom_extra)
return bom

def bom_list(self):
bom = self.bom()
def _bom_list(self):
bom = self._bom()
keys = ['item', 'qty', 'unit', 'designators'] # these BOM columns will always be included
for fieldname in ['pn', 'manufacturer', 'mpn']: # 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):
Expand Down
43 changes: 43 additions & 0 deletions src/wireviz/bom_helper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import csv
from io import StringIO

from wireviz import wv_helper

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)


def generate_bom_outputs(bomdata, dialect='tsv'):
dialect = dialect.strip().lower()
dialect_lookup = {
'csv': csv.unix_dialect,
'csv_unix': csv.unix_dialect,
'csv_excel': csv.excel,
'tsv': WIREVIZ_TSV,
'tsv_excel': csv.excel_tab
}
valid_dialects = [k for k in dialect_lookup.keys()]
if dialect not in valid_dialects:
raise ValueError(f'dialect "{dialect}" not supported')

output = StringIO()
writer = csv.writer(output, dialect=dialect_lookup[dialect])
writer.writerows(wv_helper.flatten2d(bomdata))

output.seek(0)

return bytes(output.read(), encoding='utf-8')

# TODO: Possibly refactor other BOM output operations, such as HTML, into here?
4 changes: 2 additions & 2 deletions src/wireviz/build_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

sys.path.insert(0, str(script_path.parent.parent)) # to find wireviz module
from wireviz import wireviz
from wv_helper import open_file_write, open_file_read, open_file_append
from wireviz.wv_helper import open_file_write, open_file_read, open_file_append


readme = 'readme.md'
Expand Down Expand Up @@ -61,7 +61,7 @@ def build_generated(groupkeys):
# collect and iterate input YAML files
for yaml_file in collect_filenames('Building', key, input_extensions):
print(f' "{yaml_file}"')
wireviz.parse_file(yaml_file)
wireviz.main(yaml_file, prepend=None, out=['png', 'svg', 'html', 'csv'])

if build_readme:
i = ''.join(filter(str.isdigit, yaml_file.stem))
Expand Down
Loading