From 9c99c24f9a19e42f5edf665138979f55bd766b41 Mon Sep 17 00:00:00 2001 From: Aki Date: Sun, 2 Apr 2023 16:06:43 +0200 Subject: Implemented simple module to handle radar instance configuration --- waterspout_radar/__init__.py | 0 waterspout_radar/_config.py | 74 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 waterspout_radar/__init__.py create mode 100644 waterspout_radar/_config.py (limited to 'waterspout_radar') diff --git a/waterspout_radar/__init__.py b/waterspout_radar/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/waterspout_radar/_config.py b/waterspout_radar/_config.py new file mode 100644 index 0000000..5f946cf --- /dev/null +++ b/waterspout_radar/_config.py @@ -0,0 +1,74 @@ +""" +Implements loading and providing the configuration of the radar instance. Usage should be straight-forward: + + >>> from . import _config + >>> config = _config.load() + >>> config.locations + ['New York City', 'Jersey City'] + +An example configuration file looks like this: + + [Storage] + db = .waterspout/db.json + staging = .waterspout/staging.json + + [Locations] + New York City + Jersey City + + [Windy] + key = + + [Web] + port = 80 +""" + +import configparser +import dataclasses +import typing + + +@dataclasses.dataclass +class Config: + key: str + locations: typing.List[str] + db: str + staging: str + port: int + + +class ConfigError(Exception): + "Raised when configuration could not be loaded or was malformed." + + +def load(pathname: str="radar.conf") -> Config: + "Loads configuration from a file at *pathname*. May raise ConfigError when content does not meet expectations." + config = configparser.ConfigParser(allow_no_value=True) + config.read(pathname) + raw = {} + errors = [] + + def _load_key(section, name, target=None, type=None, default=None, required=False): + target = target or name + try: + value = config[section][name] + if type: + value = type(value) + raw[target] = value + except (KeyError, ValueError): + if default: + raw[target] = default + if required: + errors.append(f"Config is missing required field: {pathname}: {section}: {name}") + + _load_key("Storage", "db", default="radar.json") + _load_key("Storage", "staging", default=raw["db"] + ".staging") + _load_key("Windy", "key", required=True) + _load_key("Web", "port", type=int) + try: + raw["locations"] = list(config["Locations"]) + except KeyError: + errors.append(f"Config is missing Locations: {pathname}") + if errors: + raise ConfigError(*errors) + return Config(**raw) -- cgit v1.1