3
from launchpadlib.launchpad import Launchpad
4
from operator import itemgetter
7
def calculate_age(from_date = None):
12
def format_as_table(data,
16
sort_order_reverse=False):
17
"""Takes a list of dictionaries, formats the data, and returns
18
the formatted data as a text table.
21
data - Data to process (list of dictionaries). (Type: List)
22
keys - List of keys in the dictionary. (Type: List)
25
header - The table header. (Type: List)
26
sort_by_key - The key to sort by. (Type: String)
27
sort_order_reverse - Default sort order is ascending, if
28
True sort order will change to descending. (Type: Boolean)
30
# Sort the data if a sort key is specified (default sort order
34
key=itemgetter(sort_by_key),
35
reverse=sort_order_reverse)
37
# If header is not empty, add header to data
39
# Get the length of each header and create a divider based
43
header_divider.append('-' * len(name))
45
# Create a list of dictionary from the keys and the header and
46
# insert it at the beginning of the list. Do the same for the
47
# divider and insert below the header.
48
header_divider = dict(zip(keys, header_divider))
49
data.insert(0, header_divider)
50
header = dict(zip(keys, header))
51
data.insert(0, header)
55
column_widths.append(max(len(str(column[key])) for column in data))
57
# Create a tuple pair of key and the associated column width for it
58
key_width_pair = zip(keys, column_widths)
60
format = ('%-*s ' * len(keys)).strip() + '\n'
64
# Create a tuple that will be used for the formatting in
66
for pair in key_width_pair:
67
data_to_format.append(pair[1])
68
data_to_format.append(element[pair[0]])
69
formatted_data += format % tuple(data_to_format)
73
def charm_review_queue():
74
print "Connecting to launchpad..."
75
lp = Launchpad.login_anonymously('charm-tools', 'production', version='devel', launchpadlib_dir='~/.cache/launchpadlib')
76
charm = lp.distributions['charms']
77
print "Querying launchpad for bugs ..."
78
bugs = charm.searchTasks(tags=['new-formula', 'new-charm'], tags_combinator="Any", status=['New', 'Confirmed', 'Triaged', 'In Progress', 'Fix Committed'])
79
charmers = lp.people['charmers']
80
print "Querying launchpad for proposals ..."
81
proposals = charmers.getRequestedReviews(status="Needs review")
83
max_summary_length = 50
84
for bug in bugs.entries:
85
entry_summary = bug['title'].split('"')[1].strip()
86
entry_age = datetime.datetime.utcnow() - datetime.datetime.strptime(bug['date_created'].split('+')[0], "%Y-%m-%dT%H:%M:%S.%f")
88
'date_created' : bug['date_created'].split("T")[0],
89
'age' : str(entry_age).split('.')[0],
90
'summary' : (entry_summary[:max_summary_length] + '...') if len(entry_summary) > max_summary_length else entry_summary,
91
'item' : bug['web_link'],
92
'status' : bug['status'],
95
for proposal in proposals.entries:
96
proposal_summary = proposal['description']
97
proposal_age = datetime.datetime.utcnow() - datetime.datetime.strptime(proposal['date_created'].split('+')[0], "%Y-%m-%dT%H:%M:%S.%f")
98
if proposal_summary is None:
99
proposal_summary = "Proposal"
101
'date_created' : proposal['date_created'].split("T")[0],
102
'age' : str(proposal_age).split('.')[0],
103
'summary' : (proposal_summary[:max_summary_length] + '...') if len(proposal_summary) > max_summary_length else proposal_summary,
104
'item' : proposal['web_link'],
105
'status' : proposal['queue_status'],
108
return(sorted(queue, key=lambda k: k['date_created']))
111
review_queue = charm_review_queue()
112
keys = ['date_created', 'age', 'summary', 'item', 'status' ]
113
headers = ['Date Created', 'Age', 'Summary', 'Item', 'Status']
114
if type(review_queue) == type([]) and len(review_queue) > 0:
115
print format_as_table(review_queue,
118
sort_by_key = 'date_created',
119
sort_order_reverse = False)
122
if __name__ == "__main__":