- Create new gitea/ package with clean API facade - Establish proper separation of concerns: tddai uses gitea, not vice versa - Replace duplicate curl+subprocess patterns with unified HTTP client - Add rich domain models with properties (issue.priority, issue.status) - Maintain full backwards compatibility in tddai modules - Reduce code complexity: -373 lines, +151 lines (net -222 lines) - Improve testability and maintainability through clean interfaces Architecture: - gitea.client.GiteaClient - main facade with sub-clients - gitea.api_client - high-level API with model conversion - gitea.http_client - low-level HTTP operations - gitea.models - rich domain objects (Issue, Milestone, Label) - gitea.config - gitea-specific configuration - gitea.exceptions - clean exception hierarchy 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
64 lines
2.3 KiB
Python
64 lines
2.3 KiB
Python
"""
|
|
Issue fetching using the Gitea facade.
|
|
|
|
This module now acts as an adapter to the new gitea package,
|
|
maintaining backwards compatibility while using the cleaner API.
|
|
"""
|
|
|
|
from typing import List, Dict, Any
|
|
|
|
from gitea import GiteaClient, Issue as GiteaIssue, GiteaConfig
|
|
from .config import get_config
|
|
from .exceptions import IssueError
|
|
|
|
# Re-export Issue for backwards compatibility
|
|
Issue = GiteaIssue
|
|
|
|
|
|
class IssueFetcher:
|
|
"""Fetches issues using the Gitea facade."""
|
|
|
|
def __init__(self, config=None):
|
|
self.config = config or get_config()
|
|
|
|
# Create Gitea client from tddai config
|
|
gitea_config = GiteaConfig.from_tddai_config(self.config)
|
|
self.gitea_client = GiteaClient(gitea_config)
|
|
|
|
def fetch_issue(self, issue_number: int) -> Issue:
|
|
"""Fetch a specific issue by number."""
|
|
try:
|
|
return self.gitea_client.issues.get(issue_number)
|
|
except Exception as e:
|
|
# Convert gitea exceptions to IssueError for backwards compatibility
|
|
raise IssueError(f"Failed to fetch issue #{issue_number}: {e}")
|
|
|
|
def fetch_issues(self, state: str = "all") -> List[Issue]:
|
|
"""Fetch all issues with optional state filter."""
|
|
try:
|
|
return self.gitea_client.issues.list(state=state)
|
|
except Exception as e:
|
|
# Convert gitea exceptions to IssueError for backwards compatibility
|
|
raise IssueError(f"Failed to fetch issues: {e}")
|
|
|
|
def fetch_open_issues(self) -> List[Issue]:
|
|
"""Fetch only open issues."""
|
|
try:
|
|
return self.gitea_client.issues.list_open()
|
|
except Exception as e:
|
|
raise IssueError(f"Failed to fetch open issues: {e}")
|
|
|
|
def get_issue_data_dict(self, issue_number: int) -> Dict[str, Any]:
|
|
"""Get issue data as dictionary for workspace creation."""
|
|
issue = self.fetch_issue(issue_number)
|
|
return {
|
|
'number': issue.number,
|
|
'title': issue.title,
|
|
'body': issue.body,
|
|
'state': issue.state,
|
|
'created_at': issue.created_at.isoformat(),
|
|
'updated_at': issue.updated_at.isoformat(),
|
|
'html_url': issue.html_url,
|
|
'assignee': {'login': issue.assignee.login} if issue.assignee else None,
|
|
'labels': [{'name': label.name} for label in issue.labels]
|
|
} |