ferrero-opentext/Python-Version/scripts/shared/config_loader.py
DJP 9dc272f8bf Start Python automation - Foundation components
Created Python-Version/ directory structure:
 Complete folder hierarchy (scripts, config, logs, temp, tests)
 Virtual environment setup script
 Python 3.6+ compatible dependencies
 Configuration system with env var substitution
 DAM API client (complete)

Components Implemented:
1. setup.sh - venv creation and dependency installation
2. requirements.txt - Python 3.6/3.10 compatible packages
3. config/config.yaml - Main configuration (URLs, credentials, settings)
4. config/field_mappings.yaml - MVP fields list (easy to edit!)
5. config_loader.py - YAML config with ${VAR} substitution
6. dam_client.py - Complete DAM API wrapper:
   - OAuth2 with auto-refresh
   - search_campaigns(status)
   - get_master_assets(campaign_id)
   - download_asset(asset_id)
   - upload_asset() with video metadata
   - update_campaign_status()
   - Helper methods

Features:
- Python 3.6 compatible (shared hosting requirement)
- Python 3.10 compatible (local development)
- Configuration-driven (no hardcoded values)
- Environment-specific configs (staging/production)
- Comprehensive error handling
- Logging built-in

Next: Box client, Database client, FilenameParser, MetadataExtractorMVP,
      Notifier, then main scripts (A1→A2, A2→A3)

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 16:38:26 -04:00

90 lines
2.5 KiB
Python

"""
Configuration Loader - Load YAML config with environment variable substitution
Compatible with Python 3.6+
"""
import os
import re
import yaml
from dotenv import load_dotenv
def load_config(config_path='config/config.yaml'):
"""
Load configuration from YAML file with environment variable substitution
Supports:
- ${VAR_NAME} - Required environment variable
- ${VAR_NAME:-default} - Optional with default value
"""
# Load environment variables from .env file
load_dotenv()
# Read YAML file
with open(config_path, 'r') as f:
config_text = f.read()
# Substitute environment variables
config_text = substitute_env_vars(config_text)
# Parse YAML
config = yaml.safe_load(config_text)
# Load environment-specific overrides if specified
env = config.get('environment', 'staging')
env_config_path = 'config/environments/{}.yaml'.format(env)
if os.path.exists(env_config_path):
with open(env_config_path, 'r') as f:
env_config_text = f.read()
env_config_text = substitute_env_vars(env_config_text)
env_config = yaml.safe_load(env_config_text)
# Merge environment-specific config
config = deep_merge(config, env_config)
return config
def substitute_env_vars(text):
"""
Substitute ${VAR_NAME} and ${VAR_NAME:-default} patterns with environment variables
"""
def replacer(match):
var_expr = match.group(1)
# Check for default value syntax: VAR:-default
if ':-' in var_expr:
var_name, default = var_expr.split(':-', 1)
return os.getenv(var_name, default)
else:
# Required variable
value = os.getenv(var_expr)
if value is None:
raise ValueError("Required environment variable not set: {}".format(var_expr))
return value
# Pattern: ${VAR_NAME} or ${VAR_NAME:-default}
pattern = r'\$\{([^}]+)\}'
return re.sub(pattern, replacer, text)
def deep_merge(base, override):
"""
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] = deep_merge(result[key], value)
else:
result[key] = value
return result
def load_field_mappings(config):
"""
Load field mappings configuration
"""
mappings_file = config['fields']['mappings_file']
with open(mappings_file, 'r') as f:
return yaml.safe_load(f)