blob: a8dd6b3b12d4891dd749679e32ebf51319cd8cbe [file] [log] [blame]
#!/usr/bin/env python
r"""
Exports issues from a list of repositories to individual CSV files.
Uses basic authentication (GitHub username + password) to retrieve issues
from a repository that username has access to. Supports GitHub API v3.
"""
import argparse
import csv
import getpass
import requests
auth = None
states = 'all'
def write_issues(response, csv_out):
r"""
Parses JSON response and writes to CSV.
"""
print response
if response.status_code != 200:
raise Exception(response.status_code)
for issue in response.json():
if 'pull_request' not in issue:
labels = ', '.join([l['name'] for l in issue['labels']])
date = issue.get('created_at').split('T')[0]
# Below lines to overcome "TypeError: 'NoneType' object has
# no attribute '__getitem__'"
assignee_resp = issue.get('assignee', 'Not Assigned')
if assignee_resp:
assignee_resp = assignee_resp.get('login').encode('utf-8')
else:
assignee_resp = "Not Assigned"
# Change the following line to write out additional fields
csv_out.writerow([labels.encode('utf-8'),
issue.get('title').encode('utf-8'),
issue.get('state').encode('utf-8'),
date.encode('utf-8'),
issue.get('html_url').encode('utf-8'),
issue.get('user').get('login').encode('utf-8'),
assignee_resp])
def get_issues_from_github_to_csv(name):
r"""
Requests issues from GitHub API and writes to CSV file.
"""
print name
print states
l_url = 'https://api.github.com/repos/{}/issues?state={}'.format(name,
states)
print l_url
# 'https://api.github.com/repos/{}/issues?state={}'.format(name, state)
response = requests.get(l_url, auth=auth)
csvfilename = '{}-issues.csv'.format(name.replace('/', '-'))
with open(csvfilename, 'w') as csvfile:
csv_out = csv.writer(csvfile)
csv_out.writerow(['Labels', 'Title', 'State', 'Date', 'URL', 'Author',
'Assignee'])
write_issues(response, csv_out)
# Multiple requests are required if response is paged
if 'link' in response.headers:
pages = {rel[6:-1]: url[url.index('<')+1:-1] for url, rel in
(link.split(';') for link in
response.headers['link'].split(','))}
while 'last' in pages and 'next' in pages:
pages = {rel[6:-1]: url[url.index('<')+1:-1] for url, rel in
(link.split(';') for link in
response.headers['link'].split(','))}
response = requests.get(pages['next'], auth=auth)
write_issues(response, csv_out)
if pages['next'] == pages['last']:
break
csvfile.close()
parser = argparse.ArgumentParser(description="Write GitHub repository issues "
"to CSV file.")
parser.add_argument('username', nargs='+', help="GitHub user name, "
"formatted as 'username'")
parser.add_argument('repositories', nargs='+', help="Repository names, "
"formatted as 'basereponame/repo'")
parser.add_argument('--all', action='store_true', help="Returns both open "
"and closed issues.")
args = parser.parse_args()
if args.all:
state = 'all'
for argusername in args.username:
username = argusername
password = getpass.getpass("Enter your GitHub Password:")
auth = (username, password)
for repository in args.repositories:
get_issues_from_github_to_csv(repository)