Skip to main content

A flexible Python package for retrieving environment variables from multiple sources including local environment and AWS Secrets Manager

Project description

env_factory

A flexible Python package for retrieving environment variables from multiple sources including local environment and AWS Secrets Manager.

Features

  • Multiple Sources: Support for local environment variables and AWS Secrets Manager
  • Type Safety: Full type hints and robust error handling
  • Flexible Usage: Factory pattern and convenience functions for easy integration
  • Case-Insensitive Matching: Fallback to case-insensitive key matching for AWS secrets
  • Comprehensive Logging: Debug and warning logs for troubleshooting
  • Error Recovery: Continues processing even if some keys are missing

Installation

pip install env-factory

Loading .env files

To automatically load your .env file, add this to the top of your main script:

from dotenv import load_dotenv
load_dotenv()  # This loads variables from .env file

# Now you can use env_factory
from env_factory import get_env_variables

Quick Start

Step 1: Create your .env file (MANDATORY)

Create a .env file in your project root directory:

# .env file - Place in your project root
API_KEY=my-secret-api-key
DATABASE_URL=postgresql://localhost:5432/myapp
DEBUG=true

# For AWS functionality (REQUIRED)
AWS_ACCOUNT_ID=123456789012

Step 2: Simple Examples

Example 1: Get Local Environment Variables

from env_factory import get_env_variables

# This will read from your .env file
config = get_env_variables(['API_KEY', 'DATABASE_URL'])
print(config)
# Output: {'API_KEY': 'my-secret-api-key', 'DATABASE_URL': 'postgresql://localhost:5432/myapp'}

# Check if variables exist
api_key = config.get('API_KEY')
if api_key:
    print(f"API Key found: {api_key}")
else:
    print("API Key not found!")

Example 2: Simple AWS Secrets Manager Usage

from env_factory import get_env_variables

# Make sure AWS_ACCOUNT_ID is in your .env file!
secrets = get_env_variables(
    keys=['DB_PASSWORD', 'JWT_SECRET'],
    source='aws',
    secret_name='my-app-secrets',
    region='us-east-1',
    role_name='my-app-role'
)

print(f"Database password: {secrets.get('DB_PASSWORD')}")

Example 3: Real-World Web App Setup

from env_factory import get_env_variables

# Load all your app configuration at startup
app_config = get_env_variables([
    'API_KEY',
    'DATABASE_URL',
    'DEBUG',
    'PORT'
])

# Use the configuration
api_key = app_config['API_KEY']
database_url = app_config['DATABASE_URL']
debug_mode = app_config.get('DEBUG', 'false').lower() == 'true'
port = int(app_config.get('PORT', '8000'))

print(f"Starting app on port {port}, debug mode: {debug_mode}")

Simple Examples

Complete Working Example

Here's a complete example showing how to use the package:

# main.py
from dotenv import load_dotenv
from env_factory import get_env_variables

# Step 1: Load .env file (MANDATORY)
load_dotenv()

# Step 2: Get your environment variables
config = get_env_variables(['API_KEY', 'DATABASE_URL', 'DEBUG'])

# Step 3: Use the configuration
api_key = config.get('API_KEY')
if not api_key:
    raise ValueError("API_KEY is required but not found in .env file")

database_url = config.get('DATABASE_URL', 'sqlite:///default.db')
debug = config.get('DEBUG', 'false').lower() == 'true'

print(f"API Key: {api_key}")
print(f"Database: {database_url}")
print(f"Debug mode: {debug}")

Your .env file should look like:

# .env
API_KEY=sk-1234567890abcdef
DATABASE_URL=postgresql://user:pass@localhost/mydb
DEBUG=true

AWS Example with .env

# aws_example.py
from dotenv import load_dotenv
from env_factory import get_env_variables

# Load .env file (contains AWS_ACCOUNT_ID)
load_dotenv()

try:
    # Get secrets from AWS
    secrets = get_env_variables(
        keys=['DB_PASSWORD', 'JWT_SECRET'],
        source='aws',
        secret_name='production-secrets',
        region='us-east-1',
        role_name='app-secrets-role'
    )
    
    print("✅ Successfully retrieved AWS secrets!")
    print(f"DB Password exists: {'DB_PASSWORD' in secrets}")
    
except Exception as e:
    print(f"❌ Error: {e}")

Your .env file must include:

# .env - MANDATORY for AWS
AWS_ACCOUNT_ID=123456789012

Error Handling Example

from dotenv import load_dotenv
from env_factory import get_env_variables, ConfigurationError

load_dotenv()

try:
    config = get_env_variables(['REQUIRED_API_KEY'])
    
    api_key = config.get('REQUIRED_API_KEY')
    if not api_key:
        print("⚠️  Warning: REQUIRED_API_KEY not found in .env file")
        print("Please add it to your .env file: REQUIRED_API_KEY=your-key-here")
    else:
        print("✅ API key loaded successfully!")
        
except ConfigurationError as e:
    print(f"❌ Configuration error: {e}")
``` with Classes

```python
from env_factory import LocalEnvRetrieval, AWSEnvRetrieval

# Local environment retrieval
local_retriever = LocalEnvRetrieval()
local_vars = local_retriever.get_env_variables(['API_KEY', 'DEBUG_MODE'])

# AWS Secrets Manager retrieval
aws_retriever = AWSEnvRetrieval(
    secret_name='production-secrets',
    region='us-west-2',
    role_name='app-secrets-role'
)
aws_vars = aws_retriever.get_env_variables(['DB_PASSWORD', 'JWT_SECRET'])

Using Factory Pattern

from env_factory import EnvFactory

# Create retrievers using factory
local_retriever = EnvFactory.create_local_retriever()
aws_retriever = EnvFactory.create_aws_retriever(
    secret_name='my-secrets',
    region='eu-west-1', 
    role_name='secrets-access-role'
)

# Use the retrievers
config = local_retriever.get_env_variables(['PORT', 'HOST'])
secrets = aws_retriever.get_env_variables(['API_TOKEN', 'WEBHOOK_SECRET'])

Configuration

Environment Variables Setup (.env file)

IMPORTANT: You must store your environment variables in a .env file in your project root. This is mandatory for the package to work properly.

For Local Development

Create a .env file in your project root:

# .env file
API_KEY=your-local-api-key
DATABASE_URL=postgresql://localhost:5432/mydb
DEBUG=true
PORT=8000

For AWS Secrets Manager

MANDATORY: Your .env file must include the AWS Account ID:

# .env file - REQUIRED for AWS functionality
AWS_ACCOUNT_ID=123456789012
ENVIRONMENT=production

Additional AWS Requirements

Before using AWS functionality, ensure you have:

  1. AWS Account ID in .env: The AWS_ACCOUNT_ID must be set in your .env file (mandatory)
  2. AWS Credentials: Configure AWS credentials (via AWS CLI, IAM roles, or environment variables)
  3. IAM Permissions: Ensure your IAM role has access to the specified secrets

Required IAM permissions:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "secretsmanager:GetSecretValue",
                "sts:AssumeRole"
            ],
            "Resource": "*"
        }
    ]
}

Advanced Usage

Error Handling

from env_factory import get_env_variables, ConfigurationError, SecretRetrievalError

try:
    variables = get_env_variables(
        keys=['API_KEY', 'SECRET_TOKEN'],
        source='aws',
        secret_name='app-secrets',
        region='us-east-1',
        role_name='secrets-role'
    )
except ConfigurationError as e:
    print(f"Configuration error: {e}")
except SecretRetrievalError as e:
    print(f"Failed to retrieve secrets: {e}")

Custom Implementation

from env_factory import EnvRetrieval
from typing import Dict, List, Optional

class CustomEnvRetrieval(EnvRetrieval):
    """Custom environment retrieval implementation"""
    
    def __init__(self, config_file: str):
        self.config_file = config_file
    
    def get_env_variables(self, keys: List[str]) -> Dict[str, Optional[str]]:
        # Your custom implementation here
        pass

Logging Configuration

import logging

# Configure logging to see debug information
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger('env_factory')

# Now you'll see debug logs when retrieving variables
variables = get_env_variables(['API_KEY'], source='local')

API Reference

Classes

EnvRetrieval (Abstract Base Class)

Base class for all environment retrieval implementations.

Methods:

  • get_env_variables(keys: List[str]) -> Dict[str, Optional[str]]: Abstract method to retrieve environment variables

LocalEnvRetrieval

Retrieves environment variables from the local system environment.

Methods:

  • get_env_variables(keys: List[str]) -> Dict[str, Optional[str]]: Get variables from local environment

AWSEnvRetrieval

Retrieves environment variables from AWS Secrets Manager.

Constructor:

  • __init__(secret_name: str, region: str, role_name: str)

Methods:

  • get_env_variables(keys: List[str]) -> Dict[str, Optional[str]]: Get variables from AWS Secrets Manager

EnvFactory

Factory class for creating environment retrieval instances.

Static Methods:

  • create_local_retriever() -> LocalEnvRetrieval: Create local retriever
  • create_aws_retriever(secret_name: str, region: str, role_name: str) -> AWSEnvRetrieval: Create AWS retriever

Functions

get_env_variables()

Convenience function for retrieving environment variables.

Parameters:

  • keys: List[str] - List of environment variable names to retrieve
  • source: str = "local" - Environment source ('local' or 'aws')
  • **kwargs - Additional arguments for AWS (secret_name, region, role_name)

Returns:

  • Dict[str, Optional[str]] - Dictionary mapping keys to their values

Exceptions

EnvFactoryError

Base exception for the env_factory package.

ConfigurationError

Raised when configuration parameters are invalid.

SecretRetrievalError

Raised when secret retrieval from AWS fails.

Examples

Web Application Configuration

from env_factory import get_env_variables

# Load configuration for a web application
config = get_env_variables([
    'DATABASE_URL',
    'SECRET_KEY',
    'DEBUG',
    'PORT',
    'REDIS_URL'
])

# Handle missing variables
database_url = config.get('DATABASE_URL')
if not database_url:
    raise ValueError("DATABASE_URL is required")

debug_mode = config.get('DEBUG', 'false').lower() == 'true'
port = int(config.get('PORT', '8000'))

Multi-Environment Setup

import os
from env_factory import get_env_variables

# Determine environment
environment = os.getenv('ENVIRONMENT', 'development')

if environment == 'production':
    # Use AWS Secrets Manager in production
    config = get_env_variables(
        keys=['DATABASE_PASSWORD', 'API_KEY', 'JWT_SECRET'],
        source='aws',
        secret_name='prod-app-secrets',
        region='us-east-1',
        role_name='prod-secrets-role'
    )
else:
    # Use local environment variables in development
    config = get_env_variables([
        'DATABASE_PASSWORD',
        'API_KEY', 
        'JWT_SECRET'
    ])

print(f"Loaded {len([v for v in config.values() if v is not None])} variables")

Batch Processing with Multiple Sources

from env_factory import EnvFactory

# Create retrievers
local_retriever = EnvFactory.create_local_retriever()
aws_retriever = EnvFactory.create_aws_retriever(
    secret_name='shared-secrets',
    region='us-west-2',
    role_name='batch-processing-role'
)

# Get different types of configuration
app_config = local_retriever.get_env_variables([
    'LOG_LEVEL',
    'BATCH_SIZE', 
    'WORKER_COUNT'
])

sensitive_config = aws_retriever.get_env_variables([
    'DATABASE_PASSWORD',
    'API_TOKEN',
    'ENCRYPTION_KEY'
])

# Merge configurations
full_config = {**app_config, **sensitive_config}

Best Practices

  1. Always use .env files: Store all environment variables in a .env file in your project root (mandatory)
  2. Load .env at startup: Use python-dotenv to load your .env file before using env_factory
  3. AWS Account ID: Always include AWS_ACCOUNT_ID in your .env file when using AWS functionality
  4. Environment-Specific Sources: Use local environment variables for development and AWS Secrets Manager for production
  5. Error Handling: Always handle ConfigurationError and SecretRetrievalError exceptions
  6. Key Validation: Check if required environment variables are present and not None
  7. Security: Never commit your .env file to version control (add it to .gitignore)

.gitignore Example

# .gitignore
.env
.env.local
.env.production
*.env

Contributing

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

License

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

Changelog

v1.0.0

  • Initial release
  • Support for local environment variables
  • Support for AWS Secrets Manager
  • Factory pattern implementation
  • Comprehensive error handling
  • Type hints and documentation

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

env_factory-1.1.0.tar.gz (11.8 kB view details)

Uploaded Source

Built Distribution

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

env_factory-1.1.0-py3-none-any.whl (8.6 kB view details)

Uploaded Python 3

File details

Details for the file env_factory-1.1.0.tar.gz.

File metadata

  • Download URL: env_factory-1.1.0.tar.gz
  • Upload date:
  • Size: 11.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.5

File hashes

Hashes for env_factory-1.1.0.tar.gz
Algorithm Hash digest
SHA256 e74c065ab2cc8cb35f02e3f26f8c5ed09d4cd810e2a9d4e87dc434bd428c1fff
MD5 c5946aeeed2b2d9476722c686b441519
BLAKE2b-256 6f0dd5bac83a93061834aaea01a55757dcf84e3ac046eb3c934f391b2a165dc9

See more details on using hashes here.

File details

Details for the file env_factory-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: env_factory-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 8.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.5

File hashes

Hashes for env_factory-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 90937e4d1b9997650fb07345f66d78fadc1aa7295e98cb4e808ded36744ddaa5
MD5 50d86c9bbd0146a522338959d5fd9570
BLAKE2b-256 800c809486ed6d1d1f277e3e65ce772e94a5f8882af4a184c1681f5a99a56d30

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