diff --git a/utilities/enissue.py b/utilities/enissue.py new file mode 100644 index 0000000..4699262 --- /dev/null +++ b/utilities/enissue.py @@ -0,0 +1,215 @@ +#!/usr/bin/env python3 +from __future__ import print_function +import sys +import json +import os + +try: + import urllib.request + request = urllib.request +except: + # python2 + python_mr = 2 + import urllib2 as urllib + request = urllib + +try: + from urllib.parse import urlparse + from urllib.parse import quote + from urllib.parse import unquote +except ImportError: + from urlparse import urlparse + from urllib import quote + from urllib import unquote + + +repo_url = "https://api.github.com/repos/poikilos/EnlivenMinetest" +url = repo_url + "/issues" +labels_url = repo_url + "/labels" +cmd = None +# me = sys.argv[0] +me = os.path.basename(__file__) +cmds = { + "list": { + "help": ("List all issues. Provide one or more labels to narrow" + " down the list. Alternatively, provide a label only." + " Labels with spaces require quotes. The matching is" + " not case sensitive."), + "examples": ["list", " list Bucket_Game", + " list Bucket_Game urgent", " Bucket_Game", + " Bucket_Game urgent"] + }, + "labels": { + "help": ("List all labels (just the labels themselves, not the" + " issues)."), + "examples": [" labels"] + }, + "<#>": { + "help": "Specify an issue number to see details.", + "examples": [" 1"] + } +} +match_all_labels = [] +def usage(): + print("") + print("Commands:") + left_w = 10 + spacer = " -- " + line_fmt = "{: <" + str(left_w) + "}" + spacer + "{}" + for name, command in cmds.items(): + hlp = command["help"] + print(line_fmt.format(name, hlp)) + if len(command["examples"]) > 0: + print(" "*(left_w+len(spacer)) + "Examples:") + for s in command["examples"]: + print(" "*(left_w+len(spacer)+2) + "./" + me + s) + print("") + print("") +match_number = None +for i in range(1, len(sys.argv)): + arg = sys.argv[i] + if arg.startswith("#"): + arg = arg[1:] + try: + match_number = int(arg) + except ValueError: + if (cmd is None) and (cmds.get(arg) is not None): + cmd = arg + else: + match_all_labels.append(arg) +if cmd is None: + if len(match_all_labels) > 1: + cmd = "list" + if match_number is not None: + cmd = "issue" +valid_cmds = ["issue"] +for k, v in cmds.items(): + valid_cmds.append(k) + +if cmd is None: + print() + print() + usage() + print() + print() + exit(0) +elif cmd not in valid_cmds: + print() + print() + usage() + print() + print(cmd + " is not a valid command.") + print() + print() + exit(0) +print("") +# print("Loading...") +response = request.urlopen(url) +d_s = response.read() +d = json.loads(d_s) +label_ids = [] +labels = [] + +match_all_labels_lower = [] +for s in match_all_labels: + # print("appending {} to match_all_labels_lower.".format(s.lower())) + match_all_labels_lower.append(s.lower()) + +match_count = 0 +matching_issue = None +for issue in d: + this_issue_labels_lower = [] + for label in issue["labels"]: + label_ids.append(label["id"]) + if label["url"].startswith(labels_url): + start = len(labels_url) + 1 # +1 for "/" + label_encoded = label["url"][start:] + label_s = unquote(label_encoded) + this_issue_labels_lower.append(label_s.lower()) + if label_s not in labels: + labels.append(label_s) + else: + raise ValueError("The url '{}' does not start with" + " '{}'".format(label["url"], labels_url)) + if len(match_all_labels) > 0: + this_issue_match_count = 0 + for try_label in match_all_labels_lower: + if try_label in this_issue_labels_lower: + this_issue_match_count += 1 + # else: + # print("#{} is not a match ({} is not in" + # " {})".format(issue["number"], try_label, + # this_issue_labels_lower)) + if this_issue_match_count == len(match_all_labels): + match_count += 1 + print("#{} {}".format(issue["number"], issue["title"])) + if match_number is not None: + # INFO: match_number & issue["number"] are ints + if match_number == issue["number"]: + matching_issue = issue +if matching_issue is not None: + print("") + print("#{} {}".format(issue["number"], issue["title"])) + # print(matching_issue["html_url"]) + print("") + this_issue_json_url = matching_issue["url"] + response = request.urlopen(this_issue_json_url) + issue_data_s = response.read() + issue_data = json.loads(issue_data_s) + markdown = issue_data["body"] + markdown = markdown.replace("\\r\\n", "\n").replace("\\t", "\t") + left_w = 10 + spacer = " " + line_fmt = "{: <" + str(left_w) + "}" + spacer + "{}" + print(line_fmt.format("html_url:", matching_issue["html_url"])) + print(line_fmt.format("by:", issue_data["user"]["login"])) + print(line_fmt.format("state:", issue_data["state"])) + assignees = issue_data["assignees"] + if len(assignees) > 1: + print(line_fmt.format("assignees:", " ".join(assignees))) + else: + print(line_fmt.format("assignee:", issue_data["assignee"])) + print(markdown) + if issue_data["comments"] > 0: + print("") + print("") + print("({}) comment(s):".format(issue_data["comments"])) + this_cmts_json_url = issue_data["comments_url"] + response = request.urlopen(this_cmts_json_url) + cmts_data_s = response.read() + cmts_data = json.loads(cmts_data_s) + left_margin = " " + c_prop_fmt = (left_margin + "{: <" + str(left_w) + "}" + spacer + + "{}") + for cmt in cmts_data: + print("") + print("") + print(c_prop_fmt.format("from:", cmt["user"]["login"])) + print(c_prop_fmt.format("updated_at:", cmt["updated_at"])) + print("") + print(left_margin + cmt["body"]) + print("") + + print("") + print("") + + +if cmd == "labels": + for label_s in labels: + print(label_s) + print("") + print("The repo has {} label(s).".format(len(labels))) +elif cmd == "list": + print() + print("{} issue(s) matched {}".format( + match_count, + " + ".join("'{}'".format(s) for s in match_all_labels) + )) + if match_count > 0: + print() + print() + print("To view details, type") + print(" ./" + me) + print("followed by a number.") +print("") +