1#!/usr/bin/env python
2
3r"""
4Exports issues from a list of repositories to individual CSV files.
5Uses basic authentication (GitHub username + password) to retrieve issues
6from a repository that username has access to. Supports GitHub API v3.
7"""
8import argparse
9import csv
10from getpass import getpass
11import requests
12
13auth = None
14states = 'all'
15
16
17def write_issues(response, csv_out):
18    r"""
19    Parses JSON response and writes to CSV.
20    """
21    print response
22    if response.status_code != 200:
23        raise Exception(response.status_code)
24    for issue in response.json():
25        if 'pull_request' not in issue:
26            labels = ', '.join([l['name'] for l in issue['labels']])
27            date = issue['created_at'].split('T')[0]
28            # Change the following line to write out additional fields
29            csv_out.writerow([labels.encode('utf-8'),
30                             issue['title'].encode('utf-8'),
31                             issue['state'].encode('utf-8'),
32                             date.encode('utf-8'),
33                             issue['html_url'].encode('utf-8'),
34                             issue['user']['login'].encode('utf-8')])
35
36
37def get_github_issues(name):
38    r"""
39    Requests issues from GitHub API and writes to CSV file.
40    """
41    print name
42    print states
43    l_url = 'https://api.github.com/repos/{}/issues?state={}'.format(name,
44                                                                     states)
45    print l_url
46    # 'https://api.github.com/repos/{}/issues?state={}'.format(name, state)
47    response = requests.get(l_url, auth=auth)
48
49    csvfilename = '{}-issues.csv'.format(name.replace('/', '-'))
50    with open(csvfilename, 'w') as csvfile:
51        csv_out = csv.writer(csvfile)
52        csv_out.writerow(['Labels', 'Title', 'State', 'Date', 'URL', 'Author'])
53        write_issues(response, csv_out)
54
55        # Multiple requests are required if response is paged
56        if 'link' in response.headers:
57            pages = {rel[6:-1]: url[url.index('<')+1:-1] for url, rel in
58                     (link.split(';') for link in
59                      response.headers['link'].split(','))}
60            while 'last' in pages and 'next' in pages:
61                pages = {rel[6:-1]: url[url.index('<')+1:-1] for url, rel in
62                         (link.split(';') for link in
63                          response.headers['link'].split(','))}
64                response = requests.get(pages['next'], auth=auth)
65                write_issues(response, csv_out)
66                if pages['next'] == pages['last']:
67                    break
68
69        csvfile.close()
70
71parser = argparse.ArgumentParser(description="Write GitHub repository issues "
72                                             "to CSV file.")
73
74parser.add_argument('username', nargs='+', help="GitHub user name, "
75                    "formatted as 'username'")
76
77parser.add_argument('password', nargs='+', help="GitHub username password, "
78                    "formatted as 'password'")
79
80parser.add_argument('repositories', nargs='+', help="Repository names, "
81                    "formatted as 'basereponame/repo'")
82
83parser.add_argument('--all', action='store_true', help="Returns both open "
84                    "and closed issues.")
85args = parser.parse_args()
86
87if args.all:
88    state = 'all'
89
90for argusername in args.username:
91    username = argusername
92
93for argpassword in args.password:
94    password = argpassword
95
96auth = (username, password)
97
98for repository in args.repositories:
99    get_github_issues(repository)
100