refactored the base classes

This commit is contained in:
Hellow 2023-04-15 12:30:55 +02:00
parent eca68ab14c
commit 6269667798
5 changed files with 109 additions and 20 deletions

View File

@ -2,6 +2,8 @@ import logging
from dataclasses import dataclass from dataclasses import dataclass
from typing import Optional, List, Union, Dict from typing import Optional, List, Union, Dict
from ..exception.config import SettingNotFound, SettingValueError
COMMENT_PREFIX = "#" COMMENT_PREFIX = "#"
@ -28,16 +30,25 @@ class Attribute:
description: Optional[str] description: Optional[str]
value: Union[str, List[str]] value: Union[str, List[str]]
rule: str = "The setting {name} can't be {value}." def validate(self, value: str):
"""
This function validates a new value without setting it.
:raise SettingValueError:
:param value:
:return:
"""
pass
def set_value(self, value: str): def set_value(self, value: str):
_value = self.value """
:raise SettingValueError: if the value is invalid for this setting
:param value:
:return:
"""
self.validate(value)
self.value = value self.value = value
try:
_ = self.object_from_value
except ValueError:
raise ValueError(self.rule.format(name=self.name, value=self.value))
@property @property
def description_as_comment(self): def description_as_comment(self):
@ -62,34 +73,78 @@ class StringAttribute(SingleAttribute):
class IntAttribute(SingleAttribute): class IntAttribute(SingleAttribute):
rule = "The setting {name} has to be an integer, not {value}" def validate(self, value: str):
if not value.isdigit():
raise SettingValueError(
setting_name=self.name,
setting_value=value,
rule="has to be a digit (an int)"
)
@property @property
def object_from_value(self) -> int: def object_from_value(self) -> int:
if not self.value.isdigit(): if not self.value.isdigit():
raise ValueError(f"The value of {self.name} needs to be an integer, not {self.value}")
return int(self.value) return int(self.value)
class FloatAttribute(SingleAttribute): class FloatAttribute(SingleAttribute):
rule = "The setting {name} has to be a number, not {value}" def validate(self, value: str):
if not value.isnumeric():
raise SettingValueError(
setting_name=self.name,
setting_value=value,
rule="has to be numeric (an int or float)"
)
@property @property
def object_from_value(self) -> float: def object_from_value(self) -> float:
if not self.value.isnumeric(): if self.value.isnumeric():
raise ValueError(f"The value of {self.name} needs to be a number, not {self.value}")
return float(self.value) return float(self.value)
class ListAttribute(Attribute): class ListAttribute(Attribute):
value: List[str] value: List[str]
has_default_values: bool = True
def set_value(self, value: str):
"""
Due to lists being represented as multiple lines with the same key,
this appends, rather than setting anything.
:raise SettingValueError:
:param value:
:return:
"""
self.validate(value)
# resetting the list to an empty list, if this is the first config line to load
if self.has_default_values:
self.value = []
self.value.append(value)
def __str__(self): def __str__(self):
return f"{self.description_as_comment}\n" + \ return f"{self.description_as_comment}\n" + \
"\n".join(f"{self.name}={element}" for element in self.value) "\n".join(f"{self.name}={element}" for element in self.value)
def single_object_from_element(self, value: str):
return value
@property
def object_from_value(self) -> list:
"""
THIS IS NOT THE PROPERTY TO OVERRIDE WHEN INHERETING ListAttribute
:return:
"""
parsed = list()
for raw in self.value:
parsed.append(self.single_object_from_element(raw))
return parsed
@dataclass @dataclass
class Description: class Description:
@ -131,9 +186,17 @@ class Section:
self.name_attribute_map[element.name] = element self.name_attribute_map[element.name] = element
def __setitem__(self, key, value): def modify_setting(self, setting_name: str, new_value: str):
if key not in self.name_attribute_map: """
raise KeyError(f"There is no such setting with the name: {key}") :raise SettingValueError, SettingNotFound:
:param setting_name:
:param new_value:
:return:
"""
attribute = self.name_attribute_map[key] if setting_name not in self.name_attribute_map:
attribute.set_value(value) raise SettingNotFound(
setting_name=setting_name
)
self.name_attribute_map[setting_name].set_value(new_value)

View File

View File

@ -0,0 +1 @@
__all__ = ["config"]

View File

@ -0,0 +1,25 @@
class SettingException(Exception):
pass
class SettingNotFound(SettingException):
def __init__(self, setting_name: str):
self.setting_name = setting_name
class SettingValueError(SettingException):
def __init__(self, setting_name: str, setting_value: str, rule: str):
"""
The rule has to be such, that the following format makes sense:
{name} {rule}, not '{value}'
:param setting_name:
:param setting_value:
:param rule:
"""
self.setting_name = setting_name
self.setting_value = setting_value
self.rule = rule
def __str__(self):
return f"{self.setting_name} {self.rule}, not '{self.setting_value}'"