Skip to content

dotenvmodel

Type-safe environment configuration with automatic .env file loading

dotenvmodel combines Pydantic-style field definitions with intelligent .env file cascading inspired by Node.js dotenv patterns. Define your config once, get full type safety, validation, and automatic .env loading — with only one runtime dependency.


Features

  • Minimal Dependencies


    Only requires python-dotenv. No heavy frameworks, no transitive dependency trees.

  • Type Safety


    Full type hint support with automatic type coercion. Your IDE and type checkers (mypy, pyright) understand every field.

  • Rich Type Support


    UUID, Decimal, datetime, timedelta, SecretStr, HttpUrl, PostgresDsn, RedisDsn, Json[T], Path, and all standard Python collection types.

  • Smart .env Loading


    Automatic cascading of .env.env.local.env.{env}.env.{env}.local so you can layer base, local, and environment-specific config.

  • Validation


    Numeric constraints (ge, le, gt, lt), string constraints (min_length, max_length, regex, starts_with, ends_with), choice validation, custom validator hooks, a model-level post_load hook for cross-field validation, string strip processing, and collection size constraints.

  • Configuration Documentation


    Generate docs in table, markdown, JSON, HTML, and dotenv formats with describe(). Auto-generate .env.example files with generate_env_example().

  • Environment Prefixes


    Class-level env_prefix namespaces environment variables so multiple config classes coexist without collisions.

  • Configuration Reload


    Reload configuration at runtime without creating new instances — perfect for responding to SIGHUP or hot config updates.


Installation

pip install dotenvmodel

Or with uv:

uv add dotenvmodel

Python 3.12+

dotenvmodel requires Python 3.12 or newer. It has a single runtime dependency: python-dotenv.


Quick Start

from dotenvmodel import DotEnvConfig, Field

class AppConfig(DotEnvConfig):
    # Required fields (Pydantic-style)
    database_url: str = Field(...)
    api_key: str = Field(...)

    # Optional with defaults and validation
    debug: bool = Field(default=False)
    port: int = Field(default=8000, ge=1, le=65535)
    workers: int = Field(default=4, ge=1, le=16)

    # Collection types
    allowed_hosts: list[str] = Field(default_factory=list)

# Load configuration from cascading .env files
config = AppConfig.load(env="dev")

# Access configuration with full type safety and IntelliSense
print(f"Connecting to {config.database_url}")  # config.database_url: str
print(f"Running on port {config.port}")        # config.port: int
print(f"Debug mode: {config.debug}")           # config.debug: bool

# Generate documentation for your configuration
print(AppConfig.describe())

Next Steps