|  | #!/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']]) | 
|  |  | 
|  | # Below lines to overcome "TypeError: 'NoneType' object has | 
|  | # no attribute '__getitem__'" | 
|  |  | 
|  | close_date = issue.get('closed_at') | 
|  | if close_date: | 
|  | close_date = issue.get('closed_at').split('T')[0] | 
|  |  | 
|  | assignee_resp = issue.get('assignees', 'Not Assigned') | 
|  | if assignee_resp: | 
|  | owners = ','.join([assignee_login['login'] for | 
|  | assignee_login in assignee_resp]) | 
|  | else: | 
|  | owners = "Not Assigned" | 
|  |  | 
|  | milestone_resp = issue.get('milestone', 'Not Assigned') | 
|  | if milestone_resp: | 
|  | milestone_resp = milestone_resp['title'].encode('utf-8') | 
|  |  | 
|  | # 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'), | 
|  | issue.get('created_at').split('T')[0], | 
|  | close_date, | 
|  | issue.get('html_url').encode('utf-8'), | 
|  | issue.get('user').get('login').encode('utf-8'), | 
|  | owners, milestone_resp]) | 
|  |  | 
|  |  | 
|  | def get_issues_from_github_to_csv(name, response): | 
|  | r""" | 
|  | Requests issues from GitHub API and writes to CSV file. | 
|  | Description of argument(s): | 
|  | name  Name of the GitHub repository | 
|  | response  GitHub repository response | 
|  | """ | 
|  | print name | 
|  | print states | 
|  |  | 
|  | # 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 | 
|  |  | 
|  |  | 
|  | 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' | 
|  |  | 
|  | username = args.username | 
|  |  | 
|  | password = getpass.getpass("Enter your GitHub Password:") | 
|  |  | 
|  | auth = (username, password) | 
|  |  | 
|  | # To set the csv filename | 
|  | csvfilename = "" | 
|  | for repository in args.repositories: | 
|  | csvfilename_temp = '{}'.format(repository.replace('/', '-')) | 
|  | csvfilename = csvfilename+csvfilename_temp | 
|  | csvfilename = csvfilename+'-issues.csv' | 
|  | with open(csvfilename, 'wb') as csvfileout: | 
|  | csv_out = csv.writer(csvfileout) | 
|  | csv_out.writerow(['Labels', 'Title', 'State', 'Open Date', | 
|  | 'Close Date', 'URL', 'Author', 'Assignees', | 
|  | 'Milestone']) | 
|  | for repository in args.repositories: | 
|  | l_url = 'https://api.github.com/repos/{}/issues?state={}' | 
|  | l_url = l_url.format(repository, states) | 
|  | response = requests.get(l_url, auth=auth) | 
|  | write_issues(response, csv_out) | 
|  | get_issues_from_github_to_csv(repository, response) | 
|  | csvfileout.close() |