Skip to content

Naming#

Control how dataclass field names map to config keys.

name_style#

Automatically convert between naming conventions. Maps dataclass field names (snake_case) to the convention used in config files.

Value Example
lower_snake my_field
upper_snake MY_FIELD
lower_camel myField
upper_camel MyField
lower_kebab my-field
upper_kebab MY-FIELD
"""name_style — auto-convert camelCase keys to snake_case fields."""

from dataclasses import dataclass
from pathlib import Path

import dature

SOURCES_DIR = Path(__file__).parent / "sources"


@dataclass
class ApiConfig:
    user_name: str
    max_retries: int
    is_active: bool
    base_url: str


config = dature.load(
    dature.Yaml12Source(
        file=SOURCES_DIR / "naming_name_style.yaml",
        name_style="lower_camel",
    ),
    schema=ApiConfig,
)

assert config.user_name == "admin"
assert config.max_retries == 3
assert config.is_active is True
assert config.base_url == "https://api.example.com"
userName: admin
maxRetries: 3
isActive: true
baseUrl: "https://api.example.com"

field_mapping#

Explicit field renaming using F objects. Takes priority over name_style:

"""field_mapping — explicit field renaming with F objects."""

from dataclasses import dataclass
from pathlib import Path

import dature

SOURCES_DIR = Path(__file__).parent / "sources"


@dataclass
class DbConfig:
    database_url: str
    secret_key: str
    pool_size: int


config = dature.load(
    dature.Yaml12Source(
        file=SOURCES_DIR / "naming_field_mapping.yaml",
        field_mapping={
            dature.F[DbConfig].database_url: "db_url",
            dature.F[DbConfig].secret_key: "key",
            dature.F[DbConfig].pool_size: "pool",
        },
    ),
    schema=DbConfig,
)

assert config.database_url == "postgresql://localhost:5432/mydb"
assert config.secret_key == "my-secret-key"
assert config.pool_size == 10
db_url: "postgresql://localhost:5432/mydb"
key: "my-secret-key"
pool: 10

Multiple Aliases#

A field can have multiple aliases — the first matching key in the source wins:

field_mapping = {dature.F[Config].name: ("fullName", "userName")}

Nested Fields#

Nested fields are supported via F[Owner].field syntax on inner dataclasses:

"""field_mapping — nested dataclass renaming with F objects."""

from dataclasses import dataclass
from pathlib import Path

import dature

SOURCES_DIR = Path(__file__).parent / "sources"


@dataclass
class Address:
    city: str
    street: str


@dataclass
class User:
    name: str
    address: Address


config = dature.load(
    dature.Yaml12Source(
        file=SOURCES_DIR / "naming_nested_fields.yaml",
        field_mapping={
            dature.F[User].name: "fullName",
            dature.F[User].address: "location",
            dature.F[Address].city: "cityName",
            dature.F[Address].street: "streetName",
        },
    ),
    schema=User,
)

assert config.name == "Alice"
assert config.address.city == "Paris"
assert config.address.street == "Rue de Rivoli"
fullName: Alice
location:
  cityName: Paris
  streetName: Rue de Rivoli

Decorator Mode#

In decorator mode where the class is not yet defined, use a string:

field_ref = F["Config"].name  # autocomplete doesn't work here

prefix#

Filters keys for ENV, or extracts a nested object from files:

"""prefix — filter ENV keys by prefix."""

import os
from dataclasses import dataclass

import dature

os.environ["MYAPP_HOST"] = "localhost"
os.environ["MYAPP_PORT"] = "9090"
os.environ["MYAPP_DEBUG"] = "true"


@dataclass
class Config:
    host: str
    port: int
    debug: bool = False


config = dature.load(dature.EnvSource(prefix="MYAPP_"), schema=Config)

assert config.host == "localhost"
assert config.port == 9090
assert config.debug is True

For file-based sources, prefix navigates into nested objects using dot notation:

"""prefix — extract nested object from file sources using dot notation."""

from dataclasses import dataclass
from pathlib import Path

import dature

SOURCES_DIR = Path(__file__).parent / "sources"


@dataclass
class Database:
    host: str
    port: int


db = dature.load(
    dature.Yaml12Source(
        file=SOURCES_DIR / "naming_prefix_nested.yaml",
        prefix="app.database",
    ),
    schema=Database,
)

assert db.host == "localhost"
assert db.port == 5432
app:
  database:
    host: localhost
    port: 5432

nested_sep#

Delimiter for building nested structures from flat ENV variables and Docker secrets file names. Default: "__".

"""nested_sep — build nested structures from flat ENV variables."""

import os
from dataclasses import dataclass

import dature

os.environ["NS_DB__HOST"] = "localhost"
os.environ["NS_DB__PORT"] = "5432"


@dataclass
class Database:
    host: str
    port: int


@dataclass
class Config:
    db: Database


config = dature.load(
    dature.EnvSource(prefix="NS_", nested_sep="__"),
    schema=Config,
)

assert config.db.host == "localhost"
assert config.db.port == 5432