feat: implement tddai Python library for TDD workspace management
- 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>
This commit is contained in:
92
tddai/config.py
Normal file
92
tddai/config.py
Normal file
@@ -0,0 +1,92 @@
|
||||
"""
|
||||
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
|
||||
Reference in New Issue
Block a user