Type-safe configuration loader for Python dataclasses. Load config from YAML, JSON, TOML, INI, ENV files, environment variables, Docker secrets, CLI arguments, HashiCorp Vault, Consul, etcd, Apache ZooKeeper, AWS SSM, AWS Secrets Manager, Azure App Configuration, Azure Key Vault, and GCP Secret Manager — with automatic type conversion, validation, and human-readable error messages.
Installation
pip install dature
With optional format support:
pip install dature[yaml] # YAML (ruamel.yaml)
pip install dature[json5] # JSON5
pip install dature[toml] # TOML (toml_rs)
pip install dature[vault] # HashiCorp Vault (hvac)
pip install dature[consul] # Consul (py-consul)
pip install dature[etcd] # etcd (etcd3gw)
pip install dature[zookeeper] # Apache ZooKeeper (kazoo)
pip install dature[aws] # AWS SSM & Secrets Manager (boto3)
pip install dature[azure-appconfig] # Azure App Configuration
pip install dature[azure-keyvault] # Azure Key Vault
pip install dature[gcp] # GCP Secret Manager
pip install dature[watch] # File watching for background reload (watchdog)
pip install dature[secure] # Secret detection heuristics
pip install dature[type-stubs] # Type stubs for the integrations above (mypy/pyright users)
Quick Start
from dataclasses import dataclass
import dature
@dataclass
class Config:
host: str
port: int
debug: bool = False
config = dature.load(dature.Yaml12Source(file="config.yaml"), schema=Config)
Readable errors
Validation errors point at the source file, the line, and the exact value:
from dataclasses import dataclass
from typing import Literal
import dature
@dataclass
class Config:
password: str
host: Literal["production", "staging"]
dature.load(
dature.Yaml12Source(file="config.yaml"),
schema=Config,
masking_mode="secrets_only", # default is "all"
)
host: "development"
password: "my_secret_password"
| dature.errors.exceptions.DatureConfigError: Config loading errors (1)
+-+---------------- 1 ----------------
| dature.errors.exceptions.FieldLoadError: [host] Invalid variant: 'development'
| ├── host: "development"
| │ ^^^^^^^^^^^
| └── FILE 'config.yaml', line 1
+------------------------------------
The same format works for YAML, JSON, JSON5, TOML, INI, ENV files, environment variables, and Docker
secrets. Values are masked by default (masking_mode="all"); the example uses "secrets_only" so
that only password is hidden. See
Masking.
Merging sources
Sources are merged in order, with a strategy for conflicts and per-field rules for lists:
from dataclasses import dataclass
import dature
@dataclass
class Config:
tags: list[str]
config = dature.load(
dature.Yaml12Source(file="base.yaml"), # tags: [web, default]
dature.Yaml12Source(file="override.yaml"), # tags: [web, api]
schema=Config,
field_merges={dature.F[Config].tags: "append"},
)
print(config.tags) # ['web', 'default', 'web', 'api']
Debug report
Pass debug=True to see which source provided each value:
import dature
config = dature.load(
dature.Yaml12Source(file="defaults.yaml"),
dature.Yaml12Source(file="overrides.yaml"),
schema=Config,
debug=True,
)
report = dature.load_report(config)
for origin in report.field_origins:
source = Path(origin.source_file).name if origin.source_file else origin.source_loader_type
print(f"{origin.key} = {origin.value!r} <- {source}")
host = 'production.example.com' <- overrides.yaml
port = 3000 <- defaults.yaml
tags = ['default'] <- defaults.yaml
Key Features
- Multiple sources — YAML, JSON, JSON5, TOML, INI, ENV, environment variables, Docker secrets, CLI args (
argparseor your own), HashiCorp Vault, Consul, etcd, Apache ZooKeeper, AWS SSM, AWS Secrets Manager, Azure App Configuration, Azure Key Vault, GCP Secret Manager - Merging — combine multiple sources with configurable strategies (
"last_wins","first_wins","first_found","raise_on_conflict") and per-field rules ("append","prepend","append_unique", custom callables) - Validation —
Annotatedfield validators, root validators,__post_init__support - Naming — automatic field name mapping (
snake_case↔camelCase↔UPPER_SNAKEetc.) - Secret masking — automatic masking in error messages and logs by field type, name, or heuristic
- ENV expansion —
$VAR,${VAR:-default}substitution in all file formats - Special types —
SecretStr,ByteSize,PaymentCardNumber,URL,Base64UrlStr - Debug report —
debug=Trueshows which source provided each field value - Decorator mode —
@dature.load(meta)auto-loads config on dataclass instantiation with caching - Shared reads —
Source(shared_read=...)shares one raw file read / remote fetch across multipleprefix=-bound schemas - CLI —
dature validateanddature inspectconsole commands for CI and debugging - Cross-source refs & conditional sources — reference values across sources, activate sources based on environment
- Extensible — plug in custom sources, type loaders, and remote backends via
SourceProtocol
See the documentation for detailed guides and API reference.
Why dature?
- Your config stays a plain dataclass. No
BaseSettingsbase class, no vendor lock-in, no Pydantic-specific validators for custom types. Full IDE completion and mypy support come from your own class. - Errors you can act on. The failure names the source, the line, and the value — not a
ValidationErrorwith a model path. - Merge is explicit. Four source strategies plus per-field rules (
append,prepend,append_unique, field groups), instead of a fixed priority order you have to work around. - One schema, many backends. The same dataclass loads from files, environment, CLI, Docker secrets, and remote stores (Vault, Consul, etcd, ZooKeeper, AWS, Azure, GCP) — switch sources without touching the schema.
How dature compares in detail:
When the other side wins: if Pydantic is already your core dependency, you build on FastAPI/SQLModel, or you want a CLI generated from your settings model with subcommands and async entrypoints — pydantic-settings is the natural fit. For ML experiment sweeps and config composition use Hydra. dature is aimed at application and service config: a fixed schema, several sources, and readable failures.
Requirements
- Python >= 3.12
- adaptix >= 3.0.0b11
Development
git clone https://github.com/reagento/dature.git
cd dature
uv sync --all-extras --all-groups
Run tests:
uv run pytest tests/ -v
Lint and type check:
uv run prek run --all-files
Build docs locally:
uv run mkdocs serve
Changelog
Each PR must include a towncrier fragment in the changes/ directory:
# Format: changes/<issue-or-pr-number>.<type>
echo "Added support for YAML anchors." > changes/42.feature
Available <type> values:
| Type | Description |
|---|---|
feature |
New features |
bugfix |
Bug fixes |
doc |
Documentation improvements |
removal |
Deprecations and removals |
misc |
Other changes |
Use +<description> instead of an issue number for changes without a linked issue:
echo "Fixed typo in error message." > changes/+fix-typo.bugfix.md
Releasing
- Run the Release workflow and choose bump type (
patch/minor/major). The next version is calculated from the latest git tag automatically. - The workflow builds the changelog from fragments and creates a PR.
- Merge the PR — CI automatically creates the tag, publishes to PyPI, creates a GitHub Release, and updates docs.
License
Apache License 2.0
Metadata
Release files for dature 1.6.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| dature-1.6.4.tar.gz | 659.3 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| dature-1.6.4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 887.2 kB
Release files / dature-1.6.4.tar.gz
| Download URL | dature-1.6.4.tar.gz |
|---|---|
| Size | 659.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5365660af40f0e7bd17498b95f6bc74452479d2ee0fd62f94aaf6dc9b41d16b4
|
|
BLAKE2b-256 checksum How to use checksums |
c8cfa6c2174a7784d952e46dd8355020460ef3c02e6caa7ee3d0bd04f49108bf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.
Transparency logRelease files / dature-1.6.4-py3-none-any.whl
| Download URL | dature-1.6.4-py3-none-any.whl |
|---|---|
| Size | 227.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
743d189fbf6ba53a97a2fd7ef43275aca9bb36cb56354d23b9f7fe0d58b578a5
|
|
BLAKE2b-256 checksum How to use checksums |
5a8bb64130d813dd01054c982f13e76bce06444c55440ffaa56f528b575d8247
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.
Transparency logSecurity for dature 1.6.4
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for dature-1.6.4.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.