##// END OF EJS Templates
Fix a typo
Andrew Kreimer -
Show More
@@ -1,141 +1,141
1 """Functions for Github API requests."""
1 """Functions for Github API requests."""
2
2
3 try:
3 try:
4 input = raw_input
4 input = raw_input
5 except NameError:
5 except NameError:
6 pass
6 pass
7
7
8 import re
8 import re
9 import sys
9 import sys
10
10
11 import requests
11 import requests
12 import getpass
12 import getpass
13 import json
13 import json
14
14
15 try:
15 try:
16 import requests_cache
16 import requests_cache
17 except ImportError:
17 except ImportError:
18 print("cache not available, install `requests_cache` for caching.", file=sys.stderr)
18 print("cache not available, install `requests_cache` for caching.", file=sys.stderr)
19 else:
19 else:
20 requests_cache.install_cache("gh_api", expire_after=3600)
20 requests_cache.install_cache("gh_api", expire_after=3600)
21
21
22 # Keyring stores passwords by a 'username', but we're not storing a username and
22 # Keyring stores passwords by a 'username', but we're not storing a username and
23 # password
23 # password
24 import socket
24 import socket
25 fake_username = 'ipython_tools_%s' % socket.gethostname().replace('.','_').replace('-','_')
25 fake_username = 'ipython_tools_%s' % socket.gethostname().replace('.','_').replace('-','_')
26
26
27 class Obj(dict):
27 class Obj(dict):
28 """Dictionary with attribute access to names."""
28 """Dictionary with attribute access to names."""
29 def __getattr__(self, name):
29 def __getattr__(self, name):
30 try:
30 try:
31 return self[name]
31 return self[name]
32 except KeyError as e:
32 except KeyError as e:
33 raise AttributeError(name) from e
33 raise AttributeError(name) from e
34
34
35 def __setattr__(self, name, val):
35 def __setattr__(self, name, val):
36 self[name] = val
36 self[name] = val
37
37
38 token = None
38 token = None
39 def get_auth_token():
39 def get_auth_token():
40 global token
40 global token
41
41
42 if token is not None:
42 if token is not None:
43 return token
43 return token
44
44
45 import keyring
45 import keyring
46 token = keyring.get_password('github', fake_username)
46 token = keyring.get_password('github', fake_username)
47 if token is not None:
47 if token is not None:
48 return token
48 return token
49
49
50 print(
50 print(
51 "Get a token fom https://github.com/settings/tokens with public repo and gist."
51 "Get a token from https://github.com/settings/tokens with public repo and gist."
52 )
52 )
53 token = getpass.getpass("Token: ", stream=sys.stderr)
53 token = getpass.getpass("Token: ", stream=sys.stderr)
54
54
55 keyring.set_password('github', fake_username, token)
55 keyring.set_password('github', fake_username, token)
56 return token
56 return token
57
57
58 def make_auth_header():
58 def make_auth_header():
59 return {'Authorization': 'token ' + get_auth_token()}
59 return {'Authorization': 'token ' + get_auth_token()}
60
60
61
61
62 def get_pull_request(project, num, auth=False):
62 def get_pull_request(project, num, auth=False):
63 """get pull request info by number
63 """get pull request info by number
64 """
64 """
65 url = "https://api.github.com/repos/{project}/pulls/{num}".format(project=project, num=num)
65 url = "https://api.github.com/repos/{project}/pulls/{num}".format(project=project, num=num)
66 if auth:
66 if auth:
67 header = make_auth_header()
67 header = make_auth_header()
68 else:
68 else:
69 header = None
69 header = None
70 print("fetching %s" % url, file=sys.stderr)
70 print("fetching %s" % url, file=sys.stderr)
71 response = requests.get(url, headers=header)
71 response = requests.get(url, headers=header)
72 response.raise_for_status()
72 response.raise_for_status()
73 return json.loads(response.text, object_hook=Obj)
73 return json.loads(response.text, object_hook=Obj)
74
74
75 element_pat = re.compile(r'<(.+?)>')
75 element_pat = re.compile(r'<(.+?)>')
76 rel_pat = re.compile(r'rel=[\'"](\w+)[\'"]')
76 rel_pat = re.compile(r'rel=[\'"](\w+)[\'"]')
77
77
78 def get_paged_request(url, headers=None, **params):
78 def get_paged_request(url, headers=None, **params):
79 """get a full list, handling APIv3's paging"""
79 """get a full list, handling APIv3's paging"""
80 results = []
80 results = []
81 params.setdefault("per_page", 100)
81 params.setdefault("per_page", 100)
82 while True:
82 while True:
83 if '?' in url:
83 if '?' in url:
84 params = None
84 params = None
85 print("fetching %s" % url, file=sys.stderr)
85 print("fetching %s" % url, file=sys.stderr)
86 else:
86 else:
87 print("fetching %s with %s" % (url, params), file=sys.stderr)
87 print("fetching %s with %s" % (url, params), file=sys.stderr)
88 response = requests.get(url, headers=headers, params=params)
88 response = requests.get(url, headers=headers, params=params)
89 response.raise_for_status()
89 response.raise_for_status()
90 results.extend(response.json())
90 results.extend(response.json())
91 if 'next' in response.links:
91 if 'next' in response.links:
92 url = response.links['next']['url']
92 url = response.links['next']['url']
93 else:
93 else:
94 break
94 break
95 return results
95 return results
96
96
97 def get_issues_list(project, auth=False, **params):
97 def get_issues_list(project, auth=False, **params):
98 """get issues list"""
98 """get issues list"""
99 params.setdefault("state", "closed")
99 params.setdefault("state", "closed")
100 url = "https://api.github.com/repos/{project}/issues".format(project=project)
100 url = "https://api.github.com/repos/{project}/issues".format(project=project)
101 if auth:
101 if auth:
102 headers = make_auth_header()
102 headers = make_auth_header()
103 else:
103 else:
104 headers = None
104 headers = None
105 pages = get_paged_request(url, headers=headers, **params)
105 pages = get_paged_request(url, headers=headers, **params)
106 return pages
106 return pages
107
107
108 def get_milestones(project, auth=False, **params):
108 def get_milestones(project, auth=False, **params):
109 params.setdefault('state', 'all')
109 params.setdefault('state', 'all')
110 url = "https://api.github.com/repos/{project}/milestones".format(project=project)
110 url = "https://api.github.com/repos/{project}/milestones".format(project=project)
111 if auth:
111 if auth:
112 headers = make_auth_header()
112 headers = make_auth_header()
113 else:
113 else:
114 headers = None
114 headers = None
115 milestones = get_paged_request(url, headers=headers, **params)
115 milestones = get_paged_request(url, headers=headers, **params)
116 return milestones
116 return milestones
117
117
118 def get_milestone_id(project, milestone, auth=False, **params):
118 def get_milestone_id(project, milestone, auth=False, **params):
119 milestones = get_milestones(project, auth=auth, **params)
119 milestones = get_milestones(project, auth=auth, **params)
120 for mstone in milestones:
120 for mstone in milestones:
121 if mstone['title'] == milestone:
121 if mstone['title'] == milestone:
122 return mstone['number']
122 return mstone['number']
123 else:
123 else:
124 raise ValueError("milestone %s not found" % milestone)
124 raise ValueError("milestone %s not found" % milestone)
125
125
126 def is_pull_request(issue):
126 def is_pull_request(issue):
127 """Return True if the given issue is a pull request."""
127 """Return True if the given issue is a pull request."""
128 return bool(issue.get('pull_request', {}).get('html_url', None))
128 return bool(issue.get('pull_request', {}).get('html_url', None))
129
129
130 def get_authors(pr):
130 def get_authors(pr):
131 print("getting authors for #%i" % pr['number'], file=sys.stderr)
131 print("getting authors for #%i" % pr['number'], file=sys.stderr)
132 h = make_auth_header()
132 h = make_auth_header()
133 r = requests.get(pr['commits_url'], headers=h)
133 r = requests.get(pr['commits_url'], headers=h)
134 r.raise_for_status()
134 r.raise_for_status()
135 commits = r.json()
135 commits = r.json()
136 authors = []
136 authors = []
137 for commit in commits:
137 for commit in commits:
138 author = commit['commit']['author']
138 author = commit['commit']['author']
139 authors.append("%s <%s>" % (author['name'], author['email']))
139 authors.append("%s <%s>" % (author['name'], author['email']))
140 return authors
140 return authors
141
141
General Comments 0
You need to be logged in to leave comments. Login now