From c48319c5daa76a7e3df467b7e5d1b699e379e651 Mon Sep 17 00:00:00 2001 From: Ilya Bezrukov Date: Sat, 2 Mar 2024 01:24:43 +0300 Subject: [PATCH] Fix issues --- example/config.yaml | 19 +++++++++++++++++++ example/simple.py | 28 ++++++++++++++++++++++++++++ kissconfig/__init__.py | 27 ++++++++++++++++----------- kissconfig/config.py | 10 ---------- kissconfig/loader.py | 13 ++++++------- 5 files changed, 69 insertions(+), 28 deletions(-) create mode 100644 example/config.yaml create mode 100644 example/simple.py diff --git a/example/config.yaml b/example/config.yaml new file mode 100644 index 0000000..ec619d8 --- /dev/null +++ b/example/config.yaml @@ -0,0 +1,19 @@ +db: + host: 127.0.0.1 + username: test + password: 123456 + +groups: + - name: admin + priority: 100 + permissions: + - ban_user + - ro_user + - invite_user + - promote_user + + - name: moderator + priority: 50 + permissions: + - invite_user + - ro_user diff --git a/example/simple.py b/example/simple.py new file mode 100644 index 0000000..63e903d --- /dev/null +++ b/example/simple.py @@ -0,0 +1,28 @@ +from dataclasses import dataclass + +from kissconfig import load_config, ConfigClass + + +@dataclass +class Database (ConfigClass): + host: str + username: str + password: str + + +@dataclass +class Group (ConfigClass): + name: str + priority: int + permissions: list[str] + + +@dataclass +class Config (ConfigClass): + db: Database + groups: list[Group] + + +if __name__ == "__main__": + config = load_config(Config, "config.yaml") + print(config) diff --git a/kissconfig/__init__.py b/kissconfig/__init__.py index 79d5bfd..73c0fbd 100644 --- a/kissconfig/__init__.py +++ b/kissconfig/__init__.py @@ -2,20 +2,25 @@ import os import shutil import logging import sys -from typing import Type +from typing import Type, Optional from kissconfig.config import ConfigClass from kissconfig.loader import Loader, YamlLoader -def load_config(main_config: Type[ConfigClass], loader: Loader = YamlLoader()): - if not os.path.exists(config_path): - logging.warning(f"Unable to locate app config ({config_path})!") - if not os.path.exists(example_config_path): - logging.critical(f"Unable to locate example config ({example_config_path})") - sys.exit(1) - else: - shutil.copy2(example_config_path, config_path) +def load_config(class_: Type[ConfigClass], + path: str, + loader: Loader = YamlLoader(), + example_path: Optional[str] = None): + if os.path.exists(path): + return loader.from_file(class_, path) + + logging.warning(f"Unable to locate app config ({path})!") + if example_path: + if os.path.exists(example_path): + shutil.copy2(example_path, path) logging.warning(f"Actual app config (%s) created from example (%s), don't forget to update it!", - config_path, example_config_path) - return main_config.from_file(config_path, config_namespace) + path, example_path) + else: + logging.critical(f"Unable to locate example config ({example_path})") + sys.exit(1) diff --git a/kissconfig/config.py b/kissconfig/config.py index 6361a34..e375195 100644 --- a/kissconfig/config.py +++ b/kissconfig/config.py @@ -34,13 +34,3 @@ class ConfigClass: raise ValueError(f"{cls.__name__}.{f.name} is not configured!") kwargs[f.name] = ConfigClass.parse(data[f.name], hints[f.name]) return cls(**kwargs) - - @classmethod - def from_file(cls, filepath: str, config_namespace: str = ""): - with open(filepath) as f: - data = safe_load(f) - if data is None: - raise ValueError("") - if config_namespace: - data = data.get(config_namespace, {}) - return cls.from_dict(data) diff --git a/kissconfig/loader.py b/kissconfig/loader.py index 654a112..35d3490 100644 --- a/kissconfig/loader.py +++ b/kissconfig/loader.py @@ -1,7 +1,7 @@ from abc import ABCMeta, abstractmethod -from typing import Type +from typing import Type, Optional -from yaml import safe_load +import yaml from kissconfig.config import ConfigClass @@ -11,10 +11,8 @@ class EmptyConfig (ValueError): class Loader (metaclass=ABCMeta): - def __init__(self, path: str = None, - example_path: str = None): - self.path = path - self.example_path = example_path + def __init__(self, namespace: Optional[str] = None): + self.namespace = namespace @abstractmethod def parse_file(self, path: str) -> dict: @@ -31,4 +29,5 @@ class Loader (metaclass=ABCMeta): class YamlLoader (Loader): def parse_file(self, path: str) -> dict: - return safe_load(path) + with open(path) as f: + return yaml.safe_load(f)