1
0

feat: support save feature for dataset

This commit is contained in:
2026-06-28 13:55:03 +08:00
parent 5ad3e11836
commit 215146bf59
3 changed files with 116 additions and 19 deletions

View File

@@ -26,7 +26,7 @@ class AppResolver(enum.StrEnum):
"""The BFS resolver.""" """The BFS resolver."""
@dataclass @dataclass(frozen=True)
class AppConfig: class AppConfig:
""" """
The configuration for the app. The configuration for the app.

View File

@@ -1,9 +1,26 @@
import enum import enum
from typing import Iterable from dataclasses import dataclass
from typing import Iterable, Iterator
from pathlib import Path from pathlib import Path
from .common import LcrConnException from .common import LcrConnException
@dataclass(frozen=True)
class DatasetItem:
value: float
"""The actual value of this item."""
str_value: str
"""The string form of this value given from original input for re-saving."""
def __post_init__(self):
value = self.value
if value <= 0:
raise ValueError(f"Invalid value {value} in dataset")
str_value = self.str_value
if len(str_value) == 0:
raise ValueError(f"Unexpected empty string in dataset item")
class Dataset: class Dataset:
""" """
A list holding available standard values for resistor, capacitor or inductor. A list holding available standard values for resistor, capacitor or inductor.
@@ -14,27 +31,34 @@ class Dataset:
This list will only contain 100 and 4.7k. This list will only contain 100 and 4.7k.
""" """
__values: tuple[float, ...] __values: tuple[DatasetItem, ...]
"""A list of available device gauge values""" """A list of available device gauge values"""
def __init__(self, values: tuple[float, ...]): def __init__(self, str_values: Iterable[str]):
# Check redundant parts # Check string form value one by one
valueset = set(values) value_items: list[DatasetItem] = []
if len(valueset) != len(values): value_set: set[float] = set()
raise LcrConnException(f"Duplicate item in standard value list") for str_value in str_values:
if len(valueset) == 0: # Try parsing value
value = from_human_readable_value(str_value)
# Check and update set
if value in value_set:
raise LcrConnException(
f"Duplicate item {str_value} in standard value list"
)
else:
value_set.add(value)
# Add into result
value_items.append(DatasetItem(value, str_value))
# Check empty case
if len(value_items) == 0:
raise LcrConnException(f"Empty standard value list is not allowed") raise LcrConnException(f"Empty standard value list is not allowed")
# Ok, assign it # Ok, assign it
self.__values = values self.__values = tuple(value_items)
@staticmethod @staticmethod
def from_iterable(stringfied_values: Iterable[str]) -> "Dataset": def from_iterable(stringfied_values: Iterable[str]) -> "Dataset":
return Dataset( return Dataset(stringfied_values)
tuple(
from_human_readable_value(stringfied_value)
for stringfied_value in stringfied_values
)
)
@staticmethod @staticmethod
def from_text(text: str) -> "Dataset": def from_text(text: str) -> "Dataset":
@@ -48,14 +72,27 @@ class Dataset:
legal_lines = filter(lambda line: line != "", (line.strip() for line in f)) legal_lines = filter(lambda line: line != "", (line.strip() for line in f))
return Dataset.from_iterable(legal_lines) return Dataset.from_iterable(legal_lines)
def __save(self) -> Iterator[str]:
return map(lambda i: i.str_value, self.__values)
def save_iterator(self) -> Iterator[str]:
return self.__save()
def save_text(self) -> str:
return "\n".join(self.__save())
def save_file(self, filename: Path) -> None:
with open(filename, "w", encoding="utf-8") as f:
f.write(self.save_text())
@property @property
def values(self) -> tuple[float, ...]: def values(self) -> Iterator[float]:
""" """
Get the available standard values Get the available standard values
:return: A tuple of available standard values :return: A tuple of available standard values
""" """
return self.__values return map(lambda i: i.value, self.__values)
class DatasetCollection: class DatasetCollection:
@@ -79,6 +116,14 @@ class DatasetCollection:
def from_iterable( def from_iterable(
resistor: Iterable[str], capacitor: Iterable[str], inductor: Iterable[str] resistor: Iterable[str], capacitor: Iterable[str], inductor: Iterable[str]
) -> "DatasetCollection": ) -> "DatasetCollection":
"""
Load the standard values for resistor, capacitor and inductor respectively from iterables.
:param resistor: The iterable to load available standard values for resistor
:param capacitor: The iterable to load available standard values for capacitor
:param inductor: The iterable to load available standard values for inductor
:return: The built dataset collection
"""
return DatasetCollection( return DatasetCollection(
Dataset.from_iterable(resistor), Dataset.from_iterable(resistor),
Dataset.from_iterable(capacitor), Dataset.from_iterable(capacitor),
@@ -87,6 +132,14 @@ class DatasetCollection:
@staticmethod @staticmethod
def from_text(resistor: str, capacitor: str, inductor: str) -> "DatasetCollection": def from_text(resistor: str, capacitor: str, inductor: str) -> "DatasetCollection":
"""
Load the standard values for resistor, capacitor and inductor respectively from strings.
:param resistor: The string to load available standard values for resistor
:param capacitor: The string to load available standard values for capacitor
:param inductor: The string to load available standard values for inductor
:return: The built dataset collection
"""
return DatasetCollection( return DatasetCollection(
Dataset.from_text(resistor), Dataset.from_text(resistor),
Dataset.from_text(capacitor), Dataset.from_text(capacitor),
@@ -97,12 +150,56 @@ class DatasetCollection:
def from_file( def from_file(
resistor: Path, capacitor: Path, inductor: Path resistor: Path, capacitor: Path, inductor: Path
) -> "DatasetCollection": ) -> "DatasetCollection":
"""
Load the standard values for resistor, capacitor and inductor respectively from files.
:param resistor: The file to load available standard values for resistor
:param capacitor: The file to load available standard values for capacitor
:param inductor: The file to load available standard values for inductor
:return: The built dataset collection
"""
return DatasetCollection( return DatasetCollection(
Dataset.from_file(resistor), Dataset.from_file(resistor),
Dataset.from_file(capacitor), Dataset.from_file(capacitor),
Dataset.from_file(inductor), Dataset.from_file(inductor),
) )
def save_iterator(self) -> tuple[Iterator[str], Iterator[str], Iterator[str]]:
"""
Get the iterator of available standard values for resistor, capacitor and inductor respectively.
:return: A tuple of iterators of available standard values for resistor, capacitor and inductor respectively.
"""
return (
self.__resistor.save_iterator(),
self.__capacitor.save_iterator(),
self.__inductor.save_iterator(),
)
def save_text(self) -> tuple[str, str, str]:
"""
Get the string form of available standard values for resistor, capacitor and inductor respectively.
:return: A tuple of strings of available standard values for resistor, capacitor and inductor respectively.
"""
return (
self.__resistor.save_text(),
self.__capacitor.save_text(),
self.__inductor.save_text(),
)
def save_file(self, resistor: Path, capacitor: Path, inductor: Path) -> None:
"""
Save the available standard values for resistor, capacitor and inductor respectively to files.
:param resistor: The file to save available standard values for resistor
:param capacitor: The file to save available standard values for capacitor
:param inductor: The file to save available standard values for inductor
"""
self.__resistor.save_file(resistor)
self.__capacitor.save_file(capacitor)
self.__inductor.save_file(inductor)
@property @property
def resistor_values(self) -> Dataset: def resistor_values(self) -> Dataset:
""" """

View File

@@ -20,7 +20,7 @@ MAX_RESPONSE_CNT: int = 50
"""The maximum count for the response item count passed in request.""" """The maximum count for the response item count passed in request."""
@dataclass @dataclass(frozen=True)
class Request: class Request:
""" """
All request infomation for the resolver. All request infomation for the resolver.