import os import json from config_schema import AppConfig from constants import CONFIG_FILE, Color from logger import logger def load_config() -> AppConfig: """ Loads the user's config file and validates using Pydantic. """ user_cfg = {} if os.path.exists(CONFIG_FILE): try: with open(CONFIG_FILE, 'r', encoding='utf-8') as f: user_cfg = json.load(f) except Exception as e: logger.error(f"Failed to read config file, falling back to defaults: {e}") print(f" {Color.YELLOW}⚠ Config file corrupted. Using defaults.{Color.RESET}") constraints_file = os.path.join(os.path.dirname(__file__), 'constraints.json') if os.path.exists(constraints_file): try: with open(constraints_file, 'r', encoding='utf-8') as f: constraints = json.load(f) user_cfg.update(constraints) except Exception as e: logger.error(f"Failed to read constraints.json: {e}") validation_failed = False try: app_cfg = AppConfig(**{k:v for k,v in user_cfg.items() if not k.startswith('_')}) except Exception as e: logger.error(f"Config Validation Error: {e}") print(f" {Color.YELLOW}⚠ Config validation failed: {e}{Color.RESET}") print(f" {Color.YELLOW}⚠ Using safe defaults. The original config was not overwritten.{Color.RESET}") app_cfg = AppConfig() validation_failed = True # Restore internal variables (starting with _) for key, value in user_cfg.items(): if key.startswith('_'): setattr(app_cfg, key, value) _sector_map = {} for category, tickers in app_cfg.universe_categories.items(): for t in tickers: _sector_map[t] = category.split(' ')[0].replace('&', '').replace('/', '') app_cfg.sector_map = _sector_map if not validation_failed: save_config(app_cfg) return app_cfg def save_config(cfg: AppConfig) -> None: """Saves the active configuration dictionary to disk.""" try: with open(CONFIG_FILE, 'w', encoding='utf-8') as f: cfg_dict = cfg.model_dump() for key, val in cfg.__dict__.items(): if key not in cfg_dict: cfg_dict[key] = val json.dump({k: v for k, v in cfg_dict.items() if not k.startswith('_')}, f, indent=4) except Exception as e: logger.error(f"Could not save config to {CONFIG_FILE}: {e}")