import pathlib import json import json.decoder from .exception import config_exception from .app_resources import app_resources class config: def __init__(self, defaults: dict) -> None: self.__defaults = defaults.copy() self.__config = defaults.copy() def _get(self, name: str) -> str | int | float | dict | list: if not name in self.__config: raise TypeError("Can not found " + name + " in config.") return self.__config[name] def __get_default(self, name: str) -> str | int | float | dict | list: return self.__defaults[name] @property def defaults(self) -> dict: return self.__defaults.copy() def exists(self, name: str) -> bool: return name in self.__defaults def load(self, config: dict) -> object: for key in config: if not self.exists(key): content = "When parsing config file found key " + key + " " content = content + "which is not recognized. Correct it." raise config_exception(content) if type(config[key]) is not type(self.__get_default(key)): required_type = type(self.__get_default).__name__ detected_type = type(config[key]).__name__ content = "When processing \"" + key + "\" key in config " content = content + "detected types mismatch. It would be an " content = content + required_type + ", but it is an " content = content + detected_type + "." raise config_exception(content) self.__config[key] = config[key] return self def __str__(self) -> str: dump = "Config dump: \n" for count in self.defaults.keys(): key = "Key \"" + count + "\": " key = key + "\"" + self._get(count) + "\", " key = key + "default = \"" + self.__get_default(count) + "\"" dump = dump + key + "\n" return dump class config_generator: def __init__(self, target: type) -> None: if target is config: raise TypeError("Config is skeleton class for configs.") self.__config = target().defaults self.__json_config = json.dumps(self.__config) def save(self, where: pathlib.Path) -> None: if where.exists(): content = "Can not create config file \"" + str(where) + "\" " content = content + "because it already exists in filesystem." raise config_exception(content) with where.open("w") as handler: handler.write(self.__json_config) class config_loader: def __init__(self, target: type) -> None: if target is config: raise TypeError("Config is skeleton class for configs.") self.__type = target self.__target = None @property def result(self) -> config: if self.__target is None: raise RuntimeError("Config is not loaded yet.") return self.__target @property def resources(self) -> app_resources: return app_resources(self.result) def load(self, where: pathlib.Path) -> object: if not where.is_file(): content = "Can not found required config file \"" content = content + where.absolute() + "\"." raise config_exception(content) preparing = self.__type() with where.open() as config: try: config_object = json.loads(config.read()) preparing.load(config_object) self.__target = preparing except json.decoder.JSONDecodeError as code_error: content = "Can not load config file, syntax error: " content = content + str(code_error) + "." raise config_error(content) return self