Move parse_number_and_unit() and NumberAndUnit definition to wv_utils.py

This commit is contained in:
Daniel Rojas 2024-04-16 14:51:28 +02:00
parent 49556bd81e
commit 3539b2f8fb
2 changed files with 49 additions and 36 deletions

View File

@ -20,7 +20,14 @@ from wireviz.wv_colors import (
SingleColor,
get_color_by_colorcode_index,
)
from wireviz.wv_utils import aspect_ratio, awg_equiv, mm2_equiv, remove_links
from wireviz.wv_utils import (
NumberAndUnit,
awg_equiv,
aspect_ratio,
mm2_equiv,
parse_number_and_unit,
remove_links,
)
# Each type alias have their legal values described in comments
# - validation might be implemented in the future
@ -54,7 +61,6 @@ MetadataKeys = PlainText # Literal['title', 'description', 'notes', ...]
Side = Enum("Side", "LEFT RIGHT")
ArrowDirection = Enum("ArrowDirection", "NONE BACK FORWARD BOTH")
ArrowWeight = Enum("ArrowWeight", "SINGLE DOUBLE")
NumberAndUnit = namedtuple("NumberAndUnit", "number unit")
AUTOGENERATED_PREFIX = "AUTOGENERATED_"
@ -196,34 +202,8 @@ class Component:
partnos = tuple(partnos)
self.partnumbers = PartNumberInfo(*partnos)
self.qty = self.parse_number_and_unit(self.qty, None)
self.amount = self.parse_number_and_unit(self.amount, None)
def parse_number_and_unit(
self,
inp: Optional[Union[NumberAndUnit, float, int, str]],
default_unit: Optional[str] = None,
) -> Optional[NumberAndUnit]:
if inp is None:
return None
elif isinstance(inp, NumberAndUnit):
return inp
elif isinstance(inp, float) or isinstance(inp, int):
return NumberAndUnit(float(inp), default_unit)
elif isinstance(inp, str):
if " " in inp:
number, unit = inp.split(" ", 1)
else:
number, unit = inp, default_unit
try:
number = float(number)
except ValueError:
raise Exception(
f"{inp} is not a valid number and unit.\n"
"It must be a number, or a number and unit separated by a space."
)
else:
return NumberAndUnit(number, unit)
self.qty = parse_number_and_unit(self.qty, None)
self.amount = parse_number_and_unit(self.amount, None)
@property
def bom_hash(self) -> BomHash:
@ -451,7 +431,9 @@ class Connector(TopLevelGraphicalComponent):
raise Exception("Loops must be between exactly two pins!")
for pin in loop:
if pin not in self.pins:
raise Exception(f'Unknown loop pin "{pin}" for connector "{self.name}"!')
raise Exception(
f'Unknown loop pin "{pin}" for connector "{self.name}"!'
)
# Make sure loop connected pins are not hidden.
# side=None, determine side to show loops during rendering
self.activate_pin(pin, side=None, is_connection=True)
@ -675,8 +657,8 @@ class Cable(TopLevelGraphicalComponent):
# allow gauge, length, and other fields to be lists too (like part numbers),
# and assign them the same way to bundles.
self.gauge = self.parse_number_and_unit(self.gauge, "mm2")
self.length = self.parse_number_and_unit(self.length, "m")
self.gauge = parse_number_and_unit(self.gauge, "mm2")
self.length = parse_number_and_unit(self.length, "m")
self.amount = self.length # for BOM
if self.wirecount: # number of wires explicitly defined
@ -753,9 +735,11 @@ class Cable(TopLevelGraphicalComponent):
index=index_offset,
id=id,
label="Shield",
color=MultiColor(self.shield)
if isinstance(self.shield, str)
else MultiColor(None),
color=(
MultiColor(self.shield)
if isinstance(self.shield, str)
else MultiColor(None)
),
parent=self.designator,
)

View File

@ -1,9 +1,12 @@
# -*- coding: utf-8 -*-
import re
from collections import namedtuple
from pathlib import Path
from typing import List, Optional, Union
NumberAndUnit = namedtuple("NumberAndUnit", "number unit")
awg_equiv_table = {
"0.09": "28",
"0.14": "26",
@ -76,6 +79,32 @@ def get_single_key_and_value(d: dict):
return next(iter(d.items()))
def parse_number_and_unit(
inp: Optional[Union[NumberAndUnit, float, int, str]],
default_unit: Optional[str] = None,
) -> Optional[NumberAndUnit]:
if inp is None:
return None
elif isinstance(inp, NumberAndUnit):
return inp
elif isinstance(inp, float) or isinstance(inp, int):
return NumberAndUnit(float(inp), default_unit)
elif isinstance(inp, str):
if " " in inp:
number, unit = inp.split(" ", 1)
else:
number, unit = inp, default_unit
try:
number = float(number)
except ValueError:
raise Exception(
f"{inp} is not a valid number and unit.\n"
"It must be a number, or a number and unit separated by a space."
)
else:
return NumberAndUnit(number, unit)
def int2tuple(inp):
if isinstance(inp, tuple):
output = inp