CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-environs

Simplified environment variable parsing with type casting, validation, and framework integration

Pending
Overview
Eval results
Files

framework-integration.mddocs/

Framework Integration

Specialized parsers for Django framework integration including database URLs, email configuration, and cache settings with automatic dependency management and comprehensive configuration support.

Capabilities

Django Database URL Parsing

Parse Django-compatible database URLs into configuration dictionaries using the dj-database-url library.

def dj_db_url(self, name: str, default=..., **kwargs):
    """
    Parse environment variable as Django database URL.
    
    Parameters:
    - name: str, environment variable name
    - default: any, default value if variable not set (optional)
    - **kwargs: additional arguments passed to dj_database_url.parse()
    
    Returns:
    dj_database_url.DBConfig: Database configuration object
    
    Raises:
    RuntimeError: If dj-database-url package is not installed
    EnvValidationError: If URL is not a valid database URL
    
    Dependencies:
    Requires 'dj-database-url' package: pip install dj-database-url
    """

Usage examples:

import os
from environs import env

# PostgreSQL database URL
os.environ["DATABASE_URL"] = "postgres://user:password@localhost:5432/mydb"
db_config = env.dj_db_url("DATABASE_URL")

print(f"Engine: {db_config['ENGINE']}")     # => 'django.db.backends.postgresql'
print(f"Name: {db_config['NAME']}")         # => 'mydb'
print(f"User: {db_config['USER']}")         # => 'user'
print(f"Password: {db_config['PASSWORD']}")  # => 'password'
print(f"Host: {db_config['HOST']}")         # => 'localhost'
print(f"Port: {db_config['PORT']}")         # => 5432

# MySQL database URL
os.environ["MYSQL_URL"] = "mysql://root:secret@db.example.com:3306/production"
mysql_config = env.dj_db_url("MYSQL_URL")

# SQLite database URL
os.environ["SQLITE_URL"] = "sqlite:///path/to/database.db"
sqlite_config = env.dj_db_url("SQLITE_URL")

# Database URL with additional options
os.environ["DB_URL"] = "postgres://user:pass@host:5432/db?conn_max_age=600&autocommit=true"
db_config = env.dj_db_url("DB_URL")
print(f"Options: {db_config.get('OPTIONS', {})}")

# Use in Django settings.py
DATABASES = {
    'default': env.dj_db_url("DATABASE_URL")
}

# With default value
default_db = env.dj_db_url("DATABASE_URL", "sqlite:///default.db")

# Multiple databases
os.environ["PRIMARY_DB"] = "postgres://user:pass@primary:5432/main"
os.environ["ANALYTICS_DB"] = "postgres://user:pass@analytics:5432/analytics"

DATABASES = {
    'default': env.dj_db_url("PRIMARY_DB"),
    'analytics': env.dj_db_url("ANALYTICS_DB")
}

Django Email URL Parsing

Parse Django-compatible email URLs into email backend configurations using the dj-email-url library.

def dj_email_url(self, name: str, default=..., **kwargs):
    """
    Parse environment variable as Django email URL.
    
    Parameters:
    - name: str, environment variable name
    - default: any, default value if variable not set (optional)
    - **kwargs: additional arguments passed to dj_email_url.parse()
    
    Returns:
    dict: Email backend configuration dictionary
    
    Raises:
    RuntimeError: If dj-email-url package is not installed
    EnvValidationError: If URL is not a valid email URL
    
    Dependencies:
    Requires 'dj-email-url' package: pip install dj-email-url
    """

Usage examples:

import os
from environs import env

# SMTP email configuration
os.environ["EMAIL_URL"] = "smtp://user:password@smtp.gmail.com:587?tls=true"
email_config = env.dj_email_url("EMAIL_URL")

print(f"Backend: {email_config['EMAIL_BACKEND']}")       # Email backend class
print(f"Host: {email_config['EMAIL_HOST']}")             # => 'smtp.gmail.com'
print(f"Port: {email_config['EMAIL_PORT']}")             # => 587
print(f"User: {email_config['EMAIL_HOST_USER']}")        # => 'user'
print(f"Password: {email_config['EMAIL_HOST_PASSWORD']}")# => 'password'
print(f"Use TLS: {email_config['EMAIL_USE_TLS']}")       # => True

# Console backend for development
os.environ["DEV_EMAIL_URL"] = "console:"
dev_email_config = env.dj_email_url("DEV_EMAIL_URL")

# File backend
os.environ["FILE_EMAIL_URL"] = "file:///tmp/emails"
file_email_config = env.dj_email_url("FILE_EMAIL_URL")

# SendGrid configuration
os.environ["SENDGRID_URL"] = "smtp://apikey:SG.xyz123@smtp.sendgrid.net:587?tls=true"
sendgrid_config = env.dj_email_url("SENDGRID_URL")

# Mailgun configuration
os.environ["MAILGUN_URL"] = "smtp://postmaster@mg.example.com:key123@smtp.mailgun.org:587?tls=true"
mailgun_config = env.dj_email_url("MAILGUN_URL")

# Use in Django settings.py
email_config = env.dj_email_url("EMAIL_URL", "console:")

EMAIL_BACKEND = email_config['EMAIL_BACKEND']
EMAIL_HOST = email_config.get('EMAIL_HOST', '')
EMAIL_PORT = email_config.get('EMAIL_PORT', 25)
EMAIL_HOST_USER = email_config.get('EMAIL_HOST_USER', '')
EMAIL_HOST_PASSWORD = email_config.get('EMAIL_HOST_PASSWORD', '')
EMAIL_USE_TLS = email_config.get('EMAIL_USE_TLS', False)
EMAIL_USE_SSL = email_config.get('EMAIL_USE_SSL', False)

# Simplified Django settings integration
locals().update(env.dj_email_url("EMAIL_URL", "console:"))

Django Cache URL Parsing

Parse Django-compatible cache URLs into cache backend configurations using the django-cache-url library.

def dj_cache_url(self, name: str, default=..., **kwargs):
    """
    Parse environment variable as Django cache URL.
    
    Parameters:
    - name: str, environment variable name
    - default: any, default value if variable not set (optional)
    - **kwargs: additional arguments passed to django_cache_url.parse()
    
    Returns:
    dict: Cache backend configuration dictionary
    
    Raises:
    RuntimeError: If django-cache-url package is not installed
    EnvValidationError: If URL is not a valid cache URL or backend is unknown
    
    Dependencies:
    Requires 'django-cache-url' package: pip install django-cache-url
    """

Usage examples:

import os
from environs import env

# Redis cache configuration
os.environ["CACHE_URL"] = "redis://localhost:6379/1?client_class=django_redis.client.DefaultClient"
cache_config = env.dj_cache_url("CACHE_URL")

print(f"Backend: {cache_config['BACKEND']}")           # Redis backend class
print(f"Location: {cache_config['LOCATION']}")         # => 'redis://localhost:6379/1'
print(f"Options: {cache_config.get('OPTIONS', {})}")   # Client options

# Memcached configuration
os.environ["MEMCACHE_URL"] = "memcache://127.0.0.1:11211"
memcache_config = env.dj_cache_url("MEMCACHE_URL")

# Database cache backend
os.environ["DB_CACHE_URL"] = "db://cache_table"
db_cache_config = env.dj_cache_url("DB_CACHE_URL")

# File-based cache
os.environ["FILE_CACHE_URL"] = "file:///tmp/django_cache"
file_cache_config = env.dj_cache_url("FILE_CACHE_URL")

# Dummy cache for development
os.environ["DUMMY_CACHE_URL"] = "dummy:"
dummy_cache_config = env.dj_cache_url("DUMMY_CACHE_URL")

# Local memory cache
os.environ["LOCMEM_CACHE_URL"] = "locmem:unique-snowflake"
locmem_config = env.dj_cache_url("LOCMEM_CACHE_URL")

# Redis with additional options
os.environ["REDIS_CACHE_URL"] = "redis://redis.example.com:6379/0?client_class=django_redis.client.DefaultClient&connection_pool_kwargs={'max_connections':50}"
redis_config = env.dj_cache_url("REDIS_CACHE_URL")

# Use in Django settings.py
CACHES = {
    'default': env.dj_cache_url("CACHE_URL", "locmem:")
}

# Multiple cache configurations
os.environ["DEFAULT_CACHE"] = "redis://localhost:6379/0"
os.environ["SESSION_CACHE"] = "redis://localhost:6379/1"
os.environ["TEMPLATE_CACHE"] = "memcache://localhost:11211"

CACHES = {
    'default': env.dj_cache_url("DEFAULT_CACHE"),
    'sessions': env.dj_cache_url("SESSION_CACHE"),
    'templates': env.dj_cache_url("TEMPLATE_CACHE", "dummy:")
}

# Cache with timeout and versioning
os.environ["CACHE_WITH_OPTIONS"] = "redis://localhost:6379/0?timeout=300&version=2"
cache_with_options = env.dj_cache_url("CACHE_WITH_OPTIONS")

Complete Django Settings Example

Here's how to use all Django integration parsers together in a typical Django settings.py file:

# settings.py
import os
from environs import env

# Initialize environs
env.read_env()  # Load .env file

# Database configuration
DATABASES = {
    'default': env.dj_db_url("DATABASE_URL", "sqlite:///db.sqlite3")
}

# Cache configuration  
CACHES = {
    'default': env.dj_cache_url("CACHE_URL", "locmem:")
}

# Email configuration
email_config = env.dj_email_url("EMAIL_URL", "console:")
EMAIL_BACKEND = email_config['EMAIL_BACKEND']
EMAIL_HOST = email_config.get('EMAIL_HOST', '')
EMAIL_PORT = email_config.get('EMAIL_PORT', 25)
EMAIL_HOST_USER = email_config.get('EMAIL_HOST_USER', '')
EMAIL_HOST_PASSWORD = email_config.get('EMAIL_HOST_PASSWORD', '')
EMAIL_USE_TLS = email_config.get('EMAIL_USE_TLS', False)
EMAIL_USE_SSL = email_config.get('EMAIL_USE_SSL', False)

# Other environment-based settings
DEBUG = env.bool("DEBUG", False)
SECRET_KEY = env.str("SECRET_KEY")
ALLOWED_HOSTS = env.list("ALLOWED_HOSTS", ["localhost", "127.0.0.1"])

# Static and media files
STATIC_URL = env.str("STATIC_URL", "/static/")
STATIC_ROOT = env.path("STATIC_ROOT", None)
MEDIA_URL = env.str("MEDIA_URL", "/media/")
MEDIA_ROOT = env.path("MEDIA_ROOT", None)

# Logging
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
            'level': env.log_level("LOG_LEVEL", "INFO"),
        },
    },
    'root': {
        'handlers': ['console'],
        'level': env.log_level("ROOT_LOG_LEVEL", "INFO"),
    },
}

Environment File Example

Corresponding .env file for the Django settings:

# .env file
DEBUG=true
SECRET_KEY=your-secret-key-here
ALLOWED_HOSTS=localhost,127.0.0.1,yoursite.com

# Database
DATABASE_URL=postgres://user:password@localhost:5432/myproject

# Cache
CACHE_URL=redis://localhost:6379/0

# Email
EMAIL_URL=smtp://username:password@smtp.gmail.com:587?tls=true

# Logging
LOG_LEVEL=DEBUG
ROOT_LOG_LEVEL=INFO

# Static files
STATIC_URL=/static/
STATIC_ROOT=/var/www/static/
MEDIA_URL=/media/
MEDIA_ROOT=/var/www/media/

Error Handling

Handle missing dependencies and invalid configurations appropriately:

from environs import env, EnvValidationError
import os

# Handle missing dj-database-url
try:
    db_config = env.dj_db_url("DATABASE_URL")
except RuntimeError as e:
    print(f"Missing dependency: {e}")
    # Fallback to manual configuration or default
    db_config = {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'db.sqlite3'
    }

# Handle invalid URLs
os.environ["INVALID_DB_URL"] = "not-a-valid-url"
try:
    db_config = env.dj_db_url("INVALID_DB_URL")
except EnvValidationError as e:
    print(f"Invalid database URL: {e}")
    # Use default configuration
    db_config = env.dj_db_url("DATABASE_URL", "sqlite:///default.db")

Types

from typing import Dict, Any, Optional

try:
    from dj_database_url import DBConfig
except ImportError:
    DBConfig = Dict[str, Any]

EmailConfig = Dict[str, Any]
CacheConfig = Dict[str, Any]

Install with Tessl CLI

npx tessl i tessl/pypi-environs

docs

advanced-data.md

configuration.md

core-parsing.md

custom-parsers.md

file-secrets.md

framework-integration.md

index.md

specialized-types.md

validation.md

tile.json