← Back to team overview

ubuntu-bugcontrol team mailing list archive

[Merge] lp:~jibel/ubuntu-qa-tools/thankyou.xlpb-modifiers into lp:ubuntu-qa-tools

 

Jean-Baptiste Lallement has proposed merging lp:~jibel/ubuntu-qa-tools/thankyou.xlpb-modifiers into lp:ubuntu-qa-tools.

Requested reviews:
  Ubuntu Bug Control (ubuntu-bugcontrol)

-- 
https://code.launchpad.net/~jibel/ubuntu-qa-tools/thankyou.xlpb-modifiers/+merge/34522
Your team Ubuntu Bug Control is requested to review the proposed merge of lp:~jibel/ubuntu-qa-tools/thankyou.xlpb-modifiers into lp:ubuntu-qa-tools.
=== added file 'sru-report-tools/thankyou-testers'
--- sru-report-tools/thankyou-testers	1970-01-01 00:00:00 +0000
+++ sru-report-tools/thankyou-testers	2010-09-03 10:14:41 +0000
@@ -0,0 +1,239 @@
+#!/usr/bin/python
+#
+# This script will parse a bugs mailing list file for e-mails indicating
+# that a bug has been tagged with a verification-* tag
+# We then export the list of users having added a comment after between the
+# moment the report has been tagged verification-needed and the moment the
+# report has been tagged verification-done
+# Canonical employees are filtered out
+#
+# The output are 2 "thank you" messages, one for IRC and I for the Wiki
+# The messages are saved to /tmp/sru_thankyou.XXXXXXXX.msg for further reading
+# use mutt -f /tmp/sru_thankyou.XXXXXXXX.msg
+#
+# Example:
+# sru-thankyou 2010-08-25 bugmail/2010-08 bugmail/2010-09
+#
+#
+# Copyright 2008-2010 Canonical, Ltd
+# Author: Jean-Baptiste Lallement <jean-baptiste.lallement@xxxxxxxxxx>
+# Credits to Brian Murray for the parsing of the bugmail archive.
+# Licensed under the GNU General Public License, version 3.
+
+# TODO:
+#   - Sort people by number of tasks verified
+#
+# We use 2 structures as to store bug and person information:
+# srubugs[bug_id]
+#   0. displayname
+#   1. email addr
+#   2. (display_name, lp_id)     From X-Launchpad-Bug-Modifier
+#   3. action_date
+#
+# people[lpid]
+#  0. displayname
+#  1. bugs[]        list of bugs commented by this person
+#  2. ircnickname
+#  3. wikiname
+#  4. canonical     True if it's a canonical employee. See isCanonicalEmployee()
+#
+from mailbox import PortableUnixMailbox
+from email import message_from_file
+from email.errors import MessageParseError
+from email.utils import parseaddr
+from email.utils import parsedate
+from sys import argv, stderr, stdout, exit
+from operator import itemgetter
+import logging
+import re
+
+import time
+from launchpadlib.launchpad import Launchpad
+
+LOGGINGLEVEL = logging.DEBUG
+xlpm_pattern = re.compile('(?P<name>.+) \((?P<id>[^\)]+)\)')
+
+lp = None
+# adjust as appropriate
+report_folder = ""
+
+MESSAGE_NOT_PARSEABLE = object()
+
+def message_factory(fp):
+    try:
+        return message_from_file(fp)
+    except MessageParseError:
+        # Don't return None since that will stop the mailbox iterator.
+        return MESSAGE_NOT_PARSEABLE
+
+
+def show_progress(iterator, interval=100):
+    """Show signs of progress."""
+    for count, item in enumerate(iterator):
+        if count % interval == 0:
+            stderr.write('.')
+        yield item
+
+def scan_bugs(startdate, messagelog, messages):
+    """ Scan interesting reports
+
+    startdate: Date from which we want to export messages
+    messagelog: file descriptor where to store the interesting messages for
+        further reading
+    """
+    global xlpm_pattern
+
+    srudone = []
+    for count, message in enumerate(messages):
+        # Skip broken messages.
+        if message is MESSAGE_NOT_PARSEABLE:
+            continue
+
+        # Check it's from a Launchpad bug.
+        reply_to = message['reply-to']
+        if reply_to is None:
+            continue
+        reply_name, reply_address = parseaddr(reply_to)
+        reply_local_part, reply_domain = reply_address.split('@')
+        if not (reply_domain == 'bugs.launchpad.net' and
+                reply_local_part.isdigit()):
+            continue
+        tags = message['X-Launchpad-Bug-Tags']
+
+        bug_id = int(reply_local_part)
+        # Comments after verification is done are often metooing and not very useful
+        if tags and 'verification-' in tags and not bug_id in srudone:
+            sent_date = parsedate(message['date'])
+            if sent_date < startdate:
+                continue
+            sender = parseaddr(message['from'])
+
+            # Remove the robots
+            if sender[0] in ('Launchpad Bug Tracker',
+                             'Bug Watch Updater',
+                             'Ubuntu QA Website'):
+                continue
+            xlpm_header = message['X-Launchpad-Bug-Modifier']
+            if not xlpm_header:
+                continue
+            xlpm_m = xlpm_pattern.search(xlpm_header)
+            if xlpm_m:
+                modifier=xlpm_m.groupdict() # {display_name, lp_id}
+            action_date = time.mktime(sent_date)
+            try:
+                srubugs[bug_id].append((sender[0], sender[1], modifier, action_date))
+            except KeyError:
+                srubugs[bug_id] = [(sender[0], sender[1], modifier, action_date)]
+
+
+            messagelog.write(str(message))
+            if tags and 'verification-done' in tags:
+                srudone.append(bug_id)
+
+def ircnickname(person, server="irc.freenode.net"):
+    for irc in person.irc_nicknames:
+        if irc.network == server:
+            return irc.nickname
+    return None
+
+def wikiname(person, server='wiki.ubuntu.com'):
+    for wiki in person.wiki_names:
+        if server in wiki.wiki:
+            return wiki.wikiname
+    return None
+
+def isCanonicalEmployee(person):
+    """ Return true if we think the person is a Canonical employee
+
+    We assume that any member of a canonical team is a canonical employee
+    Is there a way to find if a team is a subteam of canonical ???
+    """
+    canonical_teams = ('canonical', 'landscape')
+    for tm in person.memberships_details:
+        for ct in canonical_teams:
+            if ct in tm.team.name:
+                return True
+    return False
+
+def printReport(people, type ):
+    if not people:
+        print "No people to thank. Sorry!"
+        return
+
+    print "== Thank you output for %s ==" % ( 'IRC' if 'irc' in type.lower() else "WIKI")
+    # Filter Canonical employees
+    noncanonical = filter(lambda x: not people[x]['canonical'] , people)
+
+    if 'irc' in type.lower():
+        thankslist = map(lambda x: people[x]['displayname'] +
+                                ' (' + str(people[x]['ircnickname']) + ')'
+                                if people[x]['ircnickname']
+                                else people[x]['displayname'], sorted(noncanonical))
+    else:
+        thankslist = map(lambda x: '[[' + str(people[x]['wikiname']) +
+                                '|' + people[x]['displayname'] + ']]'
+                                if people[x]['wikiname']
+                                else people[x]['displayname'], sorted(noncanonical))
+
+    print "Thanks to %s and %s for testing packages in -proposed.\n\
+\n\
+As always, you can see the current set of packages needing testing in the \
+-proposed queue at http://people.canonical.com/~ubuntu-archive/pending-sru.html . \
+Your assistance in testing is always appreciated! " % \
+    (", ".join(thankslist[:-1]), thankslist[-1])
+
+
+if __name__ == '__main__':
+    logging.basicConfig(level=LOGGINGLEVEL)
+
+    # Check if the amount of arguments is correct
+    if len(argv) < 3 or argv[1] in ('help', '-h', '--help'):
+        print 'Usage: %s <from YYYY-MM-DD> <bug_mailinglist_file> [<bug_mailinglist_file> ...]' % argv[0]
+        exit(1)
+
+    srubugs = {}
+    people = {}
+
+    startdate = time.strptime(argv[1], "%Y-%m-%d")
+    messagelogname = "/tmp/sru_thankyou.%s.msg" % (str(int(time.time())))
+    messagelog = open(messagelogname, "wb")
+
+    for mailbox_file in argv[2:]:
+        mailbox = PortableUnixMailbox(
+            open(mailbox_file, 'rb'), message_factory)
+        scan_bugs(startdate, messagelog, show_progress(mailbox))
+
+    print
+    lp = Launchpad.login_anonymously("lookup-irc-nick", "edge")
+    for k, b in sorted(srubugs.items(), key=itemgetter(1), reverse=False):
+        for v in b:
+            logging.debug('Searching [%s]: %s' % (v[2]['id'],v[2]['name']))
+            personId = v[2]['id']
+            try:
+                people[personId]['bugs'].append(k)
+                logging.debug("- Already exists: %s" % (personId))
+                logging.debug("- Updating with bug: %s" % (k))
+            except KeyError:
+                try:
+                    person = lp.people[personId]
+                except KeyError:
+                    continue
+                if person:
+                    logging.debug("= Found: [%s]	%s" % (v[2]['id'],person.name))
+                    people[person.name] =  {
+                        'displayname':person.display_name,
+                        'bugs':[k],
+                        'ircnickname':ircnickname(person),
+                        'wikiname':wikiname(person),
+                        'canonical':isCanonicalEmployee(person)
+                    }
+                else:
+                    logging.debug("No person found with id [%s] skipping" % personId)
+                    continue
+
+    print
+    printReport(people,'irc')
+    print
+    printReport(people,'wiki')
+    print
+    print "Messages have been saved to ", messagelogname


Follow ups