Source code for bexchange.config

# Copyright (C) 2021- Swedish Meteorological and Hydrological Institute (SMHI)
#
# This file is part of baltrad-exchange.
#
# baltrad-exchange is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# baltrad-exchange is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with baltrad-exchange.  If not, see <http://www.gnu.org/licenses/>.
###############################################################################

## Provides functionality for reading the configuration

## @file
## @author Anders Henja, SMHI
## @date 2021-08-18
from baltradutils import jprops

_undefined = object()

[docs] class Error(Exception): """base configuration error"""
[docs] class PropertyLookupError(Error): """property not found """
[docs] class PropertyValueError(Error): """invalid property value """
[docs] class Properties(object): def __init__(self, values, prefix=""): """ :param values: initial set of values :type values: :class:`dict` :prefix: the prefix to use for keys when getting values from this instance :type prefix: :class:`str` """ self._values = values self._prefix = prefix @property def prefix(self): return self._prefix
[docs] def dictionary(self): """ :return: returns the internal dictionary """ return self._values
[docs] def get(self, key, default=_undefined): """get the value associated with the key :param key: the key for which to look up the value :param default: default value if the key is not found :raise: :class:`PropertyLookupError` if the key is not found and no default value is provided. """ try: return self[key] except PropertyLookupError: if default != _undefined: return default else: raise
[docs] def get_int(self, key, default=_undefined): """get int value associated with the key :param key: the key for which to look up the value :param default: default value if the key is not found. This can be any value, but when provided as a `str`, it is parsed as if read from the configuration, otherwise it is returned as it is. :param sep: value separator :raise: :class:`PropertyLookupError` if the key is not found and no default value is provided. """ value = self.get(key, default) if not isinstance(value, str): return value try: return int(value) except ValueError: raise PropertyValueError("invalid int value: %s" % value)
[docs] def get_list(self, key, default=_undefined, sep=" "): """get list of values associated with the key :param key: the key for which to look up the value :param default: default value if the key is not found. This can be any value, but when provided as a `str`, it is parsed as if read from the configuration, otherwise it is returned as it is. :param sep: value separator :raise: :class:`PropertyLookupError` if the key is not found and no default value is provided. """ value = self.get(key, default) if not isinstance(value, str): return value return [part.strip() for part in value.split(sep)]
[docs] def get_boolean(self, key, default=_undefined): """get boolean value associated with the key :param key: the key for which to look up the value :param default: default value if the key is not found. This can be any value, but when provided as a `str`, it is parsed as if read from the configuration, otherwise it is returned as it is. :raise: :class:`PropertyLookupError` if the key is not found and no default value is provided. """ value = self.get(key, default) if not isinstance(value, str): return value if value in ("True", "true", "yes", "on", "1"): return True elif value in ("False", "false", "no", "off", "0"): return False else: raise PropertyValueError("can't parse boolean from: %s" % value)
def __getitem__(self, key): """get the value associated with the key :param key: the key for which to look up the value :raise: :class:`PropertyLookupError` if the key is not found and no default value is provided. """ full_key = self._prefix + key try: return self._values[full_key] except LookupError: raise PropertyLookupError(full_key)
[docs] def filter(self, prefix): """apply a prefix to the key lookups :param prefix: the prefix to apply :return: a new :class:`Properties` instance with the specified prefix """ return Properties(self._values, prefix=self._prefix + prefix)
[docs] def get_keys(self): """get available keys :return: list of keys matching for current prefix """ result = [] for key in self._values: if key.startswith(self._prefix): result.append(key[len(self._prefix):]) return result
[docs] def get_full_key(self, key): """get a full key corresponding to this 'filtered' key """ return self._prefix + key
[docs] @classmethod def load(cls, path): """Loads a property file :param path: the property file to read :return: a new :class:`Properties` instance """ with open(path) as fp: return Properties(jprops.load_properties(fp))