""" Configuration management for tddai. DEPRECATED: This module is kept for backward compatibility only. New code should use the unified configuration system in the `config` module. The tddai framework is project-agnostic and can be configured per project via environment variables: - TDDAI_WORKSPACE_DIR: Workspace directory name (default: .tddai_workspace) - TDDAI_GITEA_URL: Git platform URL - TDDAI_REPO_OWNER: Repository owner/organization - TDDAI_REPO_NAME: Repository name Example .env file for a project: ``` TDDAI_WORKSPACE_DIR=.myproject_workspace TDDAI_GITEA_URL=https://github.com TDDAI_REPO_OWNER=myusername TDDAI_REPO_NAME=myproject ``` """ import os from pathlib import Path from typing import Optional from dataclasses import dataclass from .exceptions import ConfigurationError # Import unified configuration system try: from config import get_tddai_config as _get_unified_tddai_config _UNIFIED_CONFIG_AVAILABLE = True except ImportError: _UNIFIED_CONFIG_AVAILABLE = False def load_dotenv_file(env_file: Path) -> None: """Load environment variables from a .env file. DEPRECATED: Use config.loaders.load_env_file() instead. """ if not env_file.exists(): return with open(env_file, 'r') as f: for line in f: line = line.strip() if line and not line.startswith('#') and '=' in line: key, value = line.split('=', 1) os.environ.setdefault(key.strip(), value.strip()) @dataclass class TddaiConfig: """Configuration settings for tddai. DEPRECATED: Use config.TddaiConfigCompat instead. """ # Workspace settings workspace_dir: Path = Path(".tddai_workspace") current_issue_file: str = "current_issue.json" # Git repository settings (must be configured per project) gitea_url: str = "" repo_owner: str = "" repo_name: str = "" # Test settings tests_dir: Path = Path("tests") test_file_pattern: str = "test_issue_{issue_num}_{scenario}.py" # AI settings claude_code_command: str = "claude" @property def issues_api_url(self) -> str: """Get the full issues API URL.""" return f"{self.gitea_url}/api/v1/repos/{self.repo_owner}/{self.repo_name}/issues" @property def current_issue_path(self) -> Path: """Get the path to current issue file.""" return self.workspace_dir / self.current_issue_file @classmethod def from_environment(cls) -> "TddaiConfig": """Create config from environment variables and .env files.""" # Auto-load .env.tddai file if it exists env_file = Path(".env.tddai") load_dotenv_file(env_file) config = cls() # Override with environment variables if present gitea_url = os.getenv("TDDAI_GITEA_URL") if gitea_url: config.gitea_url = gitea_url repo_owner = os.getenv("TDDAI_REPO_OWNER") if repo_owner: config.repo_owner = repo_owner repo_name = os.getenv("TDDAI_REPO_NAME") if repo_name: config.repo_name = repo_name workspace_dir = os.getenv("TDDAI_WORKSPACE_DIR") if workspace_dir: config.workspace_dir = Path(workspace_dir) return config def validate(self) -> None: """Validate configuration settings.""" if not self.gitea_url: raise ConfigurationError("gitea_url cannot be empty") if not self.repo_owner: raise ConfigurationError("repo_owner cannot be empty") if not self.repo_name: raise ConfigurationError("repo_name cannot be empty") # Global config instance _config: Optional[TddaiConfig] = None def get_config() -> TddaiConfig: """Get the global configuration instance. DEPRECATED: Use config.get_tddai_config() instead for new code. This function maintains backward compatibility. """ global _config if _config is None: if _UNIFIED_CONFIG_AVAILABLE: # Use unified configuration system if available try: unified_config = _get_unified_tddai_config() _config = TddaiConfig( workspace_dir=unified_config.workspace_dir, gitea_url=unified_config.gitea_url, repo_owner=unified_config.repo_owner, repo_name=unified_config.repo_name, tests_dir=unified_config.tests_dir, test_file_pattern=unified_config.test_file_pattern, claude_code_command=unified_config.claude_code_command ) return _config except Exception: # Fall back to legacy behavior if unified config fails pass # Legacy fallback _config = TddaiConfig.from_environment() _config.validate() return _config def set_config(config: TddaiConfig) -> None: """Set the global configuration instance. DEPRECATED: Use the unified configuration system instead. """ global _config config.validate() _config = config