Multi-Environment Setup
Environment-Specific Configuration
from yapfm import YAPFileManager
import os
from typing import Dict, Any
class EnvironmentConfig:
def __init__(self, base_config: str = "config.json"):
self.environment = os.getenv("ENVIRONMENT", "development")
self.config_file = f"config_{self.environment}.json"
self.fm = YAPFileManager(self.config_file, auto_create=True)
def load(self) -> Dict[str, Any]:
"""Load environment-specific configuration."""
with self.fm:
# Set environment
self.fm.set_key(self.environment, dot_key="environment")
# Set environment-specific defaults
if self.environment == "development":
self._set_development_defaults()
elif self.environment == "staging":
self._set_staging_defaults()
elif self.environment == "production":
self._set_production_defaults()
return self.fm.data
def _set_development_defaults(self) -> None:
"""Set development environment defaults."""
defaults = {
"debug": True,
"database.host": "localhost",
"database.port": 5432,
"database.ssl": False,
"api.timeout": 60,
"api.debug": True,
"logging.level": "DEBUG",
"logging.console": True,
"cors.origins": ["http://localhost:3000", "http://localhost:8080"]
}
for key, value in defaults.items():
if not self.fm.has_key(dot_key=key):
self.fm.set_key(value, dot_key=key)
def _set_staging_defaults(self) -> None:
"""Set staging environment defaults."""
defaults = {
"debug": False,
"database.host": "staging-db.example.com",
"database.port": 5432,
"database.ssl": True,
"api.timeout": 30,
"api.debug": False,
"logging.level": "INFO",
"logging.console": False,
"cors.origins": ["https://staging.demo.example.com"]
}
for key, value in defaults.items():
if not self.fm.has_key(dot_key=key):
self.fm.set_key(value, dot_key=key)
def _set_production_defaults(self) -> None:
"""Set production environment defaults."""
defaults = {
"debug": False,
"database.host": "prod-db.example.com",
"database.port": 3306,
"database.ssl": True,
"api.timeout": 15,
"api.debug": False,
"logging.level": "WARNING",
"logging.console": False,
"cors.origins": ["https://demo.example.com"]
}
for key, value in defaults.items():
if not self.fm.has_key(dot_key=key):
self.fm.set_key(value, dot_key=key)
def get_database_url(self) -> str:
"""Get database URL for current environment."""
host = self.fm.get_key(dot_key="database.host")
port = self.fm.get_key(dot_key="database.port")
name = self.fm.get_key(dot_key="database.name", default="myapp")
ssl = self.fm.get_key(dot_key="database.ssl", default=False)
protocol = "postgresql+ssl" if ssl else "postgresql"
return f"{protocol}://{host}:{port}/{name}"
def get_api_config(self) -> Dict[str, Any]:
"""Get API configuration for current environment."""
return {
"version": self.fm.get_key(dot_key="api.version", default="v1"),
"timeout": self.fm.get_key(dot_key="api.timeout", default=30),
"debug": self.fm.get_key(dot_key="api.debug", default=False),
"cors": {
"origins": self.fm.get_key(dot_key="cors.origins", default=[])
}
}
# Usage example
def main():
# Set environment (usually done via environment variable)
os.environ["ENVIRONMENT"] = "development"
config = EnvironmentConfig()
config.load()
print(f"Environment: {config.environment}")
print(f"Database URL: {config.get_database_url()}")
print(f"API Config: {config.get_api_config()}")
if __name__ == "__main__":
main()
Configuration Inheritance
from yapfm import YAPFileManager
from typing import Dict, Any, Optional
class ConfigInheritance:
def __init__(self, base_config: str = "base_config.json"):
self.base_config = base_config
self.environment = os.getenv("ENVIRONMENT", "development")
self.env_config = f"config_{self.environment}.json"
def load_merged_config(self) -> Dict[str, Any]:
"""Load and merge base and environment-specific configuration."""
# Load base configuration
base_fm = YAPFileManager(self.base_config, auto_create=True)
with base_fm:
base_data = base_fm.data.copy()
# Load environment-specific configuration
env_fm = YAPFileManager(self.env_config, auto_create=True)
with env_fm:
env_data = env_fm.data
# Merge configurations (environment overrides base)
merged_config = self._deep_merge(base_data, env_data)
# Save merged configuration
merged_fm = YAPFileManager("merged_config.json", auto_create=True)
with merged_fm:
merged_fm.data = merged_config
return merged_config
def _deep_merge(self, base: Dict[str, Any], override: Dict[str, Any]) -> Dict[str, Any]:
"""Deep merge two dictionaries."""
result = base.copy()
for key, value in override.items():
if key in result and isinstance(result[key], dict) and isinstance(value, dict):
result[key] = self._deep_merge(result[key], value)
else:
result[key] = value
return result
# Usage example
def main():
config_manager = ConfigInheritance()
merged_config = config_manager.load_merged_config()
print("Merged Configuration:")
print(f"Environment: {merged_config.get('environment')}")
print(f"Database: {merged_config.get('database', {}).get('host')}")
print(f"API: {merged_config.get('api', {}).get('timeout')}")
if __name__ == "__main__":
main()