Settings management using Pydantic with support for multiple configuration sources including environment variables, configuration files, CLI arguments, and cloud secret management services
—
Load configuration from environment variables, .env files, and various configuration file formats including JSON, YAML, TOML, and Docker/Kubernetes secrets. These sources provide flexible configuration management for different deployment environments and use cases.
Load settings from environment variables with support for prefixes, nested structures, and type conversion.
class EnvSettingsSource(PydanticBaseEnvSettingsSource):
"""Source for environment variables."""
def __init__(
self,
settings_cls: type[BaseSettings],
case_sensitive: bool | None = None,
env_prefix: str | None = None,
env_nested_delimiter: str | None = None,
env_nested_max_split: int | None = None,
env_ignore_empty: bool | None = None,
env_parse_none_str: str | None = None,
env_parse_enums: bool | None = None,
):
"""
Initialize environment settings source.
Parameters:
- settings_cls: The settings class
- case_sensitive: Whether environment variable names are case-sensitive
- env_prefix: Prefix for environment variable names
- env_nested_delimiter: Delimiter for nested environment variables
- env_nested_max_split: Maximum splits for nested variables
- env_ignore_empty: Whether to ignore empty environment variables
- env_parse_none_str: String value to parse as None
- env_parse_enums: Whether to parse enum field names to values
"""Load settings from .env files with support for multiple files, encodings, and environment variable processing.
class DotEnvSettingsSource(EnvSettingsSource):
"""Source for .env file loading."""
def __init__(
self,
settings_cls: type[BaseSettings],
env_file: DotenvType | None = ENV_FILE_SENTINEL,
env_file_encoding: str | None = None,
case_sensitive: bool | None = None,
env_prefix: str | None = None,
env_nested_delimiter: str | None = None,
env_nested_max_split: int | None = None,
env_ignore_empty: bool | None = None,
env_parse_none_str: str | None = None,
env_parse_enums: bool | None = None,
):
"""
Initialize .env file settings source.
Parameters:
- settings_cls: The settings class
- env_file: Path(s) to .env file(s) to load
- env_file_encoding: Encoding for .env files
- Other parameters: Same as EnvSettingsSource
"""
def read_env_file(
file_path: Path,
*,
encoding: str | None = None,
case_sensitive: bool = False,
ignore_empty: bool = False,
parse_none_str: str | None = None,
) -> Mapping[str, str | None]:
"""
Read and parse environment files.
Note: This function is deprecated and will be removed in the next version.
Use DotEnvSettingsSource._static_read_env_file if needed.
Parameters:
- file_path: Path to environment file
- encoding: File encoding
- case_sensitive: Whether keys are case-sensitive
- ignore_empty: Whether to ignore empty values
- parse_none_str: String value to parse as None
Returns:
Mapping of environment variables
"""Load settings from JSON configuration files with support for nested structures and file encoding options.
class JsonConfigSettingsSource(InitSettingsSource, ConfigFileSourceMixin):
"""Source for JSON configuration files."""
def __init__(
self,
settings_cls: type[BaseSettings],
json_file: PathType | None = None,
json_file_encoding: str | None = None,
):
"""
Initialize JSON configuration source.
Parameters:
- settings_cls: The settings class
- json_file: Path to JSON configuration file
- json_file_encoding: Encoding for JSON file
"""Load settings from YAML configuration files with support for configuration sections and file encoding.
class YamlConfigSettingsSource(InitSettingsSource, ConfigFileSourceMixin):
"""Source for YAML configuration files."""
def __init__(
self,
settings_cls: type[BaseSettings],
yaml_file: PathType | None = None,
yaml_file_encoding: str | None = None,
yaml_config_section: str | None = None,
):
"""
Initialize YAML configuration source.
Parameters:
- settings_cls: The settings class
- yaml_file: Path to YAML configuration file
- yaml_file_encoding: Encoding for YAML file
- yaml_config_section: Top-level key to load from YAML file
"""Load settings from TOML configuration files with support for table headers and nested structures.
class TomlConfigSettingsSource(InitSettingsSource, ConfigFileSourceMixin):
"""Source for TOML configuration files."""
def __init__(
self,
settings_cls: type[BaseSettings],
toml_file: PathType | None = None,
):
"""
Initialize TOML configuration source.
Parameters:
- settings_cls: The settings class
- toml_file: Path to TOML configuration file
"""
class PyprojectTomlConfigSettingsSource(TomlConfigSettingsSource):
"""Source for pyproject.toml configuration files."""
def __init__(
self,
settings_cls: type[BaseSettings],
pyproject_toml_depth: int = 0,
pyproject_toml_table_header: tuple[str, ...] = (),
):
"""
Initialize pyproject.toml configuration source.
Parameters:
- settings_cls: The settings class
- pyproject_toml_depth: Directory levels up to search for pyproject.toml
- pyproject_toml_table_header: TOML table header path
"""Load settings from Docker/Kubernetes secrets files with support for secrets directories and file-based configuration.
class SecretsSettingsSource(PydanticBaseEnvSettingsSource):
"""Source for Docker/Kubernetes secrets files."""
def __init__(
self,
settings_cls: type[BaseSettings],
secrets_dir: PathType | None = None,
case_sensitive: bool | None = None,
env_prefix: str | None = None,
):
"""
Initialize secrets file source.
Parameters:
- settings_cls: The settings class
- secrets_dir: Directory containing secret files
- case_sensitive: Whether secret names are case-sensitive
- env_prefix: Prefix for secret names
"""import os
from pydantic_settings import BaseSettings
class AppSettings(BaseSettings):
app_name: str = "MyApp"
debug: bool = False
max_connections: int = 100
model_config = SettingsConfigDict(
env_prefix='MYAPP_',
case_sensitive=False
)
# Set environment variables
os.environ['MYAPP_DEBUG'] = 'true'
os.environ['MYAPP_MAX_CONNECTIONS'] = '200'
settings = AppSettings()
print(f"Debug: {settings.debug}, Connections: {settings.max_connections}")from pydantic import BaseModel
class DatabaseConfig(BaseModel):
host: str = "localhost"
port: int = 5432
credentials: dict[str, str] = {}
class AppSettings(BaseSettings):
database: DatabaseConfig = DatabaseConfig()
model_config = SettingsConfigDict(
env_nested_delimiter='__',
case_sensitive=False
)
# Environment variables: DATABASE__HOST, DATABASE__PORT, DATABASE__CREDENTIALS__USERNAME
os.environ['DATABASE__HOST'] = 'prod-db.company.com'
os.environ['DATABASE__PORT'] = '5432'
os.environ['DATABASE__CREDENTIALS__USERNAME'] = 'app_user'
settings = AppSettings()# .env file content:
# DEBUG=true
# DATABASE_URL=postgresql://localhost/myapp
# API_KEY=secret-key-here
class AppSettings(BaseSettings):
debug: bool = False
database_url: str
api_key: str
model_config = SettingsConfigDict(
env_file='.env',
env_file_encoding='utf-8'
)
settings = AppSettings() # Loads from .env fileclass AppSettings(BaseSettings):
debug: bool = False
database_url: str
api_key: str
model_config = SettingsConfigDict(
env_file=['.env', '.env.local', '.env.production'],
env_file_encoding='utf-8'
)
# Files loaded in order, later files override earlier ones
settings = AppSettings()# config.json:
# {
# "app_name": "Production App",
# "database": {
# "host": "prod-db.company.com",
# "port": 5432
# },
# "features": {
# "enable_logging": true,
# "max_retries": 3
# }
# }
from pydantic import BaseModel
class DatabaseConfig(BaseModel):
host: str
port: int
class FeatureConfig(BaseModel):
enable_logging: bool
max_retries: int
class AppSettings(BaseSettings):
app_name: str
database: DatabaseConfig
features: FeatureConfig
model_config = SettingsConfigDict(
json_file='config.json',
json_file_encoding='utf-8'
)
settings = AppSettings()# config.yaml:
# production:
# app_name: "Production App"
# database:
# host: "prod-db.company.com"
# port: 5432
# api:
# timeout: 30
# retries: 3
class AppSettings(BaseSettings):
app_name: str
database: dict
api: dict
model_config = SettingsConfigDict(
yaml_file='config.yaml',
yaml_config_section='production' # Load from 'production' section
)
settings = AppSettings()# Docker secrets mounted at /run/secrets/
# Files: /run/secrets/db_password, /run/secrets/api_key
class AppSettings(BaseSettings):
db_password: str
api_key: str
model_config = SettingsConfigDict(
secrets_dir='/run/secrets'
)
settings = AppSettings() # Loads secrets from filesfrom pydantic_settings import JsonConfigSettingsSource, YamlConfigSettingsSource
class AppSettings(BaseSettings):
app_name: str = "MyApp"
debug: bool = False
@classmethod
def settings_customise_sources(
cls,
settings_cls,
init_settings,
env_settings,
dotenv_settings,
file_secret_settings,
):
return (
init_settings,
JsonConfigSettingsSource(settings_cls, json_file='config.json'),
YamlConfigSettingsSource(settings_cls, yaml_file='config.yaml'),
env_settings,
dotenv_settings,
file_secret_settings,
)
settings = AppSettings() # Loads from JSON, YAML, env vars, .env, and secretsInstall with Tessl CLI
npx tessl i tessl/pypi-pydantic-settings