refactored the base classes
This commit is contained in:
parent
eca68ab14c
commit
6269667798
@ -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)
|
||||||
|
0
src/music_kraken/utils/config/connection.py
Normal file
0
src/music_kraken/utils/config/connection.py
Normal file
0
src/music_kraken/utils/config/misc.py
Normal file
0
src/music_kraken/utils/config/misc.py
Normal file
1
src/music_kraken/utils/exception/__init__.py
Normal file
1
src/music_kraken/utils/exception/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
__all__ = ["config"]
|
25
src/music_kraken/utils/exception/config.py
Normal file
25
src/music_kraken/utils/exception/config.py
Normal 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}'"
|
Loading…
Reference in New Issue
Block a user