diff options
Diffstat (limited to 'src/home/config/config.py')
-rw-r--r-- | src/home/config/config.py | 175 |
1 files changed, 96 insertions, 79 deletions
diff --git a/src/home/config/config.py b/src/home/config/config.py index b79fecb..8ed8483 100644 --- a/src/home/config/config.py +++ b/src/home/config/config.py @@ -3,110 +3,74 @@ import yaml import logging import os +from . import validators from os.path import join, isdir, isfile from typing import Optional, Any, MutableMapping from argparse import ArgumentParser from ..util import parse_addr -import _validators as validators -_validators = {} +my_validators = {} def _get_validator(name: str) -> Optional[callable]: if hasattr(validators, f'{name}_validator'): return getattr(validators, f'{name}_validator') - if name in _validators: - return _validators[name] + if name in my_validators: + return my_validators[name] return None def add_validator(name: str, f: callable): - _validators[name] = f + my_validators[name] = f -def _get_config_path(name: str) -> str: - formats = ['toml', 'yaml'] +class ConfigUnit: + NAME = 'dumb' - dirnames = [ - join(os.environ['HOME'], '.config', 'homekit'), - '/etc/homekit' - ] - - for dirname in dirnames: - if isdir(dirname): - for fmt in formats: - filename = join(dirname, f'{name}.{fmt}') - if isfile(filename): - return filename - - raise IOError(f'config \'{name}\' not found') - - -class SingleConfig: data: MutableMapping[str, Any] - def __init__(self): - self.data = {} + @classmethod + def get_config_path(cls, name=None) -> str: + if name is None: + name = cls.NAME + if name is None: + raise ValueError('get_config_path: name is none') - def load(self, - name: Optional[str] = None, - use_cli=True, - parser: ArgumentParser = None): - self.app_name = name + dirnames = ( + join(os.environ['HOME'], '.config', 'homekit'), + '/etc/homekit' + ) - if (name is None) and (not use_cli): - raise RuntimeError('either config name must be none or use_cli must be True') + for dirname in dirnames: + if isdir(dirname): + for fmt in ('toml', 'yaml'): + filename = join(dirname, f'{name}.{fmt}') + if isfile(filename): + return filename - log_default_fmt = False - log_file = None - log_verbose = False - no_config = name is False + raise IOError(f'config \'{name}\' not found') - path = None - if use_cli: - if parser is None: - parser = ArgumentParser() - if not no_config: - parser.add_argument('-c', '--config', type=str, required=name is None, - help='Path to the config in TOML or YAML format') - parser.add_argument('-V', '--verbose', action='store_true') - parser.add_argument('--log-file', type=str) - parser.add_argument('--log-default-fmt', action='store_true') - args = parser.parse_args() + def __init__(self, name=None): + self.data = {} - if not no_config and args.config: - path = args.config + if self.NAME != 'dumb': + self.load_from(self.get_config_path()) + self.validate() - if args.verbose: - log_verbose = True - if args.log_file: - log_file = args.log_file - if args.log_default_fmt: - log_default_fmt = args.log_default_fmt + elif name is not None: + self.NAME = name - if not no_config and path is None: - path = _get_config_path(name) - - if no_config: - self.data = {} - else: - if path.endswith('.toml'): - self.data = toml.load(path) - elif path.endswith('.yaml'): - with open(path, 'r') as fd: - self.data = yaml.safe_load(fd) - - if 'logging' in self: - if not log_file and 'file' in self['logging']: - log_file = self['logging']['file'] - if log_default_fmt and 'default_fmt' in self['logging']: - log_default_fmt = self['logging']['default_fmt'] + def load_from(self, path: str): + if path.endswith('.toml'): + self.data = toml.load(path) + elif path.endswith('.yaml'): + with open(path, 'r') as fd: + self.data = yaml.safe_load(fd) - setup_logging(log_verbose, log_file, log_default_fmt) - - if use_cli: - return args + def validate(self): + v = _get_validator(self.NAME) + v(self.data) def __getitem__(self, key): return self.data[key] @@ -139,22 +103,75 @@ class SingleConfig: class Config: app_name: Optional[str] + app_config: ConfigUnit def __init__(self): - self.app_name = None + self.app_config = ConfigUnit() + def load_app(self, + name: Optional[str] = None, + use_cli=True, + parser: ArgumentParser = None): + self.app_name = name + + if (name is None) and (not use_cli): + raise RuntimeError('either config name must be none or use_cli must be True') + + log_default_fmt = False + log_file = None + log_verbose = False + no_config = name is False + path = None + if use_cli: + if parser is None: + parser = ArgumentParser() + if not no_config: + parser.add_argument('-c', '--config', type=str, required=name is None, + help='Path to the config in TOML or YAML format') + parser.add_argument('-V', '--verbose', action='store_true') + parser.add_argument('--log-file', type=str) + parser.add_argument('--log-default-fmt', action='store_true') + args = parser.parse_args() + + if not no_config and args.config: + path = args.config + + if args.verbose: + log_verbose = True + if args.log_file: + log_file = args.log_file + if args.log_default_fmt: + log_default_fmt = args.log_default_fmt + + if not no_config and path is None: + path = ConfigUnit.get_config_path(name=name) + + if not no_config: + self.app_config.load_from(path) + + if 'logging' in self.app_config: + if not log_file and 'file' in self.app_config['logging']: + log_file = self.app_config['logging']['file'] + if log_default_fmt and 'default_fmt' in self.app_config['logging']: + log_default_fmt = self.app_config['logging']['default_fmt'] + + setup_logging(log_verbose, log_file, log_default_fmt) + + if use_cli: + return args -config = ConfigStore() +config = Config() +app_config = config.app_config def is_development_mode() -> bool: if 'HK_MODE' in os.environ and os.environ['HK_MODE'] == 'dev': return True - return ('logging' in config) and ('verbose' in config['logging']) and (config['logging']['verbose'] is True) + return ('logging' in config.app_config) and ('verbose' in config.app_config['logging']) and (config.app_config['logging']['verbose'] is True) def setup_logging(verbose=False, log_file=None, default_fmt=False): |