2023-08-10 21:01:16 +00:00
|
|
|
import re
|
2023-09-10 14:27:09 +00:00
|
|
|
from typing import Optional, List, Union, Iterable, Callable
|
|
|
|
from dataclasses import dataclass
|
|
|
|
import logging
|
|
|
|
import toml
|
2023-09-10 17:00:51 +00:00
|
|
|
from copy import deepcopy, copy
|
|
|
|
from urllib.parse import urlparse, urlunparse, ParseResult
|
2023-08-10 21:01:16 +00:00
|
|
|
|
|
|
|
from ...exception.config import SettingValueError
|
|
|
|
from ..utils import comment
|
|
|
|
|
|
|
|
|
2023-09-10 14:27:09 +00:00
|
|
|
LOGGER = logging.getLogger("config")
|
|
|
|
|
|
|
|
COMMENT_PREFIX = "#"
|
|
|
|
|
|
|
|
|
|
|
|
def comment_string(uncommented: str) -> str:
|
|
|
|
unprocessed_lines = uncommented.split("\n")
|
|
|
|
|
|
|
|
processed_lines: List[str] = []
|
|
|
|
|
|
|
|
for line in unprocessed_lines:
|
|
|
|
if line.startswith(COMMENT_PREFIX) or line == "":
|
|
|
|
processed_lines.append(line)
|
|
|
|
continue
|
|
|
|
|
|
|
|
line = COMMENT_PREFIX + " " + line
|
|
|
|
processed_lines.append(line)
|
|
|
|
|
|
|
|
return "\n".join(processed_lines)
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass
|
2023-08-10 21:01:16 +00:00
|
|
|
class Description:
|
2023-09-10 14:27:09 +00:00
|
|
|
description: str
|
2023-08-10 21:01:16 +00:00
|
|
|
|
|
|
|
@property
|
2023-09-10 14:27:09 +00:00
|
|
|
def toml_string(self):
|
|
|
|
return comment_string(self.description)
|
2023-08-10 21:01:16 +00:00
|
|
|
|
|
|
|
|
2023-09-10 14:27:09 +00:00
|
|
|
class EmptyLine(Description):
|
|
|
|
def __init__(self):
|
|
|
|
self.description = ""
|
2023-08-10 21:01:16 +00:00
|
|
|
|
2023-09-10 14:27:09 +00:00
|
|
|
|
|
|
|
|
|
|
|
class Attribute:
|
|
|
|
def __init__(
|
|
|
|
self,
|
|
|
|
name: str,
|
|
|
|
default_value: any,
|
|
|
|
description: Optional[str] = None,
|
|
|
|
):
|
2023-08-10 21:01:16 +00:00
|
|
|
|
|
|
|
self.name = name
|
|
|
|
|
2023-09-10 17:00:51 +00:00
|
|
|
self.value = self._recursive_parse_object(default_value, self.parse_simple_value)
|
2023-09-10 14:27:09 +00:00
|
|
|
|
|
|
|
self.description: Optional[str] = description
|
2023-09-10 15:27:07 +00:00
|
|
|
self.loaded_settings: dict = None
|
|
|
|
|
|
|
|
def initialize_from_config(self, loaded_settings: dict):
|
|
|
|
self.loaded_settings = loaded_settings
|
2023-09-10 17:00:51 +00:00
|
|
|
self.loaded_settings.__setitem__(self.name, self.value, True)
|
2023-09-10 14:27:09 +00:00
|
|
|
|
|
|
|
def unparse_simple_value(self, value: any) -> any:
|
|
|
|
return value
|
|
|
|
|
|
|
|
def parse_simple_value(self, value: any) -> any:
|
|
|
|
return value
|
2023-08-10 21:01:16 +00:00
|
|
|
|
2023-09-10 14:27:09 +00:00
|
|
|
def _recursive_parse_object(self, __object, callback: Callable):
|
2023-09-10 17:00:51 +00:00
|
|
|
__object = copy(__object)
|
|
|
|
|
2023-09-10 14:27:09 +00:00
|
|
|
if isinstance(__object, dict):
|
|
|
|
for key, value in __object.items():
|
|
|
|
__object[key] = self._recursive_parse_object(value, callback)
|
|
|
|
|
|
|
|
return __object
|
2023-08-10 21:01:16 +00:00
|
|
|
|
2023-09-10 17:00:51 +00:00
|
|
|
if isinstance(__object, list) or (isinstance(__object, tuple) and not isinstance(__object, ParseResult)):
|
2023-09-10 14:27:09 +00:00
|
|
|
for i, item in enumerate(__object):
|
|
|
|
__object[i] = self._recursive_parse_object(item, callback)
|
|
|
|
return __object
|
|
|
|
|
|
|
|
return callback(__object)
|
2023-09-10 17:00:51 +00:00
|
|
|
|
|
|
|
def parse(self, unparsed_value):
|
|
|
|
self.value = self._recursive_parse_object(unparsed_value, self.parse_simple_value)
|
|
|
|
return self.value
|
|
|
|
|
|
|
|
def unparse(self, parsed_value):
|
|
|
|
return self._recursive_parse_object(parsed_value, self.unparse_simple_value)
|
2023-09-10 14:27:09 +00:00
|
|
|
|
2023-09-10 15:27:07 +00:00
|
|
|
def load_toml(self, loaded_toml: dict) -> bool:
|
2023-09-10 14:27:09 +00:00
|
|
|
"""
|
|
|
|
returns true if succesfull
|
|
|
|
"""
|
|
|
|
|
|
|
|
if self.name not in loaded_toml:
|
|
|
|
LOGGER.warning(f"No setting by the name {self.name} found in the settings file.")
|
2023-09-10 15:27:07 +00:00
|
|
|
self.loaded_settings.__setitem__(self.name, self.value, True)
|
2023-09-10 14:27:09 +00:00
|
|
|
return
|
|
|
|
|
|
|
|
try:
|
2023-09-10 17:00:51 +00:00
|
|
|
self.parse(loaded_toml[self.name])
|
2023-09-10 14:27:09 +00:00
|
|
|
except SettingValueError as settings_error:
|
|
|
|
logging.warning(settings_error)
|
|
|
|
return False
|
2023-09-10 17:00:51 +00:00
|
|
|
|
2023-09-10 15:27:07 +00:00
|
|
|
self.loaded_settings.__setitem__(self.name, self.value, True)
|
2023-09-10 14:27:09 +00:00
|
|
|
|
|
|
|
return True
|
|
|
|
|
2023-08-10 21:01:16 +00:00
|
|
|
|
|
|
|
@property
|
2023-09-10 14:27:09 +00:00
|
|
|
def toml_string(self) -> str:
|
|
|
|
string = ""
|
|
|
|
|
|
|
|
if self.description is not None:
|
|
|
|
string += comment(self.description) + "\n"
|
|
|
|
|
2023-09-10 17:00:51 +00:00
|
|
|
string += toml.dumps({self.name: self.unparse(self.value)})
|
2023-08-10 21:01:16 +00:00
|
|
|
|
2023-09-10 17:00:51 +00:00
|
|
|
# print(string)
|
2023-09-10 14:27:09 +00:00
|
|
|
return string
|
2023-08-10 21:01:16 +00:00
|
|
|
|
2023-09-10 14:27:09 +00:00
|
|
|
def __str__(self):
|
|
|
|
return f"{self.description}\n{self.name}={self.value}"
|
2023-08-10 21:01:16 +00:00
|
|
|
|