diff --git a/src/wireviz/tools/build_examples.py b/src/wireviz/tools/build_examples.py
index 575f8a4..6662b77 100755
--- a/src/wireviz/tools/build_examples.py
+++ b/src/wireviz/tools/build_examples.py
@@ -65,15 +65,17 @@ def build_generated(groupkeys):
# collect and iterate input YAML files
yaml_files = [f for f in collect_filenames("Building", key, input_extensions)]
try:
- res = cli([
- "--formats", "ghpstb", # no pdf for now
- "--prepend", yaml_files[0].parent / "metadata.yml",
- *[str(f) for f in yaml_files],
- ])
+ res = cli(
+ [
+ "--formats",
+ "ghpstb", # no pdf for now
+ "--prepend",
+ yaml_files[0].parent / "metadata.yml",
+ *[str(f) for f in yaml_files],
+ ]
+ )
except BaseException as e:
- if str(e) != "0" and not isinstance(
- e, (click.ClickException, SystemExit)
- ):
+ if str(e) != "0" and not isinstance(e, (click.ClickException, SystemExit)):
raise
if build_readme:
@@ -111,6 +113,7 @@ def clean_generated(groupkeys):
print(f' rm "{filename}"')
filename.unlink()
+
def parse_args():
parser = argparse.ArgumentParser(
description=f"{APP_NAME} Example Manager",
diff --git a/src/wireviz/wv_bom.py b/src/wireviz/wv_bom.py
index 0dd0eb8..20291db 100644
--- a/src/wireviz/wv_bom.py
+++ b/src/wireviz/wv_bom.py
@@ -22,7 +22,6 @@ def partnumbers2list(
if not isinstance(partnumbers, list):
partnumbers = [partnumbers]
-
# if there's no parent, fold
if parent_partnumbers is None:
return PartNumberInfo.list_keep_only_eq(partnumbers).str_list
diff --git a/src/wireviz/wv_cli.py b/src/wireviz/wv_cli.py
index 22656d7..aadc4a0 100644
--- a/src/wireviz/wv_cli.py
+++ b/src/wireviz/wv_cli.py
@@ -14,7 +14,12 @@ import yaml
import wireviz.wireviz as wv
from wireviz import APP_NAME, __version__
-from wireviz.wv_output import generate_pdf_output, generate_html_output, generate_shared_bom, generate_titlepage
+from wireviz.wv_output import (
+ generate_pdf_output,
+ generate_html_output,
+ generate_shared_bom,
+ generate_titlepage,
+)
from wireviz.wv_dataclasses import AUTOGENERATED_PREFIX, Metadata, Options
format_codes = {
@@ -108,11 +113,20 @@ epilog = (
@click.option(
"-m",
"--multiplier-file-name",
- default='quantity_multipliers.txt',
+ default="quantity_multipliers.txt",
type=str,
help="name of file used to fetch the qty_multipliers",
)
-def cli(files, formats, prepend, output_dir, output_name, version, use_qty_multipliers, multiplier_file_name):
+def cli(
+ files,
+ formats,
+ prepend,
+ output_dir,
+ output_name,
+ version,
+ use_qty_multipliers,
+ multiplier_file_name,
+):
"""
Parses the provided FILE and generates the specified outputs.
"""
@@ -141,8 +155,8 @@ def cli(files, formats, prepend, output_dir, output_name, version, use_qty_multi
extra_metadata["sheet_current"] += 1
extra_metadata["sheet_total"] += 1
- if 'pdf' in harness_output_formats:
- harness_output_formats.remove('pdf')
+ if "pdf" in harness_output_formats:
+ harness_output_formats.remove("pdf")
# run WireVIz on each input file
for _file in files:
@@ -170,7 +184,6 @@ def cli(files, formats, prepend, output_dir, output_name, version, use_qty_multi
)
shared_bom = ret["shared_bom"]
-
shared_bom_base = None
if "shared_bom" in output_formats:
shared_bom_base, shared_bomlist = generate_shared_bom(
@@ -181,24 +194,27 @@ def cli(files, formats, prepend, output_dir, output_name, version, use_qty_multi
multiplier_file_name=multiplier_file_name,
)
- if ('html' in output_formats) and create_titlepage:
+ if ("html" in output_formats) and create_titlepage:
# TODO: yaml data parsing shared
yaml_data_str = "\n".join(f.open("r").read() for f in prepend)
yaml_data = yaml.safe_load(yaml_data_str)
generate_titlepage(yaml_data, extra_metadata, shared_bom)
- if 'pdf' in output_formats:
- extra_metadata["titlepage"] = extra_metadata["titlepage"].with_suffix('_for_pdf')
+ if "pdf" in output_formats:
+ extra_metadata["titlepage"] = extra_metadata["titlepage"].with_suffix(
+ "_for_pdf"
+ )
if create_titlepage:
- extra_metadata["output_names"].insert(0, extra_metadata["titlepage"].with_suffix('.html'))
+ extra_metadata["output_names"].insert(
+ 0, extra_metadata["titlepage"].with_suffix(".html")
+ )
generate_titlepage(yaml_data, extra_metadata, shared_bom, for_pdf=True)
- if 'pdf' in output_formats:
+ if "pdf" in output_formats:
generate_pdf_output([_output_dir / p for p in extra_metadata["output_names"]])
-
print() # blank line after execution
diff --git a/src/wireviz/wv_dataclasses.py b/src/wireviz/wv_dataclasses.py
index a769e94..ffd36a7 100644
--- a/src/wireviz/wv_dataclasses.py
+++ b/src/wireviz/wv_dataclasses.py
@@ -157,7 +157,9 @@ class PartNumberInfo:
}
def __bool__(self):
- return bool(self.pn or self.manufacturer or self.mpn or self.supplier or self.spn)
+ return bool(
+ self.pn or self.manufacturer or self.mpn or self.supplier or self.spn
+ )
def __hash__(self):
return hash((self.pn, self.manufacturer, self.mpn, self.supplier, self.spn))
@@ -175,7 +177,7 @@ class PartNumberInfo:
empty_if_none = lambda x: "" if x is None else str(x)
if isinstance(self.pn, list):
- raise ValueError(f'pn ({self.pn}) should not be a list')
+ raise ValueError(f"pn ({self.pn}) should not be a list")
self.pn = empty_if_none(self.pn)
self.manufacturer = empty_if_none(self.manufacturer)
self.mpn = empty_if_none(self.mpn)
@@ -222,33 +224,33 @@ class PartNumberInfo:
part = self.copy()
if other is None:
- if op == '==':
+ if op == "==":
return part
- elif op == '!=':
+ elif op == "!=":
return None
else:
- raise NotImplementedError(f'op {op} not supported')
+ raise NotImplementedError(f"op {op} not supported")
if isinstance(other, list):
for item in other:
part = part.clear_per_field(op, item)
else:
for k in ["pn", "manufacturer", "mpn", "supplier", "spn"]:
- if op == '==':
+ if op == "==":
if part[k] == other[k]:
part[k] = ""
- elif op == '!=':
+ elif op == "!=":
if part[k] != other[k]:
part[k] = ""
else:
- raise NotImplementedError(f'op {op} not supported')
+ raise NotImplementedError(f"op {op} not supported")
return part
def keep_only_eq(self, other):
- return self.clear_per_field('!=', other)
+ return self.clear_per_field("!=", other)
def remove_eq(self, other):
- return self.clear_per_field('==', other)
+ return self.clear_per_field("==", other)
@staticmethod
def list_keep_only_eq(partnumbers):
@@ -257,6 +259,7 @@ class PartNumberInfo:
pn = pn.keep_only_eq(p)
return pn
+
@dataclass
class BomEntry:
qty: NumberAndUnit
@@ -277,7 +280,6 @@ class BomEntry:
MAX_PRINTED_DESIGNATORS: int = 2
restrict_printed_lengths: bool = True
-
scaled_per_harness = False
# Map a bom key to the header
@@ -291,7 +293,7 @@ class BomEntry:
}
def __repr__(self):
- return f'{id}: {self.partnumbers}, {self.qty}'
+ return f"{id}: {self.partnumbers}, {self.qty}"
def __hash__(self):
return hash((self.partnumbers, self.description))
@@ -323,9 +325,7 @@ class BomEntry:
setattr(self, key, value)
def __post_init__(self):
- assert isinstance(
- self.qty, NumberAndUnit
- ), f"Unexpected qty type {self.qty}"
+ assert isinstance(self.qty, NumberAndUnit), f"Unexpected qty type {self.qty}"
assert isinstance(
self.partnumbers, PartNumberInfo
), f"Unexpected partnumbers type {self.partnumbers}"
@@ -342,11 +342,13 @@ class BomEntry:
if not isinstance(self.qty_multiplier, str):
self.qty *= float(self.qty_multiplier)
-
@property
def description_str(self):
description = self.description
- if self.restrict_printed_lengths and len(description) > self.MAX_PRINTED_DESCRIPTION:
+ if (
+ self.restrict_printed_lengths
+ and len(description) > self.MAX_PRINTED_DESCRIPTION
+ ):
description = f"{description[:self.MAX_PRINTED_DESCRIPTION]} (...)"
return description
@@ -356,7 +358,10 @@ class BomEntry:
return ""
all_designators = sorted(self.designators)
- if self.restrict_printed_lengths and len(all_designators) > self.MAX_PRINTED_DESIGNATORS:
+ if (
+ self.restrict_printed_lengths
+ and len(all_designators) > self.MAX_PRINTED_DESIGNATORS
+ ):
all_designators = all_designators[: self.MAX_PRINTED_DESIGNATORS] + ["..."]
return ", ".join(all_designators)
@@ -403,18 +408,22 @@ class BomEntry:
def scale_per_harness(self, qty_multipliers):
if self.scaled_per_harness:
- logging.warn('{self}: Already scaled')
+ logging.warn("{self}: Already scaled")
qty = NumberAndUnit(0, self.qty.unit_str)
for name, info in self.per_harness.items():
multiplier_name = [k for k in qty_multipliers.keys() if name.endswith(k)]
if len(multiplier_name) == 0:
- raise ValueError(f'No multiplier found for harness {name} in {qty_multipliers}')
+ raise ValueError(
+ f"No multiplier found for harness {name} in {qty_multipliers}"
+ )
if len(multiplier_name) > 1:
- raise ValueError(f'Conflicting multipliers found ({multiplier_name}) for harness {name} in {qty_multipliers}')
+ raise ValueError(
+ f"Conflicting multipliers found ({multiplier_name}) for harness {name} in {qty_multipliers}"
+ )
- info['qty'] *= qty_multipliers[multiplier_name[0]]
- qty += info['qty']
+ info["qty"] *= qty_multipliers[multiplier_name[0]]
+ qty += info["qty"]
self.qty = qty
self.scaled_per_harness = True
@@ -563,7 +572,7 @@ class Component:
self.qty = NumberAndUnit.to_number_and_unit(self.qty)
self.amount = NumberAndUnit.to_number_and_unit(self.amount)
if isinstance(self.pn, list):
- raise RuntimeError(f'PN ({self.pn}) should not be a list')
+ raise RuntimeError(f"PN ({self.pn}) should not be a list")
for i, item in enumerate(self.additional_components):
if isinstance(item, Component):
@@ -766,15 +775,21 @@ class Connector(GraphicalComponent):
}
for subitem in self.additional_components:
if isinstance(subitem.qty_multiplier, str):
- computed_factor = qty_multipliers_computed[subitem.qty_multiplier.upper()]
- #if isinstance(subitem.qty_multiplier, QtyMultiplierConnector):
+ computed_factor = qty_multipliers_computed[
+ subitem.qty_multiplier.upper()
+ ]
+ # if isinstance(subitem.qty_multiplier, QtyMultiplierConnector):
# computed_factor = qty_multipliers_computed[subitem.qty_multiplier.name.upper()]
- #elif isinstance(subitem.qty_multiplier, QtyMultiplierCable):
+ # elif isinstance(subitem.qty_multiplier, QtyMultiplierCable):
# raise Exception("Used a cable multiplier in a connector!")
- elif isinstance(subitem.qty_multiplier, int) or isinstance(subitem.qty_multiplier, float):
+ elif isinstance(subitem.qty_multiplier, int) or isinstance(
+ subitem.qty_multiplier, float
+ ):
computed_factor = subitem.qty_multiplier
else:
- raise ValueError(f'Unexpected qty multiplier "{subitem.qty_multiplier}"')
+ raise ValueError(
+ f'Unexpected qty multiplier "{subitem.qty_multiplier}"'
+ )
subitem._qty_multiplier_computed = computed_factor
diff --git a/src/wireviz/wv_harness.py b/src/wireviz/wv_harness.py
index 61071fa..f48fb54 100644
--- a/src/wireviz/wv_harness.py
+++ b/src/wireviz/wv_harness.py
@@ -30,7 +30,11 @@ from wireviz.wv_graphviz import (
parse_arrow_str,
set_dot_basics,
)
-from wireviz.wv_output import embed_svg_images_file, generate_html_output, generate_pdf_output
+from wireviz.wv_output import (
+ embed_svg_images_file,
+ generate_html_output,
+ generate_pdf_output,
+)
from wireviz.wv_utils import bom2tsv
diff --git a/src/wireviz/wv_harness_quantity.py b/src/wireviz/wv_harness_quantity.py
index 98c326f..40a6651 100644
--- a/src/wireviz/wv_harness_quantity.py
+++ b/src/wireviz/wv_harness_quantity.py
@@ -4,9 +4,11 @@ import click
import json
import logging
-class HarnessQuantity():
- def __init__(self, harnesses, multiplier_file="quantity_multipliers.txt", output_dir=None):
+class HarnessQuantity:
+ def __init__(
+ self, harnesses, multiplier_file="quantity_multipliers.txt", output_dir=None
+ ):
self.harness_names = [harness.stem for harness in harnesses]
self.multipliers = {}
self.folder = output_dir if output_dir is not None else harnesses[0].parent
@@ -17,11 +19,13 @@ class HarnessQuantity():
def fetch_qty_multipliers_from_file(self):
if self.qty_multipliers.is_file():
- with open(self.qty_multipliers, 'r') as f:
+ with open(self.qty_multipliers, "r") as f:
try:
self.multipliers = json.load(f)
except json.decoder.JSONDecodeError as err:
- raise ValueError(f'Invalid format for file {self.qty_multipliers}, error: {err}')
+ raise ValueError(
+ f"Invalid format for file {self.qty_multipliers}, error: {err}"
+ )
else:
self.get_qty_multipliers_from_user()
self.save_qty_multipliers_to_file()
@@ -29,19 +33,22 @@ class HarnessQuantity():
def check_all_multipliers_defined(self):
for name in self.harness_names:
- assert name in self.multipliers, \
- f"No multiplier defined for harness {name}, maybe delete the multiplier_file {self.qty_multipliers}"
+ assert (
+ name in self.multipliers
+ ), f"No multiplier defined for harness {name}, maybe delete the multiplier_file {self.qty_multipliers}"
def get_qty_multipliers_from_user(self):
for name in self.harness_names:
try:
- self.multipliers[name] = int(input("Quantity multiplier for {}? ".format(name)))
+ self.multipliers[name] = int(
+ input("Quantity multiplier for {}? ".format(name))
+ )
except ValueError:
logging.warning("Quantity multiplier must be an integer!")
break
def save_qty_multipliers_to_file(self):
- with open(self.qty_multipliers,"w") as f:
+ with open(self.qty_multipliers, "w") as f:
json.dump(self.multipliers, f)
def retrieve_harness_qty_multiplier(self, bom_file):
@@ -63,7 +70,7 @@ class HarnessQuantity():
@click.option(
"-m",
"--multiplier-file-name",
- default='quantity_multipliers.txt',
+ default="quantity_multipliers.txt",
type=str,
help="name of file used to fetch or save the qty_multipliers",
)
@@ -82,4 +89,3 @@ def qty_multipliers(files, multiplier_file_name, force_new):
harnesses.fetch_qty_multipliers_from_file()
qty_multipliers = harnesses.multipliers
return
-
diff --git a/src/wireviz/wv_output.py b/src/wireviz/wv_output.py
index d40d789..9ad21d0 100644
--- a/src/wireviz/wv_output.py
+++ b/src/wireviz/wv_output.py
@@ -64,26 +64,27 @@ def embed_svg_images_file(
def generate_pdf_output(
filename_list: List[Path],
- options: Dict=None,
+ options: Dict = None,
):
- '''Generate a pdf output, options are ignored for now, expect the formatting
- to be done within the html files
- '''
+ """Generate a pdf output, options are ignored for now, expect the formatting
+ to be done within the html files
+ """
if isinstance(filename_list, Path):
filename_list = [filename_list]
- output_path = filename_list[0].with_suffix('.pdf')
+ output_path = filename_list[0].with_suffix(".pdf")
else:
output_dir = filename_list[0].parent
- output_path = (output_dir / output_dir.name).with_suffix('.pdf')
+ output_path = (output_dir / output_dir.name).with_suffix(".pdf")
- filepath_list = [f.with_suffix('.html') for f in filename_list]
+ filepath_list = [f.with_suffix(".html") for f in filename_list]
- print(f'Generating pdf output: {output_path}')
+ print(f"Generating pdf output: {output_path}")
files_html = [HTML(path) for path in filepath_list]
documents = [f.render() for f in files_html]
all_pages = [p for doc in documents for p in doc.pages]
documents[0].copy(all_pages).write_pdf(output_path)
+
def generate_shared_bom(
output_dir,
shared_bom,
@@ -93,13 +94,13 @@ def generate_shared_bom(
):
shared_bom_base = output_dir / "shared_bom"
shared_bom_file = shared_bom_base.with_suffix(".tsv")
- print(f'Generating shared bom at {shared_bom_base}')
+ print(f"Generating shared bom at {shared_bom_base}")
if use_qty_multipliers:
harnesses = HarnessQuantity(files, multiplier_file_name, output_dir=output_dir)
harnesses.fetch_qty_multipliers_from_file()
qty_multipliers = harnesses.multipliers
- print(f'Using quantity multipliers: {qty_multipliers}')
+ print(f"Using quantity multipliers: {qty_multipliers}")
for bom_item in shared_bom.values():
bom_item.scale_per_harness(qty_multipliers)
@@ -121,7 +122,7 @@ def generate_html_output(
template_name = metadata.get("template", {}).get("name", "simple")
svgdata = None
- if template_name != 'titlepage':
+ if template_name != "titlepage":
# embed SVG diagram for all but the titlepage
with filename.with_suffix(".svg").open("r") as f:
svgdata = re.sub(
@@ -133,7 +134,9 @@ def generate_html_output(
# generate BOM table
# generate BOM header (may be at the top or bottom of the table)
- bom_reversed = False if template_name == "simple" or template_name == "titlepage" else True
+ bom_reversed = (
+ False if template_name == "simple" or template_name == "titlepage" else True
+ )
bom_header = bom[0]
bom_columns = [
"bom_col_{}".format("id" if c == "#" else c.lower()) for c in bom_header
@@ -142,7 +145,6 @@ def generate_html_output(
if bom_reversed:
bom_content.reverse()
-
if metadata:
sheet_current = metadata["sheet_current"]
sheet_total = metadata["sheet_total"]
@@ -217,39 +219,37 @@ def generate_html_output(
# save generated file
filename.with_suffix(".html").open("w").write(page_rendered)
+
def generate_titlepage(yaml_data, extra_metadata, shared_bom, for_pdf=False):
- print('Generating titlepage')
+ print("Generating titlepage")
index_table_content = []
- index_table_content.append((
- 1, extra_metadata['titlepage'], ''
- ))
-
- for index, page_name in enumerate(extra_metadata['output_names']):
- index_table_content.append((
- index+2, page_name, ''
- ))
+ index_table_content.append((1, extra_metadata["titlepage"], ""))
+ for index, page_name in enumerate(extra_metadata["output_names"]):
+ index_table_content.append((index + 2, page_name, ""))
if not for_pdf:
- index_table_content = [(
- p[0],
- f"{p[1]}",
- p[2],
- ) for p in index_table_content]
+ index_table_content = [
+ (
+ p[0],
+ f"{p[1]}",
+ p[2],
+ )
+ for p in index_table_content
+ ]
-
- #if create_titlepage:
+ # if create_titlepage:
# extra_metadata["index_table_content"].append([
# sheet_current,
# f"{extra_metadata['sheet_name']}",
# "",
# ])
- #index_table_content.insert(0, [
+ # index_table_content.insert(0, [
# 1,
# f"Title Page",
# ''
- #])
+ # ])
titlepage_metadata = {
**yaml_data.get("metadata", {}),
@@ -262,7 +262,7 @@ def generate_titlepage(yaml_data, extra_metadata, shared_bom, for_pdf=False):
"bom_updated_position": "top: 20mm; left: 10mm",
"notes_width": "200mm",
}
- titlepage_metadata['template']['name'] = 'titlepage'
+ titlepage_metadata["template"]["name"] = "titlepage"
titlepage_options = {
"show_bom": True,
"show_index_table": True,
@@ -270,8 +270,8 @@ def generate_titlepage(yaml_data, extra_metadata, shared_bom, for_pdf=False):
**yaml_data.get("options", {}),
}
generate_html_output(
- extra_metadata['output_dir']/ extra_metadata['titlepage'],
- bom = bom_list(shared_bom),
- metadata = Metadata(**titlepage_metadata), # TBD what we need to add here
- options = Options(**titlepage_options),
+ extra_metadata["output_dir"] / extra_metadata["titlepage"],
+ bom=bom_list(shared_bom),
+ metadata=Metadata(**titlepage_metadata), # TBD what we need to add here
+ options=Options(**titlepage_options),
)
diff --git a/src/wireviz/wv_templates.py b/src/wireviz/wv_templates.py
index e48e6ce..766fcb0 100644
--- a/src/wireviz/wv_templates.py
+++ b/src/wireviz/wv_templates.py
@@ -1,11 +1,9 @@
from pathlib import Path
import jinja2
+
def get_template(template_name, extension=""):
- template_file_path = jinja2.FileSystemLoader(
- Path(__file__).parent / "templates"
- )
+ template_file_path = jinja2.FileSystemLoader(Path(__file__).parent / "templates")
jinja_env = jinja2.Environment(loader=template_file_path)
return jinja_env.get_template(template_name + extension)
-