diff options
Diffstat (limited to 'tools/cru-py/cru/config.py')
-rw-r--r-- | tools/cru-py/cru/config.py | 147 |
1 files changed, 58 insertions, 89 deletions
diff --git a/tools/cru-py/cru/config.py b/tools/cru-py/cru/config.py index 843f30a..3fd994b 100644 --- a/tools/cru-py/cru/config.py +++ b/tools/cru-py/cru/config.py @@ -1,22 +1,35 @@ -from typing import Any, TypeVar, Generic - -from .error import CruInternalLogicError -from .value import ValueType, ValueGenerator, ValidationError - -T = TypeVar("T") - - -class ConfigItem(Generic[T]): - OptionalValueGenerator = ValueGenerator[T, []] | None - - def __init__(self, name: str, description: str, value_type: ValueType[T], value: T | None, default_value: T, *, - value_generator: OptionalValueGenerator = None) -> None: +from typing import TypeVar, Generic +import copy + + +from .list import CruUniqueKeyList +from ._error import CruInternalError +from .value import ( + CruValueTypeError, + ValueGeneratorBase, + ValueType, +) + +_T = TypeVar("_T") + + +class ConfigItem(Generic[_T]): + def __init__( + self, + name: str, + description: str, + value_type: ValueType[_T], + value: _T | None, + default_value: _T, + *, + value_generator: ValueGeneratorBase | None = None, + ) -> None: self._name = name self._description = description self._value_type = value_type self._default_value = default_value self._value_generator = value_generator - self._value: T | None = value + self._value = value @property def name(self) -> str: @@ -27,11 +40,11 @@ class ConfigItem(Generic[T]): return self._description @property - def value_type(self) -> ValueType[T]: + def value_type(self) -> ValueType[_T]: return self._value_type @property - def default_value(self) -> T: + def default_value(self) -> _T: return self._default_value @property @@ -43,86 +56,42 @@ class ConfigItem(Generic[T]): return not self.is_default @property - def value(self) -> T: + def value(self) -> _T: return self._value or self._default_value - def set_value(self, v: T | str, /, allow_convert_from_str=False): + @property + def value_generator(self) -> ValueGeneratorBase | None: + return self._value_generator + + def set_value(self, v: _T | str, /, allow_convert_from_str=False): if allow_convert_from_str: self._value = self.value_type.check_value(v) else: self._value = self.value_type.check_value_or_try_convert_from_str(v) - @value.setter - def value(self, v: T) -> None: - self.set_value(v) - - @property - def value_generator(self) -> OptionalValueGenerator: - return self._value_generator - - def generate_value(self, allow_interactive=False) -> T | None: - if self.value_generator is None: return None - if self.value_generator.interactive and not allow_interactive: + def generate_value(self) -> _T | None: + if self.value_generator is None: return None - else: - v = self.generate_value() - try: - self.value_type.check_value(v) - return v - except ValidationError as e: - raise CruInternalLogicError("Config value generator returns invalid value.", name=self.name, inner=e) + v = self.generate_value() + try: + self.value_type.check_value(v) + return v + except CruValueTypeError as e: + raise CruInternalError( + "Config value generator returns invalid value." + ) from e def copy(self) -> "ConfigItem": - return ConfigItem(self.name, self.description, self.value_type, - self._value.copy() if self._value is not None else None, self._default_value.copy(), - value_generator=self.value_generator) - - -class Configuration: - def __init__(self, items: None | list[ConfigItem] = None) -> None: - self._items: list[ConfigItem] = items or [] - - @property - def items(self) -> list[ConfigItem]: - return self._items - - @property - def item_map(self) -> dict[str, ConfigItem]: - return {i.name: i for i in self.items} - - def get_optional_item(self, name: str) -> ConfigItem | None: - for i in self.items: - if i.name == name: - return i - return None - - def clear(self) -> None: - self._items.clear() - - def has_item(self, name: str) -> bool: - return self.get_optional_item(name) is not None - - def add_item(self, item: ConfigItem): - i = self.get_optional_item(item.name) - if i is not None: - raise CruInternalLogicError("Config item of the name already exists.", name=item.name) - self.items.append(item) - return item - - def set_value(self, name: str, v: Any, /, allow_convert_from_str=False): - i = self.get_optional_item(name) - if i is None: - raise CruInternalLogicError("No config item of the name. Can't set value.", name=name) - i.set_value(v, allow_convert_from_str) - - def copy(self) -> "Configuration": - return Configuration([i.copy() for i in self.items]) - - def __getitem__(self, name: str) -> ConfigItem: - i = self.get_optional_item(name) - if i is not None: - return i - raise CruInternalLogicError('No config item of the name.', name=name) - - def __contains__(self, name: str): - return self.has_item(name) + return ConfigItem( + self.name, + self.description, + self.value_type, + copy.deepcopy(self._value) if self._value is not None else None, + copy.deepcopy(self._default_value), + value_generator=self.value_generator, + ) + + +class Configuration(CruUniqueKeyList[ConfigItem, str]): + def __init__(self): + super().__init__(lambda c: c.name) |