refactor: extract configuration handling to own class
All checks were successful
/ Tests (push) Successful in 52s
/ Static Analysis (push) Successful in 1m4s

This commit is contained in:
Marc 2024-04-13 23:17:42 -04:00
parent b391286801
commit 3dad2071ff
Signed by: marc
GPG key ID: 048E042F22B5DC79
4 changed files with 84 additions and 4 deletions

View file

@ -5,5 +5,10 @@ Models and datastructures
import pydantic import pydantic
class Configuration(pydantic.BaseModel): class ContainerMetadata(pydantic.BaseModel):
"""Command line application configuration options""" """Metadata pulled from container status check"""
name: str
status: str
image: str
started: int

View file

@ -10,7 +10,7 @@ import pathlib
import click import click
import uvicorn import uvicorn
from spud.base import Configuration from spud.config import Configuration
DEFAULT_CONFIGURATION_PATH = "~/.config/spud/config.json" DEFAULT_CONFIGURATION_PATH = "~/.config/spud/config.json"
@ -27,7 +27,14 @@ def cli(context, config):
"""CLI root""" """CLI root"""
context.ensure_object(dict) context.ensure_object(dict)
config = config if config is not None else DEFAULT_CONFIGURATION_PATH config = config if config is not None else DEFAULT_CONFIGURATION_PATH
context.obj["config_path"] = pathlib.Path(config).expanduser() config_path = pathlib.Path(config).expanduser()
context.obj["config_path"] = config_path
if config_path.exists():
context.obj["config"] = Configuration.from_file(config_path)
else:
context.obj["config"] = None
@click.command() @click.command()

36
spud/config.py Normal file
View file

@ -0,0 +1,36 @@
import json
import pathlib
import pydantic
class Configuration(pydantic.BaseModel):
"""Command line application configuration options"""
@classmethod
def from_file(cls, path: pathlib.Path) -> "Configuration":
"""
Generates a Configuration object from the file found at {path}.
Raises if:
- The file does not exist
- The file is not valid JSON
- The file does not respect the expected schema
"""
if not path.exists():
raise RuntimeError(f"Configuration file not found: {str(path)}.")
with open(path, "r", encoding="utf8") as config_file:
config_data = config_file.read()
try:
parsed_configuration = json.loads(config_data)
return cls(**parsed_configuration)
except json.decoder.JSONDecodeError as exc:
raise RuntimeError(
f"Configuration file is not valid JSON ({str(path)})."
) from exc
except pydantic.ValidationError as exc:
raise RuntimeError(
f"Configuration file has wrong schema ({str(path)})."
) from exc

32
tests/test_config.py Normal file
View file

@ -0,0 +1,32 @@
import json
import pytest
from spud.config import Configuration
@pytest.fixture(name="sample_config")
def sample_config_fixture():
return {}
def test_from_file_creates_configuration_from_file(tmpdir, sample_config):
config_file = tmpdir / "config.json"
config_file.write(json.dumps(sample_config))
config = Configuration.from_file(config_file)
assert config.model_dump() == sample_config
def test_from_file_raises_if_file_not_found(tmpdir):
with pytest.raises(RuntimeError):
Configuration.from_file(tmpdir / "nonfile.json")
def test_from_file_raises_if_file_not_json(tmpdir):
config_file = tmpdir / "config.json"
config_file.write("notjson")
with pytest.raises(RuntimeError):
Configuration.from_file(config_file)