Typed Settings

25.3.0 · active · verified Fri Apr 10

Typed Settings is an active Python library (current version 25.3.0) that simplifies loading and merging application settings from various sources like config files (TOML, JSON, YAML), environment variables, and secret vaults into structured, type-hinted classes (attrs, dataclasses, or Pydantic models). It also supports generating command-line interfaces (CLIs) based on these settings. The library follows a calendar versioning scheme and maintains a relatively frequent release cadence, often with monthly updates, reflecting continuous development and use in production environments.

Warnings

Install

Imports

Quickstart

Define settings using `attrs` or `dataclasses` (or Pydantic with optional dependency) with type hints and default values. Use `ts.load` to automatically load and merge settings from config files and environment variables, with later sources overriding earlier ones. Environment variables follow an `APPNAME_OPTION_NAME` pattern by default. `SecretStr` can be used to prevent secrets from being printed in plaintext.

import attrs
from pathlib import Path
import typed_settings as ts
import os

@attrs.frozen
class DatabaseSettings:
    host: str = "localhost"
    port: int = 5432
    user: str = "admin"
    password: ts.SecretStr = ts.SecretStr("")

@ts.settings
class AppSettings:
    debug: bool = False
    log_level: str = "INFO"
    database: DatabaseSettings = attrs.field(factory=DatabaseSettings)

# Simulate a config file
config_content = '''
[myapp]
debug = true
log-level = "DEBUG"

[myapp.database]
host = "my.db.server"
port = 6000
'''
config_file_path = Path("settings.toml")
config_file_path.write_text(config_content)

# Simulate environment variables
os.environ['MYAPP_DATABASE_USER'] = os.environ.get('MYAPP_DATABASE_USER', 'env_user')
os.environ['MYAPP_DATABASE_PASSWORD'] = os.environ.get('MYAPP_DATABASE_PASSWORD', 'env_secret')

try:
    settings = ts.load(
        cls=AppSettings,
        appname="myapp",
        config_files=[config_file_path],
        config_file_section="myapp",
    )
    print(f"Debug: {settings.debug}")
    print(f"Log Level: {settings.log_level}")
    print(f"DB Host: {settings.database.host}")
    print(f"DB Port: {settings.database.port}")
    print(f"DB User: {settings.database.user}")
    print(f"DB Password (hidden): {settings.database.password}")
except Exception as e:
    print(f"Error loading settings: {e}")
finally:
    config_file_path.unlink(missing_ok=True)
    del os.environ['MYAPP_DATABASE_USER']
    del os.environ['MYAPP_DATABASE_PASSWORD']

view raw JSON →