|  | #!/usr/bin/env python3 | 
|  |  | 
|  | 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([lable["name"] for lable 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, "w") 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() |