- Create comprehensive tddai package with workspace, issue fetcher, and test generator modules - Add Python CLI interface (tddai_cli.py) to replace complex Makefile shell logic - Update Makefile targets to use Python CLI for better maintainability - Implement proper behavior-based tests instead of file existence checks - Add workspace lifecycle management (create, active, finish, cleanup) - Add issue fetching from Gitea API with error handling - Add comprehensive test coverage with 19 passing tests - Support environment variable configuration for different deployments This addresses issue #11: Setup TDD workspace infrastructure All tests pass and the system achieves green state before commit. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
92 lines
2.5 KiB
Python
92 lines
2.5 KiB
Python
"""
|
|
Configuration management for tddai.
|
|
"""
|
|
|
|
import os
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
from dataclasses import dataclass
|
|
|
|
from .exceptions import ConfigurationError
|
|
|
|
|
|
@dataclass
|
|
class TddaiConfig:
|
|
"""Configuration settings for tddai."""
|
|
|
|
# Workspace settings
|
|
workspace_dir: Path = Path(".markitect_workspace")
|
|
current_issue_file: str = "current_issue.json"
|
|
|
|
# Git repository settings
|
|
gitea_url: str = "http://92.205.130.254:32166"
|
|
repo_owner: str = "coulomb"
|
|
repo_name: str = "markitect_project"
|
|
|
|
# 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."""
|
|
config = cls()
|
|
|
|
# Override with environment variables if present
|
|
if gitea_url := os.getenv("TDDAI_GITEA_URL"):
|
|
config.gitea_url = gitea_url
|
|
|
|
if repo_owner := os.getenv("TDDAI_REPO_OWNER"):
|
|
config.repo_owner = repo_owner
|
|
|
|
if repo_name := os.getenv("TDDAI_REPO_NAME"):
|
|
config.repo_name = repo_name
|
|
|
|
if workspace_dir := os.getenv("TDDAI_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."""
|
|
global _config
|
|
if _config is None:
|
|
_config = TddaiConfig.from_environment()
|
|
_config.validate()
|
|
return _config
|
|
|
|
|
|
def set_config(config: TddaiConfig) -> None:
|
|
"""Set the global configuration instance."""
|
|
global _config
|
|
config.validate()
|
|
_config = config |