Application config using only the Python stdlib

April 4, 2022

A simple pattern for application configuration which only relies on the standard library.

{
    "SECRET_KEY": "secret key setting",
    "SECRET_TOKEN": "$SECRET_TOKEN",
    "ALLOWED_HOSTS": ["*"],
    "DB_PATH": "$HOME/db.sqlite3"
}
import json
import os
from dataclasses import dataclass


@dataclass
class Config:
    """Application config container."""

    SECRET_KEY: str
    SECRET_TOKEN: str
    ALLOWED_HOSTS: typing.List[str]
    DB_PATH: str

    def __post_init__(self) -> None:
        """Apply post initialize transformations here."""

        self.DB_PATH = os.path.expandvars(self.DB_PATH)
        self.SECRET_TOKEN = os.path.expandvars(self.SECRET_TOKEN)

    @classmethod
    def from_env(cls) -> Config:
        """Load the application configuration from the fs.

        Note this requires DJANGO_CONFIG_PATH is available in your environ.
        """

        conf_path = os.getenv("DJANGO_CONFIG_PATH", None)

        if conf_path is None:
            raise ImproperlyConfigured(
                "Improperly configured application, please set DJANGO_CONFIG_PATH e.g. "
                "export DJANGO_CONFIG_PATH=path_to_config.json"
            )

        with open(conf_path) as stream:
            config = json.load(stream)

        return Config(**config)

config = Config.from_env()

# Apply your settings
SECRET_KEY = config.SECRET_KEY
SECRET_TOKEN = config.SECRET_TOKEN
ALLOWED_HOSTS = config.ALLOWED_HOSTS
DB_PATH = config.DB_PATH