Skip to main content

Modern, schema-first environment variable loader and manager for Python.

Project description

envsmith

PyPI version CI

A modern, production-ready solution for loading, validating, and managing environment variables in Python using a schema-first approach.

๐Ÿš€ How It Works

envsmith is a Python package that provides a robust way to manage environment variables with the following workflow:

  1. Schema Definition: You define a YAML or JSON schema that specifies:

    • Which environment variables are required
    • What data types they should have
    • Default values for optional variables
    • Validation rules
  2. Environment Loading: The package loads variables from multiple sources:

    • .env files
    • System environment variables
    • Custom dictionaries
    • Priority: System > .env file > defaults
  3. Validation & Type Casting: Each variable is validated against the schema:

    • Required variables are checked for presence
    • Values are cast to the specified types (str, int, float, bool)
    • Helpful error messages for missing/invalid variables
  4. Integration: Seamlessly integrates with FastAPI and Django applications

๐Ÿ”ง Technical Architecture

Core Processing Pipeline

class EnvSmith(dict):
    def __init__(self, schema_path, env_file=".env", env=None):
        # Step 1: Load .env file into environment
        load_dotenv(env_file)
        
        # Step 2: Parse schema file (YAML/JSON)
        self.schema = load_schema(schema_path)
        
        # Step 3: Get environment (system + .env merged)
        self.env = env or dict(os.environ)
        
        # Step 4: Validate and cast types
        validated = validate_env(self.env, self.schema)
        
        # Step 5: Update the dictionary
        self.update(validated)

Data Flow & Priority System

  1. Schema Loading: YAML/JSON โ†’ Python dict with validation rules
  2. Environment Merging: System env + .env files + custom dicts
  3. Priority Chain: System > .env > Schema defaults
  4. Type Casting: Automatic conversion (str, int, float, bool)
  5. Validation: Required checks + type validation + error collection

Key Components

  • core.py: Main engine that orchestrates the entire process
  • schema_loader.py: Parses YAML/JSON schema files
  • validation.py: Type casting and validation logic
  • integrations/: Framework-specific adapters (FastAPI, Django)
  • cli.py: Command-line interface for common operations

๐Ÿ“Š Comparison with Other Tools

Feature envsmith python-dotenv pydantic-settings dynaconf python-decouple
Schema Validation โœ… YAML/JSON โŒ None โœ… Pydantic models โœ… TOML/YAML โŒ None
Type Casting โœ… Automatic โŒ Strings only โœ… Pydantic types โœ… Basic โŒ Strings only
Framework Integration โœ… FastAPI/Django โŒ None โœ… Pydantic ecosystem โœ… Multiple โŒ None
CLI Tools โœ… Built-in โŒ None โŒ None โœ… Rich CLI โŒ None
Priority System โœ… System > .env > defaults โŒ .env only โœ… Environment > .env โœ… Multiple sources โœ… .env > env
Error Handling โœ… Comprehensive โŒ Basic โœ… Pydantic errors โœ… Good โŒ Basic
Production Ready โœ… Logging, testing โš ๏ธ Basic โœ… Enterprise โœ… Enterprise โš ๏ธ Basic

Why Choose envsmith?

vs python-dotenv

  • python-dotenv: Only loads .env files, no validation, no type casting
  • envsmith: Full validation, type safety, multiple sources, framework integration

vs pydantic-settings

  • pydantic-settings: Requires Pydantic knowledge, more complex setup
  • envsmith: Simple YAML/JSON schemas, easier to understand and maintain

vs dynaconf

  • dynaconf: More complex, multiple config formats, overkill for simple apps
  • envsmith: Focused on environment variables, simple and lightweight

vs python-decouple

  • python-decouple: Basic .env loading, no validation, no type safety
  • envsmith: Full validation suite, type casting, production features

Performance Characteristics

  • Startup Time: Fast - single pass validation
  • Memory Usage: Minimal - only stores validated variables
  • Runtime Overhead: Zero - all processing happens at initialization
  • Error Reporting: Comprehensive - all issues reported at once

Use Cases Where envsmith Excels

โœ… Web Applications: FastAPI, Django, Flask โœ… Microservices: Environment-based configuration โœ… Docker Containers: Environment variable validation โœ… CI/CD Pipelines: Configuration validation โœ… Team Development: Clear schema documentation โœ… Production Deployments: Early error detection

โœจ Features

  • Schema-First: Define your environment structure in YAML/JSON
  • Multiple Sources: Load from .env, system, or custom dicts
  • Type Safety: Automatic type casting and validation
  • Framework Integration: FastAPI and Django support
  • CLI Tools: Command-line interface for common tasks
  • Secrets Management: Mock interface for external secret providers
  • Production Ready: Logging, error handling, and comprehensive testing

๐Ÿ“ฆ Installation

pip install envsmith

With optional extras:

pip install envsmith[fastapi,django]

๐ŸŽฏ Quick Start

1. Create a Schema

Create a schema.yaml file:

DATABASE_URL:
  type: str
  required: true
  description: "Database connection string"

SECRET_KEY:
  type: str
  required: true
  description: "Application secret key"

DEBUG:
  type: bool
  default: false
  description: "Debug mode"

PORT:
  type: int
  default: 8000
  description: "Server port"

API_TIMEOUT:
  type: float
  default: 30.0
  description: "API timeout in seconds"

2. Create Environment File

Create a .env file:

DATABASE_URL=postgresql://user:pass@localhost:5432/mydb
SECRET_KEY=your-super-secret-key-here
DEBUG=true
PORT=8080
API_TIMEOUT=45.0

3. Use in Python

from envsmith import EnvSmith

# Load with schema validation
settings = EnvSmith(schema_path="schema.yaml", env_file=".env")

# Access validated variables
print(settings["DATABASE_URL"])  # postgresql://user:pass@localhost:5432/mydb
print(settings["DEBUG"])         # True (bool)
print(settings["PORT"])          # 8080 (int)
print(settings["API_TIMEOUT"])   # 45.0 (float)

# Get with default fallback
print(settings.get("NONEXISTENT", "default_value"))

๐Ÿ› ๏ธ CLI Usage

Initialize Project

Create .env and schema.yaml files:

python3 -m envsmith init

Validate Environment

Check if your .env file matches the schema:

python3 -m envsmith validate

Export Environment

Export validated variables in different formats:

# Export as JSON
python3 -m envsmith export --format json

# Export as YAML
python3 -m envsmith export --format yaml

๐Ÿ”Œ Framework Integrations

FastAPI Integration

from fastapi import FastAPI, Depends
from envsmith.integrations.fastapi import get_settings

app = FastAPI()

@app.get("/config")
def get_config(settings = Depends(get_settings)):
    return {
        "database_url": settings["DATABASE_URL"],
        "debug": settings["DEBUG"],
        "port": settings["PORT"]
    }

@app.get("/health")
def health_check(settings = Depends(get_settings)):
    return {
        "status": "healthy",
        "environment": settings.get("ENV", "development")
    }

Django Integration

In your settings.py:

from envsmith.integrations.django import load_envsmith

# Load environment variables with schema validation
load_envsmith(schema_path="schema.yaml")

# Now you can use them directly
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': DATABASE_NAME,
        'USER': DATABASE_USER,
        'PASSWORD': DATABASE_PASSWORD,
        'HOST': DATABASE_HOST,
        'PORT': DATABASE_PORT,
    }
}

SECRET_KEY = SECRET_KEY
DEBUG = DEBUG
ALLOWED_HOSTS = ALLOWED_HOSTS.split(',') if ALLOWED_HOSTS else []

๐Ÿ” Secrets Management

For production environments, you can integrate with external secret providers:

from envsmith.secrets import SecretProvider

# Mock interface (replace with actual AWS, Vault, etc.)
secrets = SecretProvider()

# Get secret from external provider
api_key = secrets.get_secret("API_KEY")

# Fallback to local secret
fallback_key = secrets.get_local_secret("API_KEY")

๐Ÿ“‹ Schema Reference

Supported Types

  • str: String values
  • int: Integer values
  • float: Floating-point values
  • bool: Boolean values (accepts: true/false, yes/no, 1/0, on/off)

Schema Structure

VARIABLE_NAME:
  type: str|int|float|bool
  required: true|false
  default: "default_value"
  description: "Human-readable description"

Example Schema

# Database Configuration
DATABASE_URL:
  type: str
  required: true
  description: "PostgreSQL connection string"

DATABASE_POOL_SIZE:
  type: int
  default: 10
  description: "Database connection pool size"

# Application Settings
DEBUG:
  type: bool
  default: false
  description: "Enable debug mode"

LOG_LEVEL:
  type: str
  default: "INFO"
  description: "Logging level"

# API Configuration
API_TIMEOUT:
  type: float
  default: 30.0
  description: "API request timeout in seconds"

MAX_REQUESTS:
  type: int
  default: 1000
  description: "Maximum concurrent requests"

๐Ÿงช Testing

Run the test suite:

# Install test dependencies
pip install pytest pytest-cov

# Run tests with coverage
python3 -m pytest --cov=envsmith

# Run specific test file
python3 -m pytest tests/test_core.py

๐Ÿš€ Development

Project Structure

envsmith/
โ”œโ”€โ”€ envsmith/           # Main package
โ”‚   โ”œโ”€โ”€ __init__.py    # Package initialization
โ”‚   โ”œโ”€โ”€ core.py        # Core loader and validation
โ”‚   โ”œโ”€โ”€ cli.py         # Command-line interface
โ”‚   โ”œโ”€โ”€ validation.py  # Schema validation logic
โ”‚   โ”œโ”€โ”€ schema_loader.py # YAML/JSON schema loading
โ”‚   โ”œโ”€โ”€ secrets.py     # Secrets management
โ”‚   โ”œโ”€โ”€ _types.py      # Type definitions
โ”‚   โ””โ”€โ”€ integrations/  # Framework integrations
โ”‚       โ”œโ”€โ”€ fastapi.py # FastAPI integration
โ”‚       โ””โ”€โ”€ django.py  # Django integration
โ”œโ”€โ”€ tests/             # Test suite
โ”œโ”€โ”€ examples/          # Usage examples
โ””โ”€โ”€ docs/             # Documentation

Adding New Features

  1. Type Support: Add new types in validation.py
  2. Framework Integration: Create new integration modules
  3. CLI Commands: Extend cli.py with new subcommands
  4. Secrets Providers: Implement actual secret provider interfaces

๐Ÿ“ Examples

Check the examples/ directory for complete working examples:

  • demo_fastapi.py - FastAPI application with envsmith
  • demo_django.py - Django settings with envsmith
  • env.example - Example environment file

๐Ÿค Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests for new functionality
  5. Ensure all tests pass
  6. Submit a pull request

Development Setup

# Clone the repository
git clone https://github.com/PeymanSohi/envsmith.git
cd envsmith

# Create virtual environment
python3 -m venv .venv
source .venv/bin/activate  # On Windows: .venv\Scripts\activate

# Install in development mode
pip install -e ".[fastapi,django]"

# Install test dependencies
pip install pytest pytest-cov

# Run tests
python3 -m pytest

๐Ÿ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

๐Ÿ†˜ Support

๐Ÿ”„ Changelog

See CHANGELOG.md for a detailed history of changes and releases.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

envsmith-0.1.0.tar.gz (16.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

envsmith-0.1.0-py3-none-any.whl (12.8 kB view details)

Uploaded Python 3

File details

Details for the file envsmith-0.1.0.tar.gz.

File metadata

  • Download URL: envsmith-0.1.0.tar.gz
  • Upload date:
  • Size: 16.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for envsmith-0.1.0.tar.gz
Algorithm Hash digest
SHA256 7da6d8e50bde173156d4d55e4e83ceb5b3ff4a0f0c5e334021ea4421b7d6f108
MD5 6e0127f9815a66889b4198c6f1b726df
BLAKE2b-256 afdd9f7841e9b8268bc69d82b3d6e4eda5035e827000dc701edb5f28381e0f14

See more details on using hashes here.

File details

Details for the file envsmith-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: envsmith-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 12.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for envsmith-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 817ad2255819c5c27a935f215391df3182c0a11f06185b108da6b20c19452121
MD5 609665f2d46278e7ae5fcfa7aa6c942a
BLAKE2b-256 1588197e895ca84cd632a8df67320cc423d750abde9eb3fafc2d6bbcc93a5c9a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page