Add basic metadata and options to Harness

Resolves the basic part of #158.
This commit is contained in:
KV 2021-02-06 22:03:38 +01:00
parent e212fc9058
commit 5d6d60c3d0
5 changed files with 42 additions and 13 deletions

View File

@ -20,6 +20,7 @@ ConnectorMultiplier = PlainText # = Literal['pincount', 'populated']
CableMultiplier = PlainText # = Literal['wirecount', 'terminations', 'length', 'total_length'] CableMultiplier = PlainText # = Literal['wirecount', 'terminations', 'length', 'total_length']
ImageScale = PlainText # = Literal['false', 'true', 'width', 'height', 'both'] ImageScale = PlainText # = Literal['false', 'true', 'width', 'height', 'both']
Color = PlainText # Two-letter color name = Literal[wv_colors._color_hex.keys()] Color = PlainText # Two-letter color name = Literal[wv_colors._color_hex.keys()]
ColorMode = PlainText # = Literal['full', 'FULL', 'hex', 'HEX', 'short', 'SHORT', 'ger', 'GER']
ColorScheme = PlainText # Color scheme name = Literal[wv_colors.COLOR_CODES.keys()] ColorScheme = PlainText # Color scheme name = Literal[wv_colors.COLOR_CODES.keys()]
# Type combinations # Type combinations
@ -31,6 +32,19 @@ NoneOrMorePinIndices = Union[PinIndex, Tuple[PinIndex, ...], None] # None, one,
OneOrMoreWires = Union[Wire, Tuple[Wire, ...]] # One or a tuple of wires OneOrMoreWires = Union[Wire, Tuple[Wire, ...]] # One or a tuple of wires
@dataclass
class Metadata:
title: PlainText
description: Optional[MultilineHypertext] = None
notes: Optional[MultilineHypertext] = None
@dataclass
class Options:
color_mode: ColorMode = 'SHORT'
mini_bom_mode: bool = True
@dataclass @dataclass
class Image: class Image:
gv_dir: InitVar[Path] # Directory of .gv file injected as context during parsing gv_dir: InitVar[Path] # Directory of .gv file injected as context during parsing

View File

@ -4,12 +4,13 @@
from graphviz import Graph from graphviz import Graph
from collections import Counter from collections import Counter
from typing import List, Union from typing import List, Union
from dataclasses import dataclass
from pathlib import Path from pathlib import Path
from itertools import zip_longest from itertools import zip_longest
import re import re
from wireviz import wv_colors, __version__, APP_NAME, APP_URL from wireviz import wv_colors, __version__, APP_NAME, APP_URL
from wireviz.DataClasses import Connector, Cable from wireviz.DataClasses import Metadata, Options, Connector, Cable
from wireviz.wv_colors import get_color_hex from wireviz.wv_colors import get_color_hex
from wireviz.wv_gv_html import nested_html_table, html_colorbar, html_image, \ from wireviz.wv_gv_html import nested_html_table, html_colorbar, html_image, \
html_caption, remove_links, html_line_breaks html_caption, remove_links, html_line_breaks
@ -20,11 +21,12 @@ from wireviz.wv_helper import awg_equiv, mm2_equiv, tuplelist2tsv, flatten2d, \
open_file_read, open_file_write open_file_read, open_file_write
@dataclass
class Harness: class Harness:
metadata: Metadata
options: Options
def __init__(self): def __post_init__(self):
self.color_mode = 'SHORT'
self.mini_bom_mode = True
self.connectors = {} self.connectors = {}
self.cables = {} self.cables = {}
self._bom = [] # Internal Cache for generated bom self._bom = [] # Internal Cache for generated bom
@ -232,7 +234,7 @@ class Harness:
wireinfo = [] wireinfo = []
if cable.show_wirenumbers: if cable.show_wirenumbers:
wireinfo.append(str(i)) wireinfo.append(str(i))
colorstr = wv_colors.translate_color(connection_color, self.color_mode) colorstr = wv_colors.translate_color(connection_color, self.options.color_mode)
if colorstr: if colorstr:
wireinfo.append(colorstr) wireinfo.append(colorstr)
if cable.wirelabels: if cable.wirelabels:
@ -368,7 +370,7 @@ class Harness:
with open_file_write(f'{filename}.bom.tsv') as file: with open_file_write(f'{filename}.bom.tsv') as file:
file.write(tuplelist2tsv(bomlist)) file.write(tuplelist2tsv(bomlist))
# HTML output # HTML output
generate_html_output(filename, bomlist) generate_html_output(filename, bomlist, self.metadata)
def bom(self): def bom(self):
if not self._bom: if not self._bom:

View File

@ -13,6 +13,7 @@ if __name__ == '__main__':
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
from wireviz import __version__ from wireviz import __version__
from wireviz.DataClasses import Metadata, Options
from wireviz.Harness import Harness from wireviz.Harness import Harness
from wireviz.wv_helper import expand, open_file_read from wireviz.wv_helper import expand, open_file_read
@ -34,7 +35,11 @@ def parse(yaml_input: str, file_out: (str, Path) = None, return_types: (None, st
yaml_data = yaml.safe_load(yaml_input) yaml_data = yaml.safe_load(yaml_input)
harness = Harness() # Assign default metadata.title here to avoid needing file_out in Metadata.__post_init__().
harness = Harness(
Metadata(**{'title': Path(file_out).stem, **yaml_data.get('metadata', {})}),
Options(**yaml_data.get('options', {})),
)
# add items # add items
sections = ['connectors', 'cables', 'connections'] sections = ['connectors', 'cables', 'connections']

View File

@ -32,7 +32,7 @@ def get_additional_component_table(harness: "Harness", component: Union[Connecto
'qty': part.qty * component.get_qty_multiplier(part.qty_multiplier), 'qty': part.qty * component.get_qty_multiplier(part.qty_multiplier),
'unit': part.unit, 'unit': part.unit,
} }
if harness.mini_bom_mode: if harness.options.mini_bom_mode:
id = get_bom_index(harness.bom(), bom_entry_key({**asdict(part), 'description': part.description})) id = get_bom_index(harness.bom(), bom_entry_key({**asdict(part), 'description': part.description}))
rows.append(component_table_entry(f'#{id} ({part.type.rstrip()})', **common_args)) rows.append(component_table_entry(f'#{id} ({part.type.rstrip()})', **common_args))
else: else:

View File

@ -2,21 +2,26 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from pathlib import Path from pathlib import Path
from typing import List, Union
import re import re
from wireviz import __version__, APP_NAME, APP_URL from wireviz import __version__, APP_NAME, APP_URL
from wireviz.DataClasses import Metadata
from wireviz.wv_helper import flatten2d, open_file_read, open_file_write from wireviz.wv_helper import flatten2d, open_file_read, open_file_write
def generate_html_output(filename: (str, Path), bom_list): def generate_html_output(filename: Union[str, Path], bom_list: List[List[str]], metadata: Metadata):
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 lang="en"><head>\n') file.write('<html lang="en"><head>\n')
file.write(' <meta charset="UTF-8">\n') file.write(' <meta charset="UTF-8">\n')
file.write(f' <meta name="generator" content="{APP_NAME} {__version__} - {APP_URL}">\n') file.write(f' <meta name="generator" content="{APP_NAME} {__version__} - {APP_URL}">\n')
file.write(f' <title>{APP_NAME} Diagram and BOM</title>\n') file.write(f' <title>{metadata.title}</title>\n')
file.write('</head><body style="font-family:Arial">\n') file.write('</head><body style="font-family:Arial">\n')
file.write('<h1>Diagram</h1>') file.write(f'<h1>{metadata.title}</h1>\n')
if metadata.description:
file.write(f'<p>{metadata.description}</p>\n')
file.write('<h2>Diagram</h2>\n')
with open_file_read(f'{filename}.svg') as svg: with open_file_read(f'{filename}.svg') as svg:
file.write(re.sub( file.write(re.sub(
'^<[?]xml [^?>]*[?]>[^<]*<!DOCTYPE [^>]*>', '^<[?]xml [^?>]*[?]>[^<]*<!DOCTYPE [^>]*>',
@ -25,7 +30,7 @@ def generate_html_output(filename: (str, Path), bom_list):
for svgdata in svg: for svgdata in svg:
file.write(svgdata) file.write(svgdata)
file.write('<h1>Bill of Materials</h1>') file.write('<h2>Bill of Materials</h2>\n')
listy = flatten2d(bom_list) listy = flatten2d(bom_list)
file.write('<table style="border:1px solid #000000; font-size: 14pt; border-spacing: 0px">') file.write('<table style="border:1px solid #000000; font-size: 14pt; border-spacing: 0px">')
file.write('<tr>') file.write('<tr>')
@ -39,6 +44,9 @@ def generate_html_output(filename: (str, Path), bom_list):
align = 'text-align:right; ' if listy[0][i] == 'Qty' else '' align = 'text-align:right; ' if listy[0][i] == 'Qty' else ''
file.write(f'<td style="{align}border:1px solid #000000; padding: 4px">{item_str}</td>') file.write(f'<td style="{align}border:1px solid #000000; padding: 4px">{item_str}</td>')
file.write('</tr>') file.write('</tr>')
file.write('</table>') file.write('</table>\n')
if metadata.notes:
file.write(f'<h2>Notes</h2>\n<p>{metadata.notes}</p>\n')
file.write('</body></html>') file.write('</body></html>')