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()