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:
- AWS Account ID in .env: The
AWS_ACCOUNT_IDmust be set in your.envfile (mandatory) - AWS Credentials: Configure AWS credentials (via AWS CLI, IAM roles, or environment variables)
- 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 retrievercreate_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 retrievesource: 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
- Always use .env files: Store all environment variables in a
.envfile in your project root (mandatory) - Load .env at startup: Use
python-dotenvto load your.envfile before using env_factory - AWS Account ID: Always include
AWS_ACCOUNT_IDin your.envfile when using AWS functionality - Environment-Specific Sources: Use local environment variables for development and AWS Secrets Manager for production
- Error Handling: Always handle
ConfigurationErrorandSecretRetrievalErrorexceptions - Key Validation: Check if required environment variables are present and not None
- Security: Never commit your
.envfile to version control (add it to.gitignore)
.gitignore Example
# .gitignore
.env
.env.local
.env.production
*.env
Contributing
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass
- 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
Metadata
Release files for env-factory 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| env_factory-1.1.0.tar.gz | 11.8 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| env_factory-1.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 20.4 kB
Release files / env_factory-1.1.0.tar.gz
| Download URL | env_factory-1.1.0.tar.gz |
|---|---|
| Size | 11.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e74c065ab2cc8cb35f02e3f26f8c5ed09d4cd810e2a9d4e87dc434bd428c1fff
|
|
BLAKE2b-256 checksum How to use checksums |
6f0dd5bac83a93061834aaea01a55757dcf84e3ac046eb3c934f391b2a165dc9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.5
|
Release files / env_factory-1.1.0-py3-none-any.whl
| Download URL | env_factory-1.1.0-py3-none-any.whl |
|---|---|
| Size | 8.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
90937e4d1b9997650fb07345f66d78fadc1aa7295e98cb4e808ded36744ddaa5
|
|
BLAKE2b-256 checksum How to use checksums |
800c809486ed6d1d1f277e3e65ce772e94a5f8882af4a184c1681f5a99a56d30
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.5
|
Security for env-factory 1.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.