Coverage for chalicelib/utils/github_client_v3.py: 49%
80 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 12:56 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 12:56 +0000
1import logging
2from datetime import datetime
4import requests
5from fastapi import HTTPException, status
7logger = logging.getLogger(__name__)
10class github_formatters:
12 @staticmethod
13 def get_timestamp(ts):
14 ts = ts[:-1]
15 pattern = '%Y-%m-%dT%H:%M:%S'
16 creation = datetime.strptime(ts, pattern)
17 return int(creation.timestamp() * 1000)
19 @staticmethod
20 def label(label):
21 return {
22 'id': label["id"],
23 'name': label["name"],
24 'description': label["description"],
25 'color': label["color"]
26 }
28 @staticmethod
29 def comment(comment):
30 return {
31 'id': str(comment["id"]),
32 'message': comment["body"],
33 'author': str(github_formatters.user(comment["user"])["id"]),
34 'createdAt': github_formatters.get_timestamp(comment["created_at"])
35 }
37 @staticmethod
38 def issue(issue):
39 labels = [github_formatters.label(l) for l in issue["labels"]]
40 result = {
41 'id': str(issue["number"]),
42 'creator': str(github_formatters.user(issue["user"])["id"]),
43 'assignees': [str(github_formatters.user(a)["id"]) for a in issue["assignees"]],
44 'title': issue["title"],
45 'description': issue["body"],
46 'status': issue["state"],
47 'createdAt': github_formatters.get_timestamp(issue["created_at"]),
48 'closed': issue["closed_at"] is not None,
49 'commentsCount': issue["comments"],
50 'issueType': [str(l["id"]) for l in labels if l["name"].lower() != "openreplay"],
51 'labels': [l["name"] for l in labels]
52 }
53 return result
55 @staticmethod
56 def user(user):
57 if not user:
58 return None
59 result = {
60 'id': user["id"],
61 'name': user["login"],
62 'avatarUrls': {'24x24': user["avatar_url"]},
63 'email': ""
64 }
65 return result
67 @staticmethod
68 def team_to_dict(team):
69 if not team:
70 return None
72 result = {'id': team.id, 'name': team.name, 'members_count': team.members_count}
73 return result
75 @staticmethod
76 def repo(repo):
77 if not repo:
78 return None
79 return {
80 "id": str(repo["id"]),
81 "name": repo["name"],
82 "description": repo["description"],
83 "creator": str(repo["owner"]["id"])
84 }
86 @staticmethod
87 def organization(org):
88 if not org:
89 return None
90 return {
91 "id": org["id"],
92 "name": org["login"],
93 "description": org["description"],
94 "avatarUrls": {'24x42': org["avatar_url"]}
95 }
98def get_response_links(response):
99 links = {}
100 if "Link" in response.headers: 100 ↛ 101line 100 didn't jump to line 101 because the condition on line 100 was never true
101 link_headers = response.headers["Link"].split(", ")
102 for link_header in link_headers:
103 (url, rel) = link_header.split("; ")
104 url = url[1:-1]
105 rel = rel[5:-1]
106 links[rel] = url
107 return links
110class githubV3Request:
111 __base = "https://api.github.com"
113 def __init__(self, token):
114 self.__token = token
116 def __get_request_header(self):
117 return {"Accept": "application/vnd.github.v3+json", 'Authorization': f'token {self.__token}'}
119 def get(self, url, params={}):
120 results = []
121 params = {"per_page": 100, **params}
122 pages = {"next": f"{self.__base}{url}", "last": ""}
123 while len(pages.keys()) > 0 and pages["next"] != pages["last"]: 123 ↛ 134line 123 didn't jump to line 134 because the condition on line 123 was always true
124 response = requests.get(pages["next"], headers=self.__get_request_header(), params=params)
125 pages = get_response_links(response)
126 result = response.json()
127 if response.status_code != 200: 127 ↛ 131line 127 didn't jump to line 131 because the condition on line 127 was always true
128 logger.warning(f"=>GITHUB Exception")
129 logger.error(result)
130 raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=f"GITHUB: {result['message']}")
131 if isinstance(result, dict):
132 return result
133 results += result
134 return results
136 def post(self, url, body):
137 response = requests.post(f"{self.__base}{url}", headers=self.__get_request_header(), json=body)
138 return response.json()