Introduction#
dature offers two ways to load configuration: function mode and decorator mode.
"""Load from YAML file."""
from dataclasses import dataclass
from pathlib import Path
import dature
SHARED_DIR = Path(__file__).parents[1] / "shared"
@dataclass
class Config:
host: str
port: int
debug: bool = False
config = dature.load(
dature.Yaml12Source(file=SHARED_DIR / "common_app.yaml"),
schema=Config,
)
assert config.host == "localhost"
assert config.port == 8080
assert config.debug is False
"""Decorator mode — auto-load config from a YAML file."""
from dataclasses import dataclass
from pathlib import Path
import dature
SHARED_DIR = Path(__file__).parents[1] / "shared"
@dature.load(dature.Yaml12Source(file=SHARED_DIR / "common_app.yaml"))
@dataclass
class Config:
host: str
port: int
debug: bool = False
config = Config()
assert config.host == "localhost"
assert config.port == 8080
assert config.debug is False
Explicit arguments to __init__ take priority over loaded values:
All Formats#
Use the specific Source subclass for your format. Here's the same config loaded from every supported format:
"""Load from YAML file."""
from dataclasses import dataclass
from pathlib import Path
import dature
SHARED_DIR = Path(__file__).parents[1] / "shared"
@dataclass
class Config:
host: str
port: int
debug: bool = False
config = dature.load(
dature.Yaml12Source(file=SHARED_DIR / "common_app.yaml"),
schema=Config,
)
assert config.host == "localhost"
assert config.port == 8080
assert config.debug is False
"""Load from JSON file."""
from dataclasses import dataclass
from pathlib import Path
import dature
SOURCES_DIR = Path(__file__).parent / "sources"
@dataclass
class Config:
host: str
port: int
debug: bool = False
config = dature.load(
dature.JsonSource(file=SOURCES_DIR / "intro_app.json"),
schema=Config,
)
assert config.host == "localhost"
assert config.port == 8080
assert config.debug is False
"""Load from JSON5 file."""
from dataclasses import dataclass
from pathlib import Path
import dature
SOURCES_DIR = Path(__file__).parent / "sources"
@dataclass
class Config:
host: str
port: int
debug: bool = False
config = dature.load(
dature.Json5Source(file=SOURCES_DIR / "intro_app.json5"),
schema=Config,
)
assert config.host == "localhost"
assert config.port == 8080
assert config.debug is False
"""Load from TOML file."""
from dataclasses import dataclass
from pathlib import Path
import dature
SOURCES_DIR = Path(__file__).parent / "sources"
@dataclass
class Config:
host: str
port: int
debug: bool = False
config = dature.load(
dature.Toml11Source(file=SOURCES_DIR / "intro_app.toml"),
schema=Config,
)
assert config.host == "localhost"
assert config.port == 8080
assert config.debug is False
"""Load from INI file with section prefix."""
from dataclasses import dataclass
from pathlib import Path
import dature
SOURCES_DIR = Path(__file__).parent / "sources"
@dataclass
class Config:
host: str
port: int
debug: bool = False
config = dature.load(
dature.IniSource(file=SOURCES_DIR / "intro_app.ini", prefix="app"),
schema=Config,
)
assert config.host == "localhost"
assert config.port == 8080
assert config.debug is False
"""Load from ENV file."""
from dataclasses import dataclass
from pathlib import Path
import dature
SOURCES_DIR = Path(__file__).parent / "sources"
@dataclass
class Config:
host: str
port: int
debug: bool = False
config = dature.load(
dature.EnvFileSource(file=SOURCES_DIR / "intro_app.env"),
schema=Config,
)
assert config.host == "localhost"
assert config.port == 8080
assert config.debug is False
"""Load from Docker secrets directory."""
from dataclasses import dataclass
from pathlib import Path
import dature
SOURCES_DIR = Path(__file__).parent / "sources"
@dataclass
class Config:
host: str
port: int
debug: bool = False
config = dature.load(
dature.DockerSecretsSource(dir_=SOURCES_DIR / "intro_app_docker_secrets"),
schema=Config,
)
assert config.host == "localhost"
assert config.port == 8080
assert config.debug is False
See the full list of Source classes and their extra dependencies on the main page.
Source Reference#
@dataclass(kw_only=True, repr=False)
class Source(abc.ABC):
prefix: "DotSeparatedPath | None" = None
name_style: "NameStyle | None" = None
field_mapping: "FieldMapping | None" = None
root_validators: "Iterable[RootPredicate] | None" = None
validators: "FieldValidators | None" = None
expand_env_vars: "ExpandEnvVarsMode | None" = None
skip_if_broken: bool | None = None
skip_field_if_invalid: "bool | tuple[FieldPath, ...] | None" = None
type_loaders: "TypeLoaderMap | None" = None
tag: str | None = None
when: "Mapping[str, str | tuple[str, ...]] | None" = None
format_name: ClassVar[str]
location_label: ClassVar[str]
config_group: ClassVar[str | None] = None
retorts: "dict[tuple[type, frozenset[tuple[type, Any]]], Retort]" = field(
default_factory=dict,
init=False,
repr=False,
)
| Parameter | Description |
|---|---|
prefix | Filter ENV keys ("APP_") or extract nested object ("app.database") |
name_style | Naming convention mapping. See Naming |
field_mapping | Explicit field renaming with F objects. See Naming |
root_validators | Post-load validation of the entire object. See Validation |
validators | Per-field validators in metadata. See Validation |
expand_env_vars | ENV variable expansion mode. See Advanced — ENV Expansion |
skip_if_broken | Skip this source if it fails to load. See Advanced — Skipping Broken Sources |
skip_field_if_invalid | Skip invalid fields from this source. See Advanced — Skipping Invalid Fields |
type_loaders | Custom type converters for this source. See Custom Types & Loaders |
FileSource subclasses (JsonSource, Yaml*Source, Toml*Source, IniSource, Json5Source) also have:
| Parameter | Description |
|---|---|
file | Path to config file (str, Path) or file-like object (BytesIO, StringIO). None → empty path |
FlatKeySource subclasses (EnvSource, EnvFileSource, DockerSecretsSource) also have:
| Parameter | Description |
|---|---|
nested_sep | Delimiter for flat→nested conversion. Default: "__" |
nested_resolve_strategy | Priority when both JSON and flat keys exist for a nested field: "flat" (default) or "json". See Nested Resolve |
nested_resolve | Per-field strategy overrides using F objects. Takes priority over nested_resolve_strategy. See Nested Resolve |
File-Like Objects#
file accepts file-like objects (StringIO, BytesIO, and any TextIOBase/BufferedIOBase/RawIOBase subclass):
"""Load from file-like objects (BytesIO, StringIO)."""
from dataclasses import dataclass
from io import BytesIO, StringIO
import dature
@dataclass
class Config:
host: str
port: int
debug: bool = False
# From StringIO
text_stream = StringIO('{"host": "localhost", "port": 8080, "debug": true}')
config = dature.load(dature.JsonSource(file=text_stream), schema=Config)
assert config.host == "localhost"
assert config.port == 8080
# From BytesIO
binary_stream = BytesIO(b'{"host": "0.0.0.0", "port": 3000}')
config = dature.load(dature.JsonSource(file=binary_stream), schema=Config)
assert config.host == "0.0.0.0"
assert config.port == 3000
Note
EnvSource and DockerSecretsSource do not support file-like objects — they read from environment variables and directories respectively.
Type Coercion#
String values from ENV and file formats are automatically converted. See Supported Types for the full list and Custom Types & Loaders for custom type parsers and format loaders. Error output with source location is covered in Validation — Error Format.