Source code for src.config.loader
"""Configuration loader with validation."""
import os
from pathlib import Path
from typing import Optional
import yaml
from dotenv import load_dotenv
from .schema import Config
from ..utils.errors import InvalidConfigError, MissingAPIKeyError
from ..utils.logging import get_logger
logger = get_logger(__name__)
[docs]
class ConfigLoader:
"""Load and validate configuration from YAML file."""
def __init__(self, config_path: Optional[Path] = None):
"""
Initialize configuration loader.
Args:
config_path: Path to config.yaml file. Defaults to ./config.yaml
"""
self.config_path = config_path or Path("config.yaml")
[docs]
def load(self) -> Config:
"""
Load and validate configuration.
Returns:
Validated Config object
Raises:
InvalidConfigError: If configuration is invalid
MissingAPIKeyError: If required API key not found
"""
# Load environment variables
load_dotenv()
# Check if config file exists
if not self.config_path.exists():
raise InvalidConfigError(
f"Configuration file not found: {self.config_path}\n"
f"Please create a config.yaml file. See examples/ for templates."
)
# Load YAML
try:
with open(self.config_path, 'r', encoding='utf-8') as f:
config_data = yaml.safe_load(f)
except yaml.YAMLError as e:
raise InvalidConfigError(f"Invalid YAML syntax: {e}")
except Exception as e:
raise InvalidConfigError(f"Failed to load config file: {e}")
# Validate with Pydantic
try:
config = Config(**config_data)
except Exception as e:
raise InvalidConfigError(f"Configuration validation failed: {e}")
# Validate API key
self._validate_api_key(config)
logger.info(f"Configuration loaded: {config.project.name}")
logger.debug(f"Loaded {len(config.queries)} queries for analysis")
return config
def _validate_api_key(self, config: Config) -> None:
"""
Validate that required API key is available.
Args:
config: Configuration object
Raises:
MissingAPIKeyError: If API key not found in environment
"""
api_key_env = config.data_source.api_key_env
api_key = os.getenv(api_key_env)
if not api_key:
raise MissingAPIKeyError(
f"API key not found in environment variable: {api_key_env}\n"
f"Please set this variable in your .env file or environment.\n"
f"Example: export {api_key_env}='your_key_here'"
)
logger.debug(f"API key validated from {api_key_env}")
[docs]
def load_config(config_path: Optional[Path] = None) -> Config:
"""
Convenience function to load configuration.
Args:
config_path: Path to config.yaml file
Returns:
Validated Config object
"""
loader = ConfigLoader(config_path)
return loader.load()