-
-
Save a-recknagel/6faacb042b6638cb30249cc52fb320da to your computer and use it in GitHub Desktop.
Config example with custom toml loaders and the builtin env loader
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
MY_APP_APP__PASSWORD="secret_foo" | |
MY_APP_DB__PASSWORD="secret_bar" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import importlib.resources | |
from pathlib import Path | |
from pydantic import BaseModel, BaseSettings, validator | |
import toml | |
def default_settings(*_): | |
with importlib.resources.path("my_app", "default.toml") as path: | |
with path.open() as f: | |
return toml.load(f) | |
def user_settings(*_): | |
user_config = Path("user.toml") # expected to be in cwd | |
try: | |
with open(user_config) as f: | |
return toml.load(f) | |
except FileNotFoundError: | |
print(f"User config expected at '{user_config}', but not found.") | |
return {} | |
class App(BaseModel): | |
loglevel: str | |
user: str | |
password: str | |
version: tuple[int, int, int] # really shouldn't be in a config, but good example for a complex setting | |
@validator("version", pre=True) | |
def parse_version(cls, v): | |
if isinstance(v, str): | |
raw_version = v.split(".") | |
if len(raw_version) != 3: | |
raise ValueError(f"Expected simple semver format, got {v} instead.") | |
v = tuple(int(x) for x in raw_version) | |
return v | |
class Model(BaseModel): | |
C: float | |
gamma: float | |
class Database(BaseModel): | |
backend: str | |
host: str | |
port: int | |
user: str | |
password: str | |
class Settings(BaseSettings): | |
app: App | |
model: Model | |
db: Database | |
class Config: | |
@classmethod | |
def customise_sources(cls, env_settings, **kwargs): | |
# the order in which these functions are returned decides the | |
# override order, which (apparently) is from right to left | |
return env_settings, user_settings, default_settings | |
env_prefix = "MY_APP_" | |
env_nested_delimiter = "__" | |
cfg = Settings() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# part of the source code, provide default values for all settings | |
[app] | |
loglevel = "DEBUG" | |
user = "" | |
password = "" | |
version = "0.10.2" | |
[model] | |
C = 5 | |
gamma = 0.01 | |
[db] | |
backend = "sqlite" | |
host = "" | |
port = 0 | |
user = "" | |
password = "" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# in cwd when code is run | |
[app] | |
user = "foo" | |
[db] | |
backend = "postgresql" | |
user = "bar" | |
host = "127.0.23.2" | |
port = 3099 | |
[model] | |
C = 7 | |
gamma = 0.3 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Given an installed package
my_app
and after exporting the.env
file, the config would look like this: