repo-cloner/repo_cloner/lib/cloner_config.py

121 lines
3.5 KiB
Python
Raw Normal View History

import os
from repo_cloner.lib.default_cloner_config import DefaultClonerConfig
from repo_cloner.lib.config_file_not_found_error import ConfigFileNotFoundError
import logging
l = logging.getLogger("rc.cfg")
class ClonerConfig(DefaultClonerConfig):
def __init__(self):
super().__init__()
self.__properties = list(filter(self.has_property, dir(self)))
self.__values = {}
def __try_default(self, key: str, default_value):
if not self.has_property(key):
raise KeyError(f"{key} is not recognized config option")
if key in self.__values:
return self.__values[key]
return default_value
@property
def cloner_project_name(self) -> str:
return self.__try_default("cloner_project_name", super(ClonerConfig, self).cloner_project_name)
@property
def cloner_repo_url(self) -> str:
return self.__try_default("cloner_repo_url", super(ClonerConfig, self).cloner_repo_url)
@property
def cloner_interval(self) -> int:
return self.__try_default("cloner_interval", super(ClonerConfig, self).cloner_interval)
@property
def cloner_submodules(self) -> bool:
return self.__try_default("cloner_submodules", super(ClonerConfig, self).cloner_submodules)
@property
def cloner_submodule_depth(self) -> int:
return self.__try_default("cloner_submodule_depth", super(ClonerConfig, self).cloner_submodule_depth)
def _set_property(self, key: str, value):
if not self.has_property(key):
raise KeyError(f"{key} is not recognized config option")
requested_type = type(self.__getattribute__(key));
if not isinstance(value, requested_type):
l.debug(f"Trying conversion of {key} from {type(value)} to {requested_type}")
try:
if requested_type == bool:
value = True if value == "1" else False
else:
value = requested_type(value)
l.debug(f"Conversion result: {type(value)}: {value}")
except Exception as e:
l.critical(f"Conversion failed! ({str(e)}")
raise ValueError(
f"Invalid value for key {key}: type is {type(value)} instead of {requested_type}, conversion failed")
self.__values[key] = value
class ClonerConfigParser:
__file: str = ""
__invalid_lines: list = []
def __init__(self, config_file: str):
self.__file = config_file
self.__config = ClonerConfig()
self.__invalid_lines = []
l.info(f"Parsing cloner config file: {self.__file}")
if not os.path.exists(self.__file):
l.critical(f"Config file: {self.__file} does not exist!")
raise ConfigFileNotFoundError(self.__file)
# parse config file
raw_lines = []
with open(self.__file, "r") as f:
raw_lines = f.readlines()
l.debug(f"Readen {len(raw_lines)} lines")
lines = []
# strip lines, remove comments
line: str = ""
for line in raw_lines:
if not line.startswith('#'):
line = line.strip()
# empty line? skip
if len(line) > 0:
lines.append(line)
l.debug(f"Found {len(lines)} config lines")
for line in lines:
if not "=" in line:
l.warning(f"Line '{line}' has invalid format!")
self.__invalid_lines.append((line, None))
continue
eq = line.find("=")
key: str = line[0:eq].strip()
val: str = line[eq + 1:].strip()
l.debug(f"Found config pair: {key} => '{val}'")
try:
self.__config._set_property(key, val)
except BaseException as e:
self.__invalid_lines.append((key, val))
l.critical(str(e))
@property
def config(self) -> ClonerConfig:
return self.__config
@property
def invalid(self) -> bool:
return len(self.__invalid_lines) > 0
@property
def invalid_lines(self):
return self.__invalid_lines