Configuration¶
Config layers settings from several sources, highest priority first:
os.environ— dotted keys map toUPPER__CASE(db.url→DB__URL)- a
.envfile (defaults to.envin the working directory) config/settings.<profile>.yamlconfig/settings.yaml- constructor
defaults
from shakti import Config
config = Config() # profile from SHAKTI_ENV, defaults to "development"
app = Shakti(config=config)
Reading values¶
config.get("app.debug", default=False, cast=bool)
config.require("db.url") # raises ConfigError if missing
config.get("server.port", 8000, cast=int)
get() returns default if the key isn't found anywhere. require() raises ConfigError instead. cast accepts any callable; passing bool uses a lenient truthy/falsy parser ("1"/"true"/"yes"/"on" → True, "0"/"false"/"no"/"off" → False) rather than Python's own bool().
Keys are dotted paths into the merged YAML tree:
Environment variable interpolation¶
String values in YAML support ${ENV_VAR} and ${ENV_VAR:default}:
Profiles¶
Config(profile="production") (or the SHAKTI_ENV environment variable) selects config/settings.production.yaml, which is deep-merged on top of the base config/settings.yaml — set shared defaults in the base file and override per-environment values in the profile file.
Secrets¶
config.secret(key) returns a Secret wrapper (its repr() never shows the value, so it's safe to log a config object without leaking it):
It also supports Docker/Kubernetes-style file-based secrets: if <KEY>_FILE is set (e.g. DB__PASSWORD_FILE=/run/secrets/db_password), the value is read from that file instead of the environment directly.
Environment variable naming¶
Dotted keys map to environment variables by uppercasing and replacing ./- with _: db.url → DB__URL, app.debug → APP__DEBUG. Environment variables always win over YAML and defaults.