Dead-simple typed config loader for dataclasses (defaults + TOML + env) with great errors.
Project description
saneconfig
Dead-simple typed config loader for dataclasses:
- defaults
- TOML file(s)
- environment variables
with great errors and provenance ("where did this value come from?").
Python 3.11+.
Core package has zero runtime dependencies; optional extras:
saneconfig[dotenv]for.envfile support.
Install
pip install saneconfig
# optional .env support
pip install "saneconfig[dotenv]"
Quick start
from dataclasses import dataclass
from saneconfig import load, REQUIRED
@dataclass
class AppConfig:
debug: bool = False
port: int = 8080
database_url: str = REQUIRED
cfg = load(
AppConfig,
env_prefix="APP",
files=["config.toml", "config.local.toml"],
)
print(cfg.port)
Precedence (highest wins)
- CLI args (
argv=Trueorargv=[...]) - Environment variables
.envfile values (whendotenvis enabled)- TOML files (later overrides earlier)
- Dataclass defaults
TOML example
debug = true
port = 9000
database_url = "postgresql://user:pass@localhost:5432/mydb"
Nested dataclasses map to TOML tables:
[db]
host = "localhost"
port = 5432
Env var mapping
With env_prefix="APP":
APP_PORT=9000->portAPP_DEBUG=true->debug- nested via
__:APP_DB__HOST=localhost->db.host
Booleans accept: true/false, yes/no, on/off, 1/0 (case-insensitive).
Lists in env vars use JSON:
APP_ALLOWED='["a","b"]'
CLI overrides
Enable CLI parsing by passing argv=True (uses sys.argv[1:]) or provide a list explicitly:
cfg = load(
AppConfig,
env_prefix="APP",
argv=["--port=9001", "--db.host=db.internal"],
)
Supported form: --key=value with dotted nesting (--db.host=x).
Provenance / debugging
cfg, report = load(
AppConfig,
env_prefix="APP",
files=["config.toml", "config.local.toml"],
return_report=True,
)
print(report)
Example output:
database_url='postgresql://...' (env:APP_DATABASE_URL)
debug=False (default)
port=9000 (file:config.toml)
Schema docs
You can include richer docs using dataclass metadata:
from dataclasses import dataclass, field
@dataclass
class AppConfig:
port: int = field(default=8080, metadata={"help": "HTTP listen port"})
from saneconfig import dump_schema
print(dump_schema(AppConfig, env_prefix="APP"))
dump_schema(...) includes a Help column using field(metadata={"help": ...}).
Errors that help
If a value cannot be converted:
ConfigError: port expected int but got "eighty"
source: env:APP_PORT
hint: Use a valid int value.
If required values are missing:
ConfigError: missing required configuration values:
- database_url
Supported types (v0.1)
str,int,float,boolOptional[T]list[T](TOML arrays or JSON arrays in env)Literal[...]- nested dataclasses
pathlib.Pathdict[str, T](TOML table or JSON object in env)
Non-goals (by design)
- profiles/composition systems
- interpolation DSLs
- frameworks and global state
MIT Licensed.
A tiny example you can run
from dataclasses import dataclass
from typing import Literal, Optional
from saneconfig import REQUIRED, load
@dataclass
class DB:
host: str = "localhost"
port: int = 5432
@dataclass
class App:
mode: Literal["dev", "prod"] = "dev"
debug: bool = False
port: int = 8080
api_key: str = REQUIRED
db: DB = DB()
notes: Optional[str] = None
cfg, report = load(App, env_prefix="APP", files=["config.toml"], return_report=True)
print(cfg)
print(report)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file saneconfig-0.1.0.tar.gz.
File metadata
- Download URL: saneconfig-0.1.0.tar.gz
- Upload date:
- Size: 14.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7ef26073be5317f419e9f865a08a55ff610bc6b2df1118ff1322c31bd77d4bcf
|
|
| MD5 |
ee874db798465e770c37a8cd88747e07
|
|
| BLAKE2b-256 |
d60f8c11ce6099d45eeccc93d98f6945197436008f4ca93279e0b93b128cee8a
|
File details
Details for the file saneconfig-0.1.0-py3-none-any.whl.
File metadata
- Download URL: saneconfig-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d7a00796a800c1c94fd91116e10044ce68a057701ec2d5361ad6474fcdbc56a6
|
|
| MD5 |
1d4404b394ec6ef4e0b997b3a0b54d76
|
|
| BLAKE2b-256 |
44eef23d0c0f75375f9e10fb9fc60b78170349f90705ea225235c992b6fc70ca
|