finished the core mechanic behind the config file
This commit is contained in:
parent
8143bb6608
commit
43de7f48c6
@ -4,4 +4,3 @@ from .audio import AUDIO_SECTION
|
|||||||
from .config import read, write
|
from .config import read, write
|
||||||
|
|
||||||
read()
|
read()
|
||||||
write()
|
|
||||||
|
@ -122,6 +122,7 @@ There are multiple fields, you can use for the path and file name:
|
|||||||
self.DEFAULT_LABEL,
|
self.DEFAULT_LABEL,
|
||||||
self.DEFAULT_SONG
|
self.DEFAULT_SONG
|
||||||
]
|
]
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
|
||||||
AUDIO_SECTION = AudioSection()
|
AUDIO_SECTION = AudioSection()
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
|
import logging
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Optional, List, Union
|
from typing import Optional, List, Union, Dict
|
||||||
|
|
||||||
COMMENT_PREFIX = "#"
|
COMMENT_PREFIX = "#"
|
||||||
|
|
||||||
@ -27,6 +28,17 @@ 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 set_value(self, value: str):
|
||||||
|
_value = self.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):
|
||||||
return comment_string(self.description)
|
return comment_string(self.description)
|
||||||
@ -50,6 +62,8 @@ class StringAttribute(SingleAttribute):
|
|||||||
|
|
||||||
|
|
||||||
class IntAttribute(SingleAttribute):
|
class IntAttribute(SingleAttribute):
|
||||||
|
rule = "The setting {name} has to be an integer, not {value}"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def object_from_value(self) -> int:
|
def object_from_value(self) -> int:
|
||||||
if not self.value.isdigit():
|
if not self.value.isdigit():
|
||||||
@ -59,6 +73,8 @@ class IntAttribute(SingleAttribute):
|
|||||||
|
|
||||||
|
|
||||||
class FloatAttribute(SingleAttribute):
|
class FloatAttribute(SingleAttribute):
|
||||||
|
rule = "The setting {name} has to be a number, not {value}"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def object_from_value(self) -> float:
|
def object_from_value(self) -> float:
|
||||||
if not self.value.isnumeric():
|
if not self.value.isnumeric():
|
||||||
@ -97,5 +113,27 @@ class Section:
|
|||||||
Description
|
Description
|
||||||
]]
|
]]
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.name_attribute_map: Dict[str, Attribute] = dict()
|
||||||
|
self.index_values()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "\n".join(attribute.__str__() for attribute in self.attribute_list)
|
return "\n".join(attribute.__str__() for attribute in self.attribute_list)
|
||||||
|
|
||||||
|
def index_values(self):
|
||||||
|
for element in self.attribute_list:
|
||||||
|
if not isinstance(element, Attribute):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if element.name in self.name_attribute_map:
|
||||||
|
raise ValueError(f"Two different Attributes have the same name: "
|
||||||
|
f"{self.name_attribute_map[element.name]} {element}")
|
||||||
|
|
||||||
|
self.name_attribute_map[element.name] = element
|
||||||
|
|
||||||
|
def __setitem__(self, key, value):
|
||||||
|
if key not in self.name_attribute_map:
|
||||||
|
raise KeyError(f"There is no such setting with the name: {key}")
|
||||||
|
|
||||||
|
attribute = self.name_attribute_map[key]
|
||||||
|
attribute.set_value(value)
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
from typing import Union, Tuple
|
from typing import Union, Tuple, Dict
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from ..path_manager import LOCATIONS
|
from ..path_manager import LOCATIONS
|
||||||
from .base_classes import Description, Attribute, Section, EmptyLine
|
from .base_classes import Description, Attribute, Section, EmptyLine, COMMENT_PREFIX
|
||||||
from .audio import AUDIO_SECTION
|
from .audio import AUDIO_SECTION
|
||||||
from .logging import LOGGING_SECTION
|
from .logging import LOGGING_SECTION
|
||||||
|
|
||||||
@ -26,10 +26,52 @@ class Config:
|
|||||||
EmptyLine()
|
EmptyLine()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self._name_section_map: Dict[str, Section] = dict()
|
||||||
|
|
||||||
|
for element in self.config_elements:
|
||||||
|
if not isinstance(element, Section):
|
||||||
|
continue
|
||||||
|
|
||||||
|
for name in element.name_attribute_map:
|
||||||
|
if name in self._name_section_map:
|
||||||
|
raise ValueError(f"Two sections have the same name: "
|
||||||
|
f"{name}: "
|
||||||
|
f"{element.__class__.__name__} {self._name_section_map[name].__class__.__name__}")
|
||||||
|
|
||||||
|
self._name_section_map[name] = element
|
||||||
|
|
||||||
|
def set_name_to_value(self, name: str, value: str):
|
||||||
|
if name not in self._name_section_map:
|
||||||
|
raise KeyError(f"There is no such setting, as: {name}")
|
||||||
|
|
||||||
|
self._name_section_map[name][name] = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def config_string(self) -> str:
|
def config_string(self) -> str:
|
||||||
return "\n\n".join(str(element) for element in self.config_elements)
|
return "\n\n".join(str(element) for element in self.config_elements)
|
||||||
|
|
||||||
|
def _parse_conf_line(self, line: str, index: int):
|
||||||
|
line = line.strip()
|
||||||
|
if line.startswith(COMMENT_PREFIX):
|
||||||
|
return
|
||||||
|
|
||||||
|
if line == "":
|
||||||
|
return
|
||||||
|
|
||||||
|
if "=" not in line:
|
||||||
|
raise ValueError(f"Couldn't find the '=' in line {index}.")
|
||||||
|
|
||||||
|
line_segments = line.split("=")
|
||||||
|
name = line_segments[0]
|
||||||
|
value = "=".join(line_segments[1:])
|
||||||
|
|
||||||
|
self.set_name_to_value(name, value)
|
||||||
|
|
||||||
|
def read_from_config_file(self, path: os.PathLike):
|
||||||
|
with open(path, "r") as conf_file:
|
||||||
|
for i, line in enumerate(conf_file):
|
||||||
|
self._parse_conf_line(line, i+1)
|
||||||
|
|
||||||
def write_to_config_file(self, path: os.PathLike):
|
def write_to_config_file(self, path: os.PathLike):
|
||||||
with open(path, "w") as conf_file:
|
with open(path, "w") as conf_file:
|
||||||
conf_file.write(self.config_string)
|
conf_file.write(self.config_string)
|
||||||
@ -39,7 +81,9 @@ config = Config()
|
|||||||
|
|
||||||
|
|
||||||
def read():
|
def read():
|
||||||
pass
|
if not LOCATIONS.CONFIG_FILE.is_file():
|
||||||
|
write()
|
||||||
|
config.read_from_config_file(LOCATIONS.CONFIG_FILE)
|
||||||
|
|
||||||
|
|
||||||
def write():
|
def write():
|
||||||
|
@ -118,5 +118,7 @@ class LoggingSection(Section):
|
|||||||
self.GENIUS_LOGGER
|
self.GENIUS_LOGGER
|
||||||
]
|
]
|
||||||
|
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
|
||||||
LOGGING_SECTION = LoggingSection()
|
LOGGING_SECTION = LoggingSection()
|
||||||
|
Loading…
Reference in New Issue
Block a user