Skip to content

Commit 39af255

Browse files
committed
Add helper logic for working with GitHub Issues
* downloading * querying * caching
1 parent 6d89f91 commit 39af255

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

github_issues.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#!/usr/bin/env python
2+
#
3+
# This is free and unencumbered software released into the public domain.
4+
# See the UNLICENSE file for details.
5+
#
6+
# ------------------------------------------------------------------------
7+
# github_issues.py
8+
# ------------------------------------------------------------------------
9+
# A class to download and organize issues from GitHub.
10+
11+
import json, logging, math
12+
import requests
13+
14+
class GitHubIssues:
15+
16+
def __init__(self, items=[], max_results=10000, token=None):
17+
self._token = token
18+
self._json = {'items': items}
19+
self._per_page = 100
20+
self._max_results = max_results
21+
22+
def repo(self, org, repo):
23+
return GitHubIssues(self.issues(lambda item: item['repository_url'].endswith(f'/repos/{org}/{repo}')), max_results=self._max_results, token=self._token)
24+
25+
def issues(self, predicate=lambda x: True):
26+
return list(map(predicate, self._json['items']))
27+
28+
def load(self, filepath):
29+
with open(filepath) as f:
30+
result = json.loads(f.read())
31+
self._merge(result)
32+
33+
def save(self, filepath):
34+
with open(filepath, 'w') as f:
35+
return json.dump(self._json, f)
36+
37+
def download(self, query):
38+
"""
39+
Downloads issues from GitHub according to the given query.
40+
"""
41+
42+
url = f"https://api.github.com/search/issues?q={query}+is:open&sort=created&order=asc&per_page={self._per_page}"
43+
url = self._download_page(url)
44+
45+
max_pages = math.ceil(self._max_results / self._per_page)
46+
for i in range(1, max_pages):
47+
if not url: break
48+
url = self._download_page(url)
49+
50+
def _download_page(self, url):
51+
headers = {}
52+
if self._token: headers['Authorization'] = self._token
53+
54+
logging.debug(f'Downloading {url}')
55+
response = requests.get(url, headers)
56+
result = response.json()
57+
58+
self._merge(result)
59+
60+
return response.links['next']['url'] if 'next' in response.links else None
61+
62+
def _merge(self, content):
63+
for key, value in content.items():
64+
if key in self._json and type(self._json[key]) == list:
65+
# Append values to the list.
66+
self._json[key].extend(value)
67+
else:
68+
# Overwrite value in the dict.
69+
self._json[key] = value

0 commit comments

Comments
 (0)