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
from dataclasses import dataclass

import dature


@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 — see Field Paths. Takes priority over name_style:

from dataclasses import dataclass

import dature


@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:


Absolute Aliases#

By default, aliases are relative to the source prefix — "HOST" with prefix="APP_" matches APP_HOST. Use Absolute to match the raw key regardless of prefix, which is useful when a field comes from a key that doesn't share the source prefix:

from dataclasses import dataclass

import dature


@dataclass
class Config:
    host: str
    password: str
    token: str


config = dature.load(
    dature.EnvFileSource(
        file=SOURCES_DIR / "naming_absolute_alias.env",
        prefix="APP_",
        field_mapping={
            dature.F[Config].host: "HOST",
            dature.F[Config].password: dature.Absolute("DB_PASSWORD"),
            dature.F[Config].token: ("TOKEN", dature.Absolute("DB_TOKEN")),
        },
    ),
    schema=Config,
)

assert config.host == "localhost"  # APP_HOST — prefix applied
assert config.password == "s3cr3t"  # DB_PASSWORD — prefix bypassed
assert config.token == "root-token"  # DB_TOKEN — Absolute in tuple
APP_HOST=localhost
DB_PASSWORD=s3cr3t
DB_TOKEN=root-token

Absolute works across all source types. For file-based sources it reads from the document root even when prefix navigates into a subtree.

Nested Fields#

Nested fields are supported via F[Owner].field syntax on inner dataclasses — see Field Paths for all syntax forms:

from dataclasses import dataclass

import dature


@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:


prefix#

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

```python
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:

from dataclasses import dataclass

import dature


@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: "__".

```python
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

```