summaryrefslogtreecommitdiff
path: root/waterspout_radar
diff options
context:
space:
mode:
Diffstat (limited to 'waterspout_radar')
-rw-r--r--waterspout_radar/__init__.py0
-rw-r--r--waterspout_radar/_config.py74
2 files changed, 74 insertions, 0 deletions
diff --git a/waterspout_radar/__init__.py b/waterspout_radar/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/waterspout_radar/__init__.py
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 = <secret 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)