Skip to content

Commit 2afc3de

Browse files
authored
Add files via upload
1 parent beea051 commit 2afc3de

File tree

2 files changed

+374
-282
lines changed

2 files changed

+374
-282
lines changed

interface_wrapper.py

Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
1+
from abc import ABC, abstractmethod
2+
from datetime import datetime
3+
from typing import List, Dict, Optional
4+
import logging
5+
6+
# Настройка логирования
7+
logging.basicConfig(
8+
level=logging.INFO,
9+
format="%(asctime)s - %(levelname)s - %(message)s"
10+
)
11+
12+
# Модельные классы
13+
class Repository:
14+
def __init__(self, id: str, name: str, url: str):
15+
self.id = id
16+
self.name = name
17+
self.url = url
18+
19+
def __repr__(self):
20+
return f"Repository(id={self.id}, name={self.name}, url={self.url})"
21+
22+
class Commit:
23+
def __init__(self, id: str, message: str, author: 'Contributor', date: datetime):
24+
self.id = id
25+
self.message = message
26+
self.author = author
27+
self.date = date
28+
29+
def __repr__(self):
30+
return f"Commit(id={self.id}, message={self.message}, author={self.author}, date={self.date})"
31+
32+
class Contributor:
33+
def __init__(self, username: str, email: str):
34+
self.username = username
35+
self.email = email
36+
37+
def __repr__(self):
38+
return f"Contributor(username={self.username}, email={self.email})"
39+
40+
class Issue:
41+
def __init__(self, id: str, title: str, author: Contributor, state: str):
42+
self.id = id
43+
self.title = title
44+
self.author = author
45+
self.state = state
46+
47+
def __repr__(self):
48+
return f"Issue(id={self.id}, title={self.title}, author={self.author}, state={self.state})"
49+
50+
class PullRequest:
51+
def __init__(self, id: str, title: str, author: Contributor, state: str):
52+
self.id = id
53+
self.title = title
54+
self.author = author
55+
self.state = state
56+
57+
def __repr__(self):
58+
return f"PullRequest(id={self.id}, title={self.title}, author={self.author}, state={self.state})"
59+
60+
class WikiPage:
61+
def __init__(self, title: str, content: str):
62+
self.title = title
63+
self.content = content
64+
65+
def __repr__(self):
66+
return f"WikiPage(title={self.title}, content={self.content[:50]}...)" # Ограничиваем вывод content для удобства
67+
68+
# Интерфейс API
69+
class IRepositoryAPI(ABC):
70+
@abstractmethod
71+
def get_repository(self, id: str) -> Optional[Repository]:
72+
"""Получить репозиторий по его идентификатору."""
73+
pass
74+
75+
@abstractmethod
76+
def get_commits(self, repo: Repository) -> List[Commit]:
77+
"""Получить список коммитов для репозитория."""
78+
pass
79+
80+
@abstractmethod
81+
def get_contributors(self, repo: Repository) -> List[Contributor]:
82+
"""Получить список контрибьюторов для репозитория."""
83+
pass
84+
85+
@abstractmethod
86+
def get_issues(self, repo: Repository) -> List[Issue]:
87+
"""Получить список issues для репозитория."""
88+
pass
89+
90+
@abstractmethod
91+
def get_pull_requests(self, repo: Repository) -> List[PullRequest]:
92+
"""Получить список pull requests для репозитория."""
93+
pass
94+
95+
@abstractmethod
96+
def get_wiki_pages(self, repo: Repository) -> List[WikiPage]:
97+
"""Получить список wiki-страниц для репозитория."""
98+
pass
99+
100+
# Реализация для GitHub
101+
class GitHubRepoAPI(IRepositoryAPI):
102+
def __init__(self, client):
103+
self.client = client
104+
105+
def get_repository(self, id: str) -> Optional[Repository]:
106+
try:
107+
repo = self.client.get_repo(id)
108+
return Repository(repo.full_name, repo.name, repo.html_url)
109+
except Exception as e:
110+
logging.error(f"Failed to get repository {id} from GitHub: {e}")
111+
return None
112+
113+
def get_commits(self, repo: Repository) -> List[Commit]:
114+
try:
115+
commits = self.client.get_repo(repo.id).get_commits()
116+
return [
117+
Commit(
118+
c.sha,
119+
c.commit.message,
120+
Contributor(c.author.login if c.author else "unknown", c.commit.author.email),
121+
c.commit.author.date
122+
) for c in commits
123+
]
124+
except Exception as e:
125+
logging.error(f"Failed to get commits from GitHub for repo {repo.name}: {e}")
126+
return []
127+
128+
def get_contributors(self, repo: Repository) -> List[Contributor]:
129+
try:
130+
contributors = self.client.get_repo(repo.id).get_contributors()
131+
return [Contributor(c.login, c.email or "") for c in contributors]
132+
except Exception as e:
133+
logging.error(f"Failed to get contributors from GitHub for repo {repo.name}: {e}")
134+
return []
135+
136+
def get_issues(self, repo: Repository) -> List[Issue]:
137+
try:
138+
issues = self.client.get_repo(repo.id).get_issues(state='all')
139+
return [
140+
Issue(
141+
i.number,
142+
i.title,
143+
Contributor(i.user.login, i.user.email or ""),
144+
i.state
145+
) for i in issues
146+
]
147+
except Exception as e:
148+
logging.error(f"Failed to get issues from GitHub for repo {repo.name}: {e}")
149+
return []
150+
151+
def get_pull_requests(self, repo: Repository) -> List[PullRequest]:
152+
try:
153+
pulls = self.client.get_repo(repo.id).get_pulls(state='all')
154+
return [
155+
PullRequest(
156+
p.number,
157+
p.title,
158+
Contributor(p.user.login, p.user.email or ""),
159+
p.state
160+
) for p in pulls
161+
]
162+
except Exception as e:
163+
logging.error(f"Failed to get pull requests from GitHub for repo {repo.name}: {e}")
164+
return []
165+
166+
def get_wiki_pages(self, repo: Repository) -> List[WikiPage]:
167+
# GitHub API не поддерживает прямое получение wiki-страниц
168+
return []
169+
170+
# Реализация для Forgejo
171+
class ForgejoRepoAPI(IRepositoryAPI):
172+
def __init__(self, client):
173+
self.client = client
174+
175+
def get_repository(self, id: str) -> Optional[Repository]:
176+
try:
177+
owner, repo_name = id.split('/')
178+
repo = self.client.repo_get(owner, repo_name)
179+
return Repository(repo['id'], repo['name'], repo['html_url'])
180+
except Exception as e:
181+
logging.error(f"Failed to get repository {id} from Forgejo: {e}")
182+
return None
183+
184+
def get_commits(self, repo: Repository) -> List[Commit]:
185+
try:
186+
owner, repo_name = repo.id.split('/')
187+
commits = self.client.repo_list_commits(owner, repo_name)
188+
return [
189+
Commit(
190+
c['sha'],
191+
c['message'],
192+
Contributor(c['author']['username'], c['author']['email']),
193+
datetime.fromisoformat(c['date'])
194+
) for c in commits
195+
]
196+
except Exception as e:
197+
logging.error(f"Failed to get commits from Forgejo for repo {repo.name}: {e}")
198+
return []
199+
200+
def get_contributors(self, repo: Repository) -> List[Contributor]:
201+
try:
202+
owner, repo_name = repo.id.split('/')
203+
contributors = self.client.repo_list_contributors(owner, repo_name)
204+
return [Contributor(c['username'], c['email']) for c in contributors]
205+
except Exception as e:
206+
logging.error(f"Failed to get contributors from Forgejo for repo {repo.name}: {e}")
207+
return []
208+
209+
def get_issues(self, repo: Repository) -> List[Issue]:
210+
try:
211+
owner, repo_name = repo.id.split('/')
212+
issues = self.client.repo_list_issues(owner, repo_name)
213+
return [
214+
Issue(
215+
i['number'],
216+
i['title'],
217+
Contributor(i['user']['username'], i['user']['email']),
218+
i['state']
219+
) for i in issues
220+
]
221+
except Exception as e:
222+
logging.error(f"Failed to get issues from Forgejo for repo {repo.name}: {e}")
223+
return []
224+
225+
def get_pull_requests(self, repo: Repository) -> List[PullRequest]:
226+
try:
227+
owner, repo_name = repo.id.split('/')
228+
pulls = self.client.repo_list_pull_requests(owner, repo_name)
229+
return [
230+
PullRequest(
231+
p['number'],
232+
p['title'],
233+
Contributor(p['user']['username'], p['user']['email']),
234+
p['state']
235+
) for p in pulls
236+
]
237+
except Exception as e:
238+
logging.error(f"Failed to get pull requests from Forgejo for repo {repo.name}: {e}")
239+
return []
240+
241+
def get_wiki_pages(self, repo: Repository) -> List[WikiPage]:
242+
try:
243+
owner, repo_name = repo.id.split('/')
244+
wiki_pages = self.client.repo_list_wiki_pages(owner, repo_name)
245+
return [WikiPage(page['title'], page['content']) for page in wiki_pages]
246+
except Exception as e:
247+
logging.error(f"Failed to get wiki pages from Forgejo for repo {repo.name}: {e}")
248+
return []
249+
250+
# Фабрика для создания API
251+
class RepositoryFactory:
252+
@staticmethod
253+
def create_api(source: str, client) -> IRepositoryAPI:
254+
if client is None:
255+
raise ValueError("Client cannot be None")
256+
if source == 'github':
257+
return GitHubRepoAPI(client)
258+
elif source == 'forgejo':
259+
return ForgejoRepoAPI(client)
260+
else:
261+
raise ValueError(f"Unsupported source: {source}")
262+
263+
# Сервис для расчёта метрик
264+
class CommitmentCalculator:
265+
def __init__(self, api: IRepositoryAPI):
266+
self.api = api
267+
268+
def calculate(self, repo: Repository) -> Dict[str, int]:
269+
if not repo:
270+
return {}
271+
try:
272+
commits = self.api.get_commits(repo)
273+
if not commits:
274+
return {}
275+
result = {}
276+
for commit in commits:
277+
author = commit.author.username
278+
result[author] = result.get(author, 0) + 1
279+
return result
280+
except Exception as e:
281+
logging.error(f"Failed to calculate commitment for repo {repo.name}: {e}")
282+
return {}

0 commit comments

Comments
 (0)