123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- #!/usr/bin/python
- """
- bts -- manage bugs filed against ftp.debian.org
- @contact: Debian FTP Master <ftpmaster@debian.org>
- @copyright: 2009 Mike O'Connor <stew@vireo.org>
- @copyright: 2010 Alexander Reichle-Schmehl <tolimar@debian.org>
- @license: GNU General Public License version 2 or later
- """
- # This program is free software; you can redistribute it and/or modify it
- # under the terms of the GNU General Public License as published by the
- # Free Software Foundation; either version 2, or (at your option) any
- # later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program; if not, write to the Free Software
- # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- # USA.
- ################################################################################
- ################################################################################
- from __future__ import print_function
- import sys
- import re
- import logging
- log = logging.getLogger()
- import apt_pkg
- from daklib import utils
- import debianbts as bts
- def usage():
- print("""
- SYNOPSIS
- dak bts-categorize [options]
- OPTIONS
- -s
- --simulate
- Don't send email, instead output the lines that would be sent to
- control@b.d.o.
- -v
- --verbose
- Print more informational log messages
- -q
- --quiet
- Suppress informational messages
- -h
- --help
- Print this documentation.
- """)
- arguments = [('s', 'simulate', 'BtsCategorize::Options::Simulate'),
- ('v', 'verbose', 'BtsCategorize::Options::Verbose'),
- ('q', 'quiet', 'BtsCategorize::Options::Quiet'),
- ('h', 'help', 'BtsCategorize::Options::Help')]
- class BugClassifier(object):
- """
- classify bugs using usertags based on the bug subject lines
- >>> BugClassifier.rm_re.match( "RM: asdf" ) != None
- True
- >>> BugClassifier.rm_re.match( "[dak] Packages.diff/Index broken" ) != None
- False
- >>> BugClassifier.dak_re.match( "[dak] Packages.diff/Index broken" ) != None
- True
- """
- rm_re = re.compile("^RM")
- dak_re = re.compile("^\[dak\]")
- arch_re = re.compile("^\[Architectures\]")
- override_re = re.compile("^override")
- classifiers = {rm_re: 'remove',
- dak_re: 'dak',
- arch_re: 'archs',
- override_re: 'override'}
- def unclassified_bugs(self):
- """
- Returns a list of open bugs which have not yet been classified
- by one of our usertags.
- """
- tagged_bugs = bts.get_usertag('ftp.debian.org@packages.debian.org')
- tagged_bugs_ftp = []
- for tags in tagged_bugs.keys():
- tagged_bugs_ftp += tagged_bugs[tags]
- return [bug for bug in bts.get_status(bts.get_bugs("package", "ftp.debian.org"))
- if bug.pending == 'pending' and bug.bug_num not in tagged_bugs_ftp]
- def classify_bug(self, bug):
- """
- if any of our classifiers match, return a newline terminated
- command to set an appropriate usertag, otherwise return an
- empty string
- """
- retval = ""
- for classifier in self.classifiers.keys():
- if classifier.match(bug.subject):
- retval = "usertag %s %s\n" % (bug.bug_num,
- self.classifiers[classifier])
- break
- if retval:
- log.info(retval)
- else:
- log.debug("Unmatched: [%s] %s" % (bug.bug_num, bug.subject))
- return retval
- def email_text(self):
- controls = ""
- bc = BugClassifier()
- try:
- for bug in bc.unclassified_bugs():
- controls += bc.classify_bug(bug)
- return controls
- except:
- log.error("couldn't retrieve bugs from soap interface: %s" % sys.exc_info()[0])
- return None
- def send_email(commands, simulate=False):
- global Cnf
- Subst = {'__COMMANDS__': commands,
- "__DAK_ADDRESS__": Cnf["Dinstall::MyAdminAddress"]}
- bts_mail_message = utils.TemplateSubst(
- Subst, Cnf["Dir::Templates"] + "/bts-categorize")
- if simulate:
- print(bts_mail_message)
- else:
- utils.send_mail(bts_mail_message)
- def main():
- """
- for now, we just dump a list of commands that could be sent for
- control@b.d.o
- """
- global Cnf
- Cnf = utils.get_conf()
- for arg in arguments:
- opt = "BtsCategorize::Options::%s" % arg[1]
- if opt not in Cnf:
- Cnf[opt] = ""
- packages = apt_pkg.parse_commandline(Cnf, arguments, sys.argv)
- Options = Cnf.subtree('BtsCategorize::Options')
- if Options["Help"]:
- usage()
- sys.exit(0)
- if Options["Quiet"]:
- level = logging.ERROR
- elif Options["Verbose"]:
- level = logging.DEBUG
- else:
- level = logging.INFO
- logging.basicConfig(level=level,
- format='%(asctime)s %(levelname)s %(message)s',
- stream=sys.stderr)
- body = BugClassifier().email_text()
- if body:
- send_email(body, Options["Simulate"])
- else:
- log.info("nothing to do")
- if __name__ == '__main__':
- # import doctest
- # doctest.testmod()
- main()
|