import os import urllib import csv import smtplib from optparse import make_option import StringIO from jhbuild.commands import Command, register_command import jhbuild.moduleset def _get_ticket_uri(number): return 'http://dev.laptop.org/ticket/' + number def _send_mail(sender, from_address, to_address, subject, text): msg = 'From: %s<%s>\nTo: %s\nSubject: %s\n%s' % \ (sender, from_address, to_address, subject, text) server = smtplib.SMTP('localhost') server.sendmail(from_address, to_address, msg) server.quit() class TextWriter(object): def __init__(self, out): self.out = out def write_headline(self, headline): self.out.write('= ' + headline + ' =\n\n') def write_tickets(self, tickets, compact=False): for ticket in tickets: number = ticket['number'] summary = ticket['summary'] if compact: self.out.write('* #%s %s\n' % (number, summary)) else: self.out.write(summary + '\n') self.out.write(_get_ticket_uri(number) + '\n\n') if compact: self.out.write('\n') def write_testcases(self, testcases): for number, testcase in testcases: self.out.write('#%s\n\n%s\n\n\n' % (number, testcase)) class ReviewsReport(object): def __init__(self, config): self._requested = {} self._approved = {} self._rejected = {} self._state_path = os.path.join(config.get_user_path(), 'reviews') def generate(self): f = urllib.urlopen('http://dev.laptop.org/query?' \ 'format=csv&' \ 'component=sugar&' \ 'component=datastore&' \ 'component=presence-service&' \ 'component=journal-activity&' \ 'col=id&col=summary&col=keywords&' \ 'keywords=~r%2B&keywords=~r-&keywords=~r%3F') reader = csv.reader(f) reader.next() for row in reader: number = row[0] keyword = row[2] ticket = { 'number' : row[0], 'summary' : row[1] } if 'r?' in keyword: ticket['review_state'] = 'r?' self._requested[number] = ticket if 'r+' in keyword: ticket['review_state'] = 'r+' self._approved[number] = ticket if 'r-' in keyword: ticket['review_state'] = 'r-' self._rejected[number] = ticket f.close() def write(self, writer): old_requested, old_approved, old_rejected = self._load() requested = self._diff_tickets(old_requested, self._requested) approved = self._diff_tickets(old_approved, self._approved) rejected = self._diff_tickets(old_rejected, self._rejected) if requested: writer.write_headline('New requests') writer.write_tickets(requested) if approved: writer.write_headline('Approved requests') writer.write_tickets(approved) if rejected: writer.write_headline('Rejected requests') writer.write_tickets(rejected) def save(self): s = json.write([self._requested, self._approved, self._rejected]) f = open(os.path.join(self._state_path), 'w') f.write(s) f.close() def _load(self): path = os.path.join(self._state_path) if os.path.exists(path): f = open(path, 'r') result = json.read(f.read()) f.close() return result else: return ({}, {}, {}) def _diff_tickets(self, old, new): diff = [] for number, ticket in new.items(): if number in old: old_ticket = old[number] if old_ticket['review_state'] != ticket['review_state']: diff.append(ticket) else: diff.append(ticket) return diff class cmd_report(Command): name = 'report' usage_args = '' def __init__(self): Command.__init__(self, [ make_option('-t', '--type', action='store', dest='type', default=None, help='specify the report type'), make_option('-s', '--sendto', action='append', dest='sendto', default=None, help='send report to the specified mail address') ]) def run(self, config, options, args): report_types = [ 'reviews' ] if options.type not in report_types: print 'Available reports:\n' + '\n'.join(report_types) return 1 if options.type == 'reviews': report = ReviewsReport(config) report.generate() out = StringIO.StringIO() report.write(TextWriter(out)) text = out.getvalue() out.close() if options.sendto: if text: print 'Sending to ' + ', '.join(options.sendto) for to_address in options.sendto: _send_mail('Release Team', 'mpgritti@gmail.com', to_address, 'Reviews report', text) else: print 'Empty report, do not send' else: print text report.save() try: import json register_command(cmd_report) except ImportError: print 'Disable report, json-py is not installed.'