import configparser import os from typing import Final import validators from mdrsclient.exceptions import IllegalArgumentException from mdrsclient.settings import CONFIG_FILE_PATH class ConfigFile: OPTION_URL: Final[str] = "url" serial: int config_file: str config_dir: str remote: str config: configparser.ConfigParser def __init__(self, remote: str) -> None: self.serial = -1 self.config_file = CONFIG_FILE_PATH self.config_dir = os.path.dirname(CONFIG_FILE_PATH) self.remote = remote self.config = configparser.ConfigParser() def list(self) -> list[tuple[str, str]]: ret: list[tuple[str, str]] = [] self.__load() for remote in self.config.sections(): url = self.config.get(remote, self.OPTION_URL) ret.append((remote, url)) return ret @property def url(self) -> str | None: if not self.__exists(self.remote): return None return self.config.get(self.remote, self.OPTION_URL) @url.setter def url(self, url: str) -> None: if not validators.url(url): # type: ignore raise IllegalArgumentException("malformed URI sequence") self.__load() if self.config.has_section(self.remote): self.config.remove_section(self.remote) self.config.add_section(self.remote) self.config.set(self.remote, self.OPTION_URL, url) self.__save() @url.deleter def url(self) -> None: if self.__exists(self.remote): self.config.remove_section(self.remote) self.__save() def __exists(self, section: str) -> bool: self.__load() return self.config.has_option(section, self.OPTION_URL) def __load(self) -> None: if os.path.isfile(self.config_file): stat = os.stat(self.config_file) serial = hash(stat) if self.serial != serial: self.config.read(self.config_file, encoding="utf8") self.serial = serial def __save(self) -> None: self.__ensure_cache_dir() with open(self.config_file, "w") as f: self.config.write(f) os.chmod(self.config_file, 0o600) def __ensure_cache_dir(self) -> None: if not os.path.exists(self.config_dir): os.makedirs(self.config_dir) # ensure directory is secure. os.chmod(self.config_dir, 0o700)