Skip to content

Configuration Examples

Practical examples for multi-source configuration management.

Overview

The configuration module provides powerful, flexible configuration loading from multiple sources with automatic validation and type safety.

Examples

1. Basic Configuration

File: examples/config/01_basic_config.py

Introduction to configuration loading.

Topics: - Loading from dictionaries (DictSource) - Loading from files (YAML, JSON, TOML) - Using default values - Convenience methods (load_from_file, load_from_env) - Nested configuration structures - Automatic validation with Pydantic - Type coercion

Key Concepts: - Simple, type-safe configuration - Multiple file format support - Automatic validation

Run:

uv run python examples/config/01_basic_config.py

2. Multi-Source Configuration

File: examples/config/02_multi_source_config.py

Advanced multi-source patterns.

Topics: - Source priority (later sources override earlier) - Deep merge of nested configuration - Layered configuration (Defaults → File → Environment) - Optional configuration files - Multi-format configuration - Environment-specific configuration

Key Concepts: - Flexible configuration composition - Environment-based overrides - Secrets management

Run:

uv run python examples/config/02_multi_source_config.py

3. Deployment Patterns

File: examples/config/03_deployment_patterns.py

Real-world deployment scenarios.

Topics: - Docker Compose: Environment variable based config - Kubernetes: ConfigMap + Secrets pattern - AWS ECS/Fargate: ECS Task Definition + Secrets Manager - Cloud-Native: Multi-source layered config - 12-Factor App: Pure environment variable config

Key Concepts: - Container orchestration patterns - Cloud platform integration - Secrets management best practices - 12-factor methodology

Run:

uv run python examples/config/03_deployment_patterns.py

4. Validation Patterns

File: examples/config/04_validation_patterns.py

Advanced validation with Pydantic.

Topics: - Field Constraints: Ranges, lengths, patterns - String Patterns: Email, URL, regex patterns - Enum Validation: Fixed choices - Custom Validators: Business logic validation - Conditional Validation: Cross-field validation - Type Aliases: Reusable validation rules

Key Concepts: - Data validation at load time - Custom business rules - Helpful error messages - Type safety

Run:

uv run python examples/config/04_validation_patterns.py

Quick Start

from dspu.config import Config, FileSource, EnvSource
from pydantic import BaseModel

class AppConfig(BaseModel):
    app_name: str
    debug: bool = False
    api_key: str

# Load from file with environment overrides
config = Config.load(
    AppConfig,
    sources=[
        FileSource("config.yaml"),
        EnvSource(prefix="APP_"),
    ],
)

print(f"App: {config.app_name}")
print(f"Debug: {config.debug}")

Common Patterns

Pattern 1: Local Development

config = Config.load(
    AppConfig,
    sources=[
        FileSource("config.yaml"),                    # Base config
        FileSource("config.local.yaml", required=False),  # Local overrides
        EnvSource(prefix="APP_"),                     # Environment overrides
    ],
)

Pattern 2: Docker Compose

config = Config.load(
    AppConfig,
    sources=[
        EnvSource(prefix="MYAPP_", separator="__"),
    ],
)

Pattern 3: Kubernetes

config = Config.load(
    AppConfig,
    sources=[
        FileSource("/config/app.yaml"),  # ConfigMap
        EnvSource(prefix="", separator="__"),  # Secrets
    ],
)

Pattern 4: Environment-Specific

import os

env = os.getenv("ENV", "development")

config = Config.load(
    AppConfig,
    sources=[
        FileSource("config.yaml"),           # Base
        FileSource(f"config.{env}.yaml"),    # Environment-specific
    ],
)

Configuration Layers

Best practice is to layer your configuration:

Defaults (code) → Base file → Environment file → Environment variables → Secrets

Example

from pydantic import BaseModel, Field

class DatabaseConfig(BaseModel):
    host: str = "localhost"      # Default in code
    port: int = 5432             # Default in code
    name: str
    password: str

config = Config.load(
    DatabaseConfig,
    sources=[
        FileSource("config.yaml"),              # host, port, name
        FileSource(f"config.{env}.yaml"),       # Override host
        EnvSource(prefix="DB_", separator="__"), # password from DB_PASSWORD
    ],
)

Supported Formats

Format Extensions Use Case
YAML .yaml, .yml Human-readable, common for configs
JSON .json Machine-readable, APIs
TOML .toml Python ecosystem (pyproject.toml)
HOCON .conf, .hocon Akka, complex hierarchical configs
ENV .env Secrets, Docker, simple key=value

Format Auto-Detection

DSPU automatically detects the format from the file extension:

config = Config.load_from_file(AppConfig, "config.yaml")  # Auto-detects YAML
config = Config.load_from_file(AppConfig, "config.json")  # Auto-detects JSON
config = Config.load_from_file(AppConfig, "config.toml")  # Auto-detects TOML

Or specify explicitly:

config = Config.load_from_file(AppConfig, "settings.txt", format="json")

Environment Variables

Nested Keys

Use double underscore __ for nested keys:

# Environment variables
export APP_DATABASE__HOST=localhost
export APP_DATABASE__PORT=5432
# Configuration model
class DatabaseConfig(BaseModel):
    host: str
    port: int

class AppConfig(BaseModel):
    database: DatabaseConfig

# Load
config = Config.load(
    AppConfig,
    sources=[EnvSource(prefix="APP_", separator="__")],
)

Prefixes

Use prefixes to namespace environment variables:

# APP_DEBUG=true
config = Config.load(AppConfig, sources=[EnvSource(prefix="APP_")])

Validation

Basic Validation

from pydantic import BaseModel, Field

class AppConfig(BaseModel):
    port: int = Field(ge=1, le=65535)  # Port range
    workers: int = Field(ge=1, le=100)  # Worker count
    timeout: float = Field(gt=0)        # Positive timeout

String Patterns

from pydantic import BaseModel, EmailStr, HttpUrl

class AppConfig(BaseModel):
    email: EmailStr                    # Valid email
    api_url: HttpUrl                   # Valid URL
    api_key: str = Field(min_length=32) # Minimum length

Custom Validators

from pydantic import BaseModel, field_validator

class AppConfig(BaseModel):
    database_url: str

    @field_validator("database_url")
    @classmethod
    def validate_database_url(cls, v: str) -> str:
        if not v.startswith(("postgresql://", "mysql://")):
            raise ValueError("Invalid database URL scheme")
        return v

Best Practices

DO: - Layer your configuration (defaults → file → env → secrets) - Use Pydantic models for validation - Use prefixes for environment variables - Make local overrides optional (required=False) - Provide sensible defaults - Document required vs optional settings

DON'T: - Never commit secrets to version control - Don't use loose types (use validation) - Don't skip validation (fail fast) - Don't hardcode environment-specific values

Security

Never Commit Secrets

# .gitignore
.env
.env.local
*.secret
config.local.yaml

Use Environment Variables for Secrets

# config.yaml (committed)
database:
  host: localhost
  port: 5432
  name: myapp

# Environment variables (not committed)
export DB_PASSWORD=secret123
export API_KEY=sk_live_abc123

Use Secret Managers in Production

from dspu.config import Config, FileSource, EnvSource
from dspu.security import SecretManager

# Load base config
config = Config.load(AppConfig, sources=[FileSource("config.yaml")])

# Load secrets from AWS Secrets Manager
secrets = SecretManager.from_aws(region="us-east-1")
config.database.password = secrets.get("database/password")

Troubleshooting

Common Issues

Issue: ValidationError: Field required - Solution: Provide the required field or add a default value

Issue: ConfigurationError: Configuration file not found - Solution: Check file path or use required=False for optional files

Issue: Environment variables not being picked up - Solution: Check prefix and separator match your env var names

Issue: Values not overriding as expected - Solution: Check source order - later sources override earlier ones

See Also