Source code for zensols.config.dictconfig

"""Implementation of a dictionary backing configuration.

"""
from __future__ import annotations
__author__ = 'Paul Landes'
from typing import Dict, Set, Type, Any
import logging
from collections import OrderedDict
from . import ConfigurableError, Configurable, TreeConfigurable, Dictable

logger = logging.getLogger(__name__)


[docs] class DictionaryConfig(TreeConfigurable, Dictable): """This is a simple implementation of a dictionary backing configuration. The provided configuration is just a two level dictionary. The top level keys are the section and the values are a single depth dictionary with string keys and values. You can override :meth:`_get_config` to restructure the dictionary for application specific use cases. One such example is :meth:`.JsonConfig._get_config`. .. document private functions .. automethod:: _get_config """
[docs] def __init__(self, config: Dict[str, Dict[str, Any]] = None, default_section: str = None, deep: bool = False): """Initialize. :param config: configures this instance (see class docs) :param default_section: used as the default section when non given on the get methds such as :meth:`get_option` """ super().__init__(default_section=default_section) if config is None: self._dict_config = {} else: self._dict_config = config self._deep = deep self.invalidate()
[docs] @classmethod def from_config(cls: Type, source: Configurable, **kwargs: Dict[str, Any]) -> DictionaryConfig: """Create an instance from another configurable. :param source: contains the source data from which to copy :param kwargs: initializer arguments for the new instance :return: a new instance of this class with the data copied from ``source`` """ secs: Dict[str, Any] = OrderedDict() params: Dict[str, Any] = dict(kwargs) if 'default_section' not in params and \ source.default_section is not None: params['default_section'] = source.default_section if isinstance(source, DictionaryConfig): params['deep'] = source.deep for sec in sorted(source.sections): svs = OrderedDict() secs[sec] = svs source.populate(svs, sec) return cls(secs, **kwargs)
def _from_dictable(self, *args, **kwargs) -> Dict[str, Any]: return self._get_config()
[docs] def _get_config(self) -> Dict[str, Any]: return self._dict_config
def _set_config(self, source: Dict[str, Any]): self._dict_config = source self.invalidate() @property def options(self) -> Dict[str, Any]: if self._deep: return super().options else: return Configurable.options.fget(self)
[docs] def get_options(self, section: str = None) -> Dict[str, str]: if self._deep: return super().get_options(section) else: conf = self._get_config() sec = conf.get(section) if sec is None: raise ConfigurableError(f'no section: {section}') return sec
[docs] def get_option(self, name: str, section: str = None) -> str: if self._deep: return super().get_option(name, section) else: return Configurable.get_option(self, name, section)
[docs] def has_option(self, name: str, section: str = None) -> bool: if self._deep: return super().has_option(name, section) else: conf = self._get_config() sec = conf.get(section) if sec is not None: return sec.contains(name) return False
@property def sections(self) -> Set[str]: """Return the top level keys of the dictionary as sections (see class doc). """ if self._deep: return super().sections else: return set(self._get_config().keys()) @sections.setter def sections(self, sections: Set[str]): raise RuntimeError('Can not set sections')
[docs] def set_option(self, name: str, value: str, section: str = None): section = self.default_section if section is None else section if section not in self.sections: dct = {} self._dict_config[section] = dct else: dct = self._dict_config[section] dct[name] = value
[docs] def remove_section(self, section: str): self._get_config().pop(section)
def __repr__(self): return super().__repr__()