refactor: extract focused clients from GiteaClient (Slices 1-6)

- Create gitea/issues_client.py with IssuesClient class (9 methods)
- Create gitea/prs_client.py with PullRequestsClient class (17 methods)
- Create gitea/files_client.py with FilesClient class (4 methods)
- Create gitea/notifications_client.py with NotificationsClient class (2 methods)
- Create gitea/repos_client.py with ReposClient class (2 methods)
- Create gitea/__init__.py to export all client classes
- Remove delegation methods from GiteaClient (now ~70 lines)
- Update all callers to use sub-clients (client.issues, client.prs, etc.)
- Update test files to mock sub-client attributes

GiteaClient is now a facade that provides access to focused sub-clients:
- repos: Repository operations (ReposClient)
- issues: Issue operations (IssuesClient)
- prs: Pull request operations (PullRequestsClient)
- files: File and git ref operations (FilesClient)
- notifications: Notification operations (NotificationsClient)

Refs: #godclass-refactor
This commit is contained in:
meeks
2026-07-17 07:31:05 +02:00
parent 3c94c3cfac
commit e91780169e
21 changed files with 1480 additions and 728 deletions
+10 -6
View File
@@ -50,7 +50,7 @@ class FileTools:
limit: Maximum number of lines to return (default 250).
"""
try:
content = self._client.get_file_content(owner, repo, path)
content = self._client.files.get_file_content(owner, repo, path)
raw: str = "\n".join(content) if isinstance(content, list) else content
return self._paginate_lines(raw, offset, limit)
except Exception as e:
@@ -73,22 +73,26 @@ class FileTools:
limit: Maximum number of lines to return (default 250).
"""
try:
content = self._client.get_file_content(owner, repo, path, ref)
content = self._client.files.get_file_content(owner, repo, path, ref)
raw: str = "\n".join(content) if isinstance(content, list) else content
return self._paginate_lines(raw, offset, limit)
except Exception as e:
return f"Error getting file content: {str(e)}"
def commit_file(self, owner: str, repo: str, path: str, message: str, content: str, branch: str) -> str:
def commit_file(
self, owner: str, repo: str, path: str, message: str, content: str, branch: str
) -> str:
try:
self._client.update_file(owner, repo, path, message, content, branch)
self._client.files.update_file(owner, repo, path, message, content, branch)
return f"File '{path}' committed successfully to {owner}/{repo}."
except Exception as e:
return f"Error committing file: {str(e)}"
def update_file(self, owner: str, repo: str, path: str, message: str, content: str, branch: str) -> str:
def update_file(
self, owner: str, repo: str, path: str, message: str, content: str, branch: str
) -> str:
try:
self._client.update_file(owner, repo, path, message, content, branch)
self._client.files.update_file(owner, repo, path, message, content, branch)
return f"File '{path}' updated in {owner}/{repo}."
except Exception as e:
return f"Error updating file: {str(e)}"
+1 -1
View File
@@ -10,7 +10,7 @@ class GitTools:
def create_branch(self, owner: str, repo: str, ref: str, sha: str) -> str:
try:
self._client.create_ref(owner, repo, ref, sha)
self._client.files.create_ref(owner, repo, ref, sha)
return f"Branch '{ref}' created successfully in {owner}/{repo}."
except Exception as e:
return f"Error creating branch: {str(e)}"
+9 -9
View File
@@ -17,14 +17,14 @@ class IssueTools:
def get_issue(self, owner: str, repo: str, issue_number: int) -> str:
try:
issue: IssueModel = self._client.get_issue(owner, repo, issue_number)
issue: IssueModel = self._client.issues.get_issue(owner, repo, issue_number)
return issue.model_dump_json(indent=2)
except Exception as e:
return f"Error getting issue: {str(e)}"
def close_issue(self, owner: str, repo: str, issue_number: int) -> str:
try:
self._client.close_issue(owner, repo, issue_number)
self._client.issues.close_issue(owner, repo, issue_number)
return f"Issue #{issue_number} closed successfully."
except Exception as e:
return f"Error closing issue: {str(e)}"
@@ -44,7 +44,7 @@ class IssueTools:
offset: Zero-based comment index to start from (default 0).
"""
try:
comments: list[CommentModel] = self._client.get_issue_comments(
comments: list[CommentModel] = self._client.issues.get_issue_comments(
owner, repo, issue_number
)
total: int = len(comments)
@@ -62,12 +62,12 @@ class IssueTools:
def list_assigned_issues(self) -> list[dict[str, Any]]:
try:
repos = self._client.list_all_user_repos()
repos = self._client.repos.list_all_user_repos()
all_issues: list[dict[str, Any]] = []
for repo in repos:
owner = repo.owner
repo_name = repo.name
issues = self._client.list_assigned_issues(owner, repo_name)
issues = self._client.issues.list_assigned_issues(owner, repo_name)
if issues:
all_issues.extend(
[
@@ -84,7 +84,7 @@ class IssueTools:
def list_issues(self, owner: str, repo: str, state: str = "open") -> str:
try:
issues = self._client.list_repo_issues(owner, repo, state)
issues = self._client.issues.list_repo_issues(owner, repo, state)
if not issues:
return f"No issues in {owner}/{repo}."
summary = [f"#{issue.number}: {issue.title}" for issue in issues]
@@ -102,7 +102,7 @@ class IssueTools:
assignees: list[str] | None = None,
) -> str:
try:
issue = self._client.create_issue(
issue = self._client.issues.create_issue(
owner, repo, title, body, labels, assignees
)
return f"Issue #{issue.number} created successfully in {owner}/{repo}."
@@ -113,7 +113,7 @@ class IssueTools:
self, owner: str, repo: str, issue_number: int, label: str
) -> str:
try:
self._client.add_label(owner, repo, issue_number, label)
self._client.issues.add_label(owner, repo, issue_number, label)
return f"Label '{label}' added to issue #{issue_number}."
except Exception as e:
return f"Error adding label to issue #{issue_number}: {e}"
@@ -122,7 +122,7 @@ class IssueTools:
self, owner: str, repo: str, issue_number: int, body: str
) -> str:
try:
self._client.add_comment(owner, repo, issue_number, body)
self._client.issues.add_comment(owner, repo, issue_number, body)
return f"Comment added to issue #{issue_number}."
except Exception as e:
return f"Error adding comment to issue #{issue_number}: {e}"
+44 -17
View File
@@ -42,14 +42,16 @@ class PRTools:
def get_pull_request(self, owner: str, repo: str, pull_number: int) -> str:
try:
pr: PullRequestModel = self._client.get_pull_request(owner, repo, pull_number)
pr: PullRequestModel = self._client.prs.get_pull_request(
owner, repo, pull_number
)
return pr.model_dump_json(indent=2)
except Exception as e:
return f"Error getting pull request: {str(e)}"
def close_pull_request(self, owner: str, repo: str, pull_number: int) -> str:
try:
self._client.close_pull_request(owner, repo, pull_number)
self._client.prs.close_pull_request(owner, repo, pull_number)
return f"Pull request #{pull_number} closed successfully."
except Exception as e:
return f"Error closing pull request: {str(e)}"
@@ -69,7 +71,7 @@ class PRTools:
offset: Zero-based comment index to start from (default 0).
"""
try:
comments: list[CommentModel] = self._client.get_pull_request_comments(
comments: list[CommentModel] = self._client.prs.get_pull_request_comments(
owner, repo, pull_number
)
total: int = len(comments)
@@ -87,14 +89,21 @@ class PRTools:
def list_assigned_pull_requests(self) -> list[dict[str, Any]]:
try:
repos = self._client.list_all_user_repos()
repos = self._client.repos.list_all_user_repos()
all_prs: list[dict[str, Any]] = []
for repo_info in repos:
repo_owner = repo_info.owner
repo_name = repo_info.name
prs = self._client.list_assigned_pull_requests(repo_owner, repo_name)
prs = self._client.prs.list_assigned_pull_requests(
repo_owner, repo_name
)
if prs:
all_prs.extend([pr.model_dump() if hasattr(pr, 'model_dump') else pr for pr in prs])
all_prs.extend(
[
pr.model_dump() if hasattr(pr, "model_dump") else pr
for pr in prs
]
)
return all_prs
except Exception as e:
logger.error(f"Error listing assigned pull requests: {e}", exc_info=True)
@@ -102,7 +111,7 @@ class PRTools:
def list_pull_requests(self, owner: str, repo: str, state: str = "open") -> str:
try:
prs = self._client.list_repo_pull_requests(owner, repo, state)
prs = self._client.prs.list_repo_pull_requests(owner, repo, state)
if not prs:
return f"No PRs in {owner}/{repo}."
summary = [f"#{pr.number}: {pr.title}" for pr in prs]
@@ -110,9 +119,19 @@ class PRTools:
except Exception as e:
return f"Error listing PRs: {str(e)}"
def create_pull_request(self, owner: str, repo: str, head: str, base: str, title: str, description: str = "") -> str:
def create_pull_request(
self,
owner: str,
repo: str,
head: str,
base: str,
title: str,
description: str = "",
) -> str:
try:
pr = self._client.create_pr_via_tea(owner, repo, title, description, head, base)
pr = self._client.prs.create_pr_via_tea(
owner, repo, title, description, head, base
)
return pr.model_dump_json(indent=2)
except Exception as e:
return f"Error creating PR: {str(e)}"
@@ -127,14 +146,16 @@ class PRTools:
state: str | None = None,
) -> str:
try:
pr = self._client.update_pull_request(owner, repo, pull_number, title, body, state)
pr = self._client.prs.update_pull_request(
owner, repo, pull_number, title, body, state
)
return pr.model_dump_json(indent=2)
except Exception as e:
return f"Error updating PR #{pull_number}: {str(e)}"
def add_label_to_pr(self, owner: str, repo: str, pr_number: int, label: str) -> str:
try:
self._client.add_label_pr(owner, repo, pr_number, label)
self._client.prs.add_label_pr(owner, repo, pr_number, label)
return f"Label '{label}' added to PR #{pr_number}."
except Exception as e:
return f"Error adding label to PR #{pr_number}: {e}"
@@ -155,7 +176,7 @@ class PRTools:
Increment by max_chars to page through a large diff.
"""
try:
diff: str = self._client.get_pull_request_diff(owner, repo, pull_number)
diff: str = self._client.prs.get_pull_request_diff(owner, repo, pull_number)
return _truncate_diff(diff, max_chars, char_offset)
except Exception as e:
return f"Error getting PR diff: {str(e)}"
@@ -176,21 +197,27 @@ class PRTools:
Increment by max_chars to page through a large patch.
"""
try:
patch: str = self._client.get_pull_request_patch(owner, repo, pull_number)
patch: str = self._client.prs.get_pull_request_patch(
owner, repo, pull_number
)
return _truncate_diff(patch, max_chars, char_offset)
except Exception as e:
return f"Error getting PR patch: {str(e)}"
def approve_pull_request(self, owner: str, repo: str, pull_number: int, comment: str) -> str:
def approve_pull_request(
self, owner: str, repo: str, pull_number: int, comment: str
) -> str:
try:
self._client.approve_pr(owner, repo, pull_number, comment)
self._client.prs.approve_pr(owner, repo, pull_number, comment)
return f"Approved PR #{pull_number}."
except Exception as e:
return f"Error approving PR: {str(e)}"
def request_changes(self, owner: str, repo: str, pull_number: int, comment: str) -> str:
def request_changes(
self, owner: str, repo: str, pull_number: int, comment: str
) -> str:
try:
self._client.request_changes_pr(owner, repo, pull_number, comment)
self._client.prs.request_changes_pr(owner, repo, pull_number, comment)
return f"Requested changes on PR #{pull_number}."
except Exception as e:
return f"Error requesting changes: {str(e)}"