# -*- coding: utf-8 -*- from configparser import ConfigParser from typing import Any, Callable, Dict, List, Optional # pylint: disable=W0611 class Config: """Base configuration object.""" def get(self, key: str, default: Any = None) -> Any: """ Get the config option as a string :param key: config option name :param default: default value if no value exists in the config :return: option value """ raise NotImplementedError(__name__ + '.get()') def get_bool(self, key: str, default: Optional[bool] = None) -> bool: """ Get the config option as a boolean :param key: config option name :param default: default value if no value exists in the config :return: option value """ return bool(self.get(key, default)) def get_int(self, key: str, default: Optional[int] = None) -> int: """ Get the config option as an integer :param key: config option name :param default: default value if no value exists in the config :return: option value """ return int(self.get(key, default)) def get_float(self, key: str, default: Optional[float] = None) -> float: """ Get the config option as a float :param key: config option name :param default: default value if no value exists in the config :return: option value """ return float(self.get(key, default)) class FileConfig(Config): """Config class that loads configuration options from the locally-cached ZooKeeper config""" DEFAULT_FILENAME = '/var/cache/hfs/config.ini' # type: str default_section = 'config-default' # type: str prefixes = [] # type: List[str] def __init__( self, service_prefix: Optional[str] = None, filename: Optional[str] = None, defaults: Optional[Dict[str, Any]] = None) -> None: if filename is None: filename = self.DEFAULT_FILENAME self.config = ConfigParser(default_section=self.default_section, interpolation=None) self.config.read(filename) self.prefixes = [] if service_prefix: prefix_parts = service_prefix.split('.') while prefix_parts: self.prefixes.append('.'.join(prefix_parts) + '.') prefix_parts.pop() self.prefixes.append('') self.defaults = defaults def __getattr__(self, key: str) -> Any: """ Get a config key value as a direct attribute of this class. :param key: The config key name :return: The config key value, if it exists, or None """ return self.get(key) def _get(self, getfunc: Callable, key: str, default: Any = None) -> Any: if default is None and self.defaults: default = self.defaults.get(key) for prefix in self.prefixes: prefixed_key = prefix + key val = getfunc(self.default_section, prefixed_key, fallback=None) if val: break else: val = default return val def get(self, key: str, default: Any = None) -> Any: return self._get(self.config.get, key, default) def get_bool(self, key: str, default: Optional[bool] = None) -> bool: return self._get(self.config.getboolean, key, default) def get_int(self, key: str, default: Optional[int] = None) -> int: return self._get(self.config.getint, key, default) def get_float(self, key: str, default: Optional[float] = None) -> float: return self._get(self.config.getfloat, key, default)