diff --git a/src/wireviz/DataClasses.py b/src/wireviz/DataClasses.py index 6b7462a..60e544e 100644 --- a/src/wireviz/DataClasses.py +++ b/src/wireviz/DataClasses.py @@ -6,7 +6,7 @@ from pathlib import Path from wireviz.wv_helper import int2tuple, aspect_ratio from wireviz.wv_colors import Color, Colors, ColorMode, ColorScheme, COLOR_CODES - +from wireviz.wv_bom_new import Bom_hash, Bom_hash_list # Each type alias have their legal values described in comments - validation might be implemented in the future PlainText = str # Text not containing HTML tags nor newlines @@ -115,6 +115,18 @@ class AdditionalComponent: def description(self) -> str: return self.type.rstrip() + (f', {self.subtype.rstrip()}' if self.subtype else '') + @property + def bom_hash(self) -> Bom_hash: + return Bom_hash( + self.description, + self.unit, + self.pn, + self.manufacturer, + self.mpn, + self.supplier, + self.spn, + ) + @dataclass class Connector: @@ -188,6 +200,8 @@ class Connector: if isinstance(item, dict): self.additional_components[i] = AdditionalComponent(**item) + print(self.bom_hash) + def activate_pin(self, pin: Pin) -> None: self.visible_pins[pin] = True @@ -201,6 +215,28 @@ class Connector: else: raise ValueError(f'invalid qty multiplier parameter for connector {qty_multiplier}') + @property + def description(self) -> str: + substrs = [ + 'Connector', + self.type, + self.subtype, + self.pincount if self.show_pincount else None, + str(self.color) + ' (reimplement color translation!)' if self.color else None, # translate_color(self.color, harness.options.color_mode)] <- get harness.color_mode! + ] + return ', '.join([str(s) for s in substrs if s is not None and s != '']) + + @property + def bom_hash(self) -> Bom_hash: + return Bom_hash( + self.description, + None, + self.pn, + self.manufacturer, + self.mpn, + self.supplier, + self.spn, + ) @dataclass class Cable: @@ -318,6 +354,12 @@ class Cable: if isinstance(item, dict): self.additional_components[i] = AdditionalComponent(**item) + if self.category == 'bundle': + [print(elem) for elem in self.bom_hash] + else: + print(self.bom_hash) + + # The *_pin arguments accept a tuple, but it seems not in use with the current code. def connect(self, from_name: Optional[Designator], from_pin: NoneOrMorePinIndices, via_wire: OneOrMoreWires, to_name: Optional[Designator], to_pin: NoneOrMorePinIndices) -> None: @@ -343,6 +385,71 @@ class Cable: else: raise ValueError(f'invalid qty multiplier parameter for cable {qty_multiplier}') + @property + def description(self) -> str: + if self.category == 'bundle': + desc_list = [] + for index, color in enumerate(self.colors): + substrs = [ + 'Wire', + self.type, + f'{self.gauge} {self.gauge_unit}' if self.gauge else None, + str(self.color) + ' (reimplement color translation!)' if self.color else None, # translate_color(self.color, harness.options.color_mode)] <- get harness.color_mode! + ] + desc_list.append(', '.join([s for s in substrs if s is not None and s != ''])) + return desc_list + else: + substrs = [ + ('', 'Cable'), + (', ', self.type), + (', ', self.wirecount), + (' ', f'x {self.gauge} {self.gauge_unit}' if self.gauge else ' wires'), + (' ', 'shielded' if self.shield else None), + (', ', str(self.color) + ' (reimplement color translation!)' if self.color else None) + ] + desc = ''.join([f'{s[0]}{s[1]}' for s in substrs if s[1] is not None and s[1] != '']) + return desc + + + @property + def bom_hash(self) -> Bom_hash: + + def force_list(inp): + if isinstance(inp, list): + return inp + else: + return [inp for i in range(len(self.colors))] + + if self.category == 'bundle': + # create a single item that includes the necessary fields, + # which may or may not be lists + _hash_list = Bom_hash_list( + self.description, + self.length_unit, + self.pn, + self.manufacturer, + self.mpn, + self.supplier, + self.spn, + ) + # convert elements that are not lists, into lists + _hash_matrix = list(map(force_list, [elem for elem in _hash_list])) + # transpose list of lists, convert to tuple for next step + _hash_matrix = list(map(tuple, zip(*_hash_matrix))) + # generate list of Bom_hashes + hash_list = [Bom_hash(*item) for item in _hash_matrix] + return hash_list + else: + return Bom_hash( + self.description, + self.length_unit, + self.pn, + self.manufacturer, + self.mpn, + self.supplier, + self.spn, + ) + @dataclass class Connection: diff --git a/src/wireviz/Harness.py b/src/wireviz/Harness.py index b362eef..068edf7 100644 --- a/src/wireviz/Harness.py +++ b/src/wireviz/Harness.py @@ -17,6 +17,7 @@ from wireviz.wv_gv_html import nested_html_table, \ # from wireviz.wv_bom import pn_info_string, component_table_entry, \ # get_additional_component_table, bom_list, generate_bom, \ # HEADER_PN, HEADER_MPN, HEADER_SPN +from wireviz.wv_bom_new import pn_info_string, HEADER_PN, HEADER_MPN, HEADER_SPN from wireviz.wv_html import generate_html_output from wireviz.wv_helper import awg_equiv, mm2_equiv, tuplelist2tsv, flatten2d, \ open_file_read, open_file_write diff --git a/src/wireviz/wv_bom_new.py b/src/wireviz/wv_bom_new.py new file mode 100644 index 0000000..b350d48 --- /dev/null +++ b/src/wireviz/wv_bom_new.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- + +from collections import namedtuple +from typing import Any, Dict, List, Optional, Tuple, Union + +BOM_HASH_FIELDS = 'description unit pn manufacturer mpn supplier spn' +Bom_hash = namedtuple('bom_item', BOM_HASH_FIELDS) +Bom_hash_list = namedtuple('bom_hash_list', BOM_HASH_FIELDS) + +HEADER_PN = 'P/N' +HEADER_MPN = 'MPN' +HEADER_SPN = 'SPN' + +def pn_info_string(header: str, name: Optional[str], number: Optional[str]) -> Optional[str]: + """Return the company name and/or the part number in one single string or None otherwise.""" + number = str(number).strip() if number is not None else '' + if name or number: + return f'{name if name else header}{": " + number if number else ""}' + else: + return None