„Ja, ja, YAML schon wieder.“ — Every backend dev in Berlin, probably.
yayaya is a tiny helper for Yet Another YAml YArd (look, the letters lined up and we ran with it). It loads one YAML file—or several merged in order—lets you read nested keys with dot notation, and expands ${ENV_VAR} placeholders so secrets can live in the environment where they belong—not committed next to your instruction: prompts.
No framework. No magic beans. Just pyyaml and the sound of your PM saying jajaja when you tell them config is “basically done.”
pip install yayayaOr point pip at this repo if you live on the edge.
from yayaya import init, get, contains
init("/path/to/config.yaml")
title = get("app.title", default="Untitled")
db_url = get("database.url", required=True)
if contains("features.experimental"):
...Pass a list: earlier files are the base, later ones override. Nested dicts are deep-merged; scalars and lists are replaced entirely by the newer file. Expansion runs once on the merged result.
init(["/etc/myapp/defaults.yaml", "/instance/config.yaml", "/instance/local.yaml"])Useful for defaults + tenant config + secrets-by-path without copy-pasting huge trees.
After parsing YAML, all strings are walked recursively. Placeholders like ${API_KEY} are replaced with values from os.environ. Missing variables become empty strings.
# config.yaml
service:
api_key: "${API_KEY}"
port: 8080import os
from yayaya import init, get
os.environ["API_KEY"] = "secret"
init("config.yaml")
assert get("service.api_key") == "secret"
assert get("service.port") == 8080You can also run expansion yourself (e.g. on a dict you built elsewhere):
from yayaya import expand_env_placeholders
data = expand_env_placeholders({"x": "${HOME}"}, environ=os.environ)| Function | Purpose |
|---|---|
init(path) |
Load one YAML file, or init([p1, p2, ...]) to merge left → right. |
get(key, default=None, required=False) |
Dot-path lookup ("db.pool.size"). |
contains(key) |
Whether the path exists. |
reload_config() |
Re-read the same path(s) in the same order. |
override_config_path(path) |
Same as init (one path or a list). |
config_paths() |
Absolute paths last passed to init / override_config_path. |
deep_merge(a, b) |
Deep-merge two dict-like trees (lists replaced, not spliced). |
expand_env_placeholders(value, environ=None) |
Recursive ${VAR} substitution. |
Exceptions (all subclass ConfigError): ConfigNotLoadedError, ConfigFileNotFoundError, ConfigKeyNotFoundError.
pip install -e ".[dev]"
python -m unittest discover -s tests -vWhatever the repo owner says—ask Karel if you’re unsure.
If YAML were a conversation, yayaya is the part where you nod three times and actually read the file.