Merge lp:~jibel/canonical-qa-tracking/sru-tools into lp:canonical-qa-tracking

Proposed by Jean-Baptiste Lallement
Status: Merged
Approved by: Brian Murray
Approved revision: 446
Merged at revision: 449
Proposed branch: lp:~jibel/canonical-qa-tracking/sru-tools
Merge into: lp:canonical-qa-tracking
Diff against target: 244 lines (+239/-0)
1 file modified
sru-tools/thankyou-testers (+239/-0)
To merge this branch: bzr merge lp:~jibel/canonical-qa-tracking/sru-tools
Reviewer Review Type Date Requested Status
Brian Murray Approve
Review via email: mp+36550@code.launchpad.net

Description of the change

Moving the thankyou script from ubuntu-qa-tools to canonical-qa-tracking following comment of bdmurray https://code.edge.launchpad.net/~jibel/ubuntu-qa-tools/thankyou.xlpb-modifiers/+merge/34522

To post a comment you must log in.
Revision history for this message
Brian Murray (brian-murray) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'sru-tools'
2=== added file 'sru-tools/thankyou-testers'
3--- sru-tools/thankyou-testers 1970-01-01 00:00:00 +0000
4+++ sru-tools/thankyou-testers 2010-09-24 14:01:01 +0000
5@@ -0,0 +1,239 @@
6+#!/usr/bin/python
7+#
8+# This script will parse a bugs mailing list file for e-mails indicating
9+# that a bug has been tagged with a verification-* tag
10+# We then export the list of users having added a comment after between the
11+# moment the report has been tagged verification-needed and the moment the
12+# report has been tagged verification-done
13+# Canonical employees are filtered out
14+#
15+# The output are 2 "thank you" messages, one for IRC and I for the Wiki
16+# The messages are saved to /tmp/sru_thankyou.XXXXXXXX.msg for further reading
17+# use mutt -f /tmp/sru_thankyou.XXXXXXXX.msg
18+#
19+# Example:
20+# sru-thankyou 2010-08-25 bugmail/2010-08 bugmail/2010-09
21+#
22+#
23+# Copyright 2008-2010 Canonical, Ltd
24+# Author: Jean-Baptiste Lallement <jean-baptiste.lallement@ubuntu.com>
25+# Credits to Brian Murray for the parsing of the bugmail archive.
26+# Licensed under the GNU General Public License, version 3.
27+
28+# TODO:
29+# - Sort people by number of tasks verified
30+#
31+# We use 2 structures as to store bug and person information:
32+# srubugs[bug_id]
33+# 0. displayname
34+# 1. email addr
35+# 2. (display_name, lp_id) From X-Launchpad-Bug-Modifier
36+# 3. action_date
37+#
38+# people[lpid]
39+# 0. displayname
40+# 1. bugs[] list of bugs commented by this person
41+# 2. ircnickname
42+# 3. wikiname
43+# 4. canonical True if it's a canonical employee. See isCanonicalEmployee()
44+#
45+from mailbox import PortableUnixMailbox
46+from email import message_from_file
47+from email.errors import MessageParseError
48+from email.utils import parseaddr
49+from email.utils import parsedate
50+from sys import argv, stderr, stdout, exit
51+from operator import itemgetter
52+import logging
53+import re
54+
55+import time
56+from launchpadlib.launchpad import Launchpad
57+
58+LOGGINGLEVEL = logging.DEBUG
59+xlpm_pattern = re.compile('(?P<name>.+) \((?P<id>[^\)]+)\)')
60+
61+lp = None
62+# adjust as appropriate
63+report_folder = ""
64+
65+MESSAGE_NOT_PARSEABLE = object()
66+
67+def message_factory(fp):
68+ try:
69+ return message_from_file(fp)
70+ except MessageParseError:
71+ # Don't return None since that will stop the mailbox iterator.
72+ return MESSAGE_NOT_PARSEABLE
73+
74+
75+def show_progress(iterator, interval=100):
76+ """Show signs of progress."""
77+ for count, item in enumerate(iterator):
78+ if count % interval == 0:
79+ stderr.write('.')
80+ yield item
81+
82+def scan_bugs(startdate, messagelog, messages):
83+ """ Scan interesting reports
84+
85+ startdate: Date from which we want to export messages
86+ messagelog: file descriptor where to store the interesting messages for
87+ further reading
88+ """
89+ global xlpm_pattern
90+
91+ srudone = []
92+ for count, message in enumerate(messages):
93+ # Skip broken messages.
94+ if message is MESSAGE_NOT_PARSEABLE:
95+ continue
96+
97+ # Check it's from a Launchpad bug.
98+ reply_to = message['reply-to']
99+ if reply_to is None:
100+ continue
101+ reply_name, reply_address = parseaddr(reply_to)
102+ reply_local_part, reply_domain = reply_address.split('@')
103+ if not (reply_domain == 'bugs.launchpad.net' and
104+ reply_local_part.isdigit()):
105+ continue
106+ tags = message['X-Launchpad-Bug-Tags']
107+
108+ bug_id = int(reply_local_part)
109+ # Comments after verification is done are often metooing and not very useful
110+ if tags and 'verification-' in tags and not bug_id in srudone:
111+ sent_date = parsedate(message['date'])
112+ if sent_date < startdate:
113+ continue
114+ sender = parseaddr(message['from'])
115+
116+ # Remove the robots
117+ if sender[0] in ('Launchpad Bug Tracker',
118+ 'Bug Watch Updater',
119+ 'Ubuntu QA Website'):
120+ continue
121+ xlpm_header = message['X-Launchpad-Bug-Modifier']
122+ if not xlpm_header:
123+ continue
124+ xlpm_m = xlpm_pattern.search(xlpm_header)
125+ if xlpm_m:
126+ modifier=xlpm_m.groupdict() # {display_name, lp_id}
127+ action_date = time.mktime(sent_date)
128+ try:
129+ srubugs[bug_id].append((sender[0], sender[1], modifier, action_date))
130+ except KeyError:
131+ srubugs[bug_id] = [(sender[0], sender[1], modifier, action_date)]
132+
133+
134+ messagelog.write(str(message))
135+ if tags and 'verification-done' in tags:
136+ srudone.append(bug_id)
137+
138+def ircnickname(person, server="irc.freenode.net"):
139+ for irc in person.irc_nicknames:
140+ if irc.network == server:
141+ return irc.nickname
142+ return None
143+
144+def wikiname(person, server='wiki.ubuntu.com'):
145+ for wiki in person.wiki_names:
146+ if server in wiki.wiki:
147+ return wiki.wikiname
148+ return None
149+
150+def isCanonicalEmployee(person):
151+ """ Return true if we think the person is a Canonical employee
152+
153+ We assume that any member of a canonical team is a canonical employee
154+ Is there a way to find if a team is a subteam of canonical ???
155+ """
156+ canonical_teams = ('canonical', 'landscape')
157+ for tm in person.memberships_details:
158+ for ct in canonical_teams:
159+ if ct in tm.team.name:
160+ return True
161+ return False
162+
163+def printReport(people, type ):
164+ if not people:
165+ print "No people to thank. Sorry!"
166+ return
167+
168+ print "== Thank you output for %s ==" % ( 'IRC' if 'irc' in type.lower() else "WIKI")
169+ # Filter Canonical employees
170+ noncanonical = filter(lambda x: not people[x]['canonical'] , people)
171+
172+ if 'irc' in type.lower():
173+ thankslist = map(lambda x: people[x]['displayname'] +
174+ ' (' + str(people[x]['ircnickname']) + ')'
175+ if people[x]['ircnickname']
176+ else people[x]['displayname'], sorted(noncanonical))
177+ else:
178+ thankslist = map(lambda x: '[[' + str(people[x]['wikiname']) +
179+ '|' + people[x]['displayname'] + ']]'
180+ if people[x]['wikiname']
181+ else people[x]['displayname'], sorted(noncanonical))
182+
183+ print "Thanks to %s and %s for testing packages in -proposed.\n\
184+\n\
185+As always, you can see the current set of packages needing testing in the \
186+-proposed queue at http://people.canonical.com/~ubuntu-archive/pending-sru.html . \
187+Your assistance in testing is always appreciated! " % \
188+ (", ".join(thankslist[:-1]), thankslist[-1])
189+
190+
191+if __name__ == '__main__':
192+ logging.basicConfig(level=LOGGINGLEVEL)
193+
194+ # Check if the amount of arguments is correct
195+ if len(argv) < 3 or argv[1] in ('help', '-h', '--help'):
196+ print 'Usage: %s <from YYYY-MM-DD> <bug_mailinglist_file> [<bug_mailinglist_file> ...]' % argv[0]
197+ exit(1)
198+
199+ srubugs = {}
200+ people = {}
201+
202+ startdate = time.strptime(argv[1], "%Y-%m-%d")
203+ messagelogname = "/tmp/sru_thankyou.%s.msg" % (str(int(time.time())))
204+ messagelog = open(messagelogname, "wb")
205+
206+ for mailbox_file in argv[2:]:
207+ mailbox = PortableUnixMailbox(
208+ open(mailbox_file, 'rb'), message_factory)
209+ scan_bugs(startdate, messagelog, show_progress(mailbox))
210+
211+ print
212+ lp = Launchpad.login_anonymously("lookup-irc-nick", "edge")
213+ for k, b in sorted(srubugs.items(), key=itemgetter(1), reverse=False):
214+ for v in b:
215+ logging.debug('Searching [%s]: %s' % (v[2]['id'],v[2]['name']))
216+ personId = v[2]['id']
217+ try:
218+ people[personId]['bugs'].append(k)
219+ logging.debug("- Already exists: %s" % (personId))
220+ logging.debug("- Updating with bug: %s" % (k))
221+ except KeyError:
222+ try:
223+ person = lp.people[personId]
224+ except KeyError:
225+ continue
226+ if person:
227+ logging.debug("= Found: [%s] %s" % (v[2]['id'],person.name))
228+ people[person.name] = {
229+ 'displayname':person.display_name,
230+ 'bugs':[k],
231+ 'ircnickname':ircnickname(person),
232+ 'wikiname':wikiname(person),
233+ 'canonical':isCanonicalEmployee(person)
234+ }
235+ else:
236+ logging.debug("No person found with id [%s] skipping" % personId)
237+ continue
238+
239+ print
240+ printReport(people,'irc')
241+ print
242+ printReport(people,'wiki')
243+ print
244+ print "Messages have been saved to ", messagelogname

Subscribers

People subscribed via source and target branches

to status/vote changes: