]> git.decadent.org.uk Git - dak.git/blob - dak/bts_categorize.py
Use dak's facility for sending email. Add bts-categorize to cron.dinstall
[dak.git] / dak / bts_categorize.py
1 #!/usr/bin/python
2
3 #  bts -- manage bugs filed against ftp.debian.org
4 #
5 #  Copyright 2009 Mike O'Connor <stew@vireo.org>
6 #
7 #  This program is free software; you can redistribute it and/or modify it
8 #  under the terms of the GNU General Public License as published by the
9 #  Free Software Foundation; either version 2, or (at your option) any
10 #  later version.
11 #
12 #  This program is distributed in the hope that it will be useful,
13 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #  GNU General Public License for more details.
16 #
17 #  You should have received a copy of the GNU General Public License
18 #  along with this program; if not, write to the Free Software
19 #  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20 #  USA.
21
22 ################################################################################
23 ################################################################################
24
25 import sys
26 import re
27 import logging
28 log = logging.getLogger()
29
30 import apt_pkg
31 from daklib import utils
32 from btsutils.debbugs import debbugs
33
34 def usage():
35     print """
36 SYNOPSIS
37     dak bts-categorize [options]
38
39 OPTIONS
40     -s
41     --simulate
42         Don't send email, instead output the lines that would be sent to
43         control@b.d.o.
44
45     -v
46     --verbose
47         Print more informational log messages
48
49     -q
50     --quiet
51         Suppress informational messages
52
53     -h
54     --help
55         Print this documentation.
56 """
57
58 arguments = [('s','simulate','BtsCategorize::Options::Simulate'),
59              ('v', 'verbose', 'BtsCategorize::Options::Verbose'),
60              ('q', 'quiet', 'BtsCategorize::Options::Quiet'),
61              ('h', 'help', 'BtsCategorize::Options::Help')]
62
63 class BugClassifier(object):
64     """
65     classify bugs using usertags based on the bug subject lines
66
67     >>> BugClassifier.rm_re.match( "RM: asdf" ) != None
68     True
69     >>> BugClassifier.rm_re.match( "[dak] Packages.diff/Index broken" ) != None
70     False
71     >>> BugClassifier.dak_re.match( "[dak] Packages.diff/Index broken" ) != None
72     True
73     """
74     rm_re = re.compile( "^RM" )
75     dak_re = re.compile( "^\[dak\]" )
76     arch_re = re.compile( "^\[Architectures\]" )
77
78     classifiers = { rm_re: 'remove',
79                     dak_re: 'dak',
80                     arch_re: 'archs'}
81
82     def __init__( self ):
83         self.bts = debbugs()
84         self.bts.setUsers(['ftp.debian.org@packages.debian.org'])
85
86
87     def unclassified_bugs(self):
88         """
89         Returns a list of open bugs which have not yet been classified
90         by one of our usertags.
91         """
92         return [ bug for bug in self.bts.query("pkg:ftp.debian.org") \
93                      if bug.status=='pending' and not bug.usertags ]
94
95
96     def classify_bug(self, bug):
97         """
98         if any of our classifiers match, return a newline terminated
99         command to set an appropriate usertag, otherwise return an
100         empty string
101         """
102         retval = ""
103
104         for classifier in self.classifiers.keys():
105             if classifier.match(bug.summary):
106                 retval = "usertag %s %s\n" % (bug.bug,
107                                             self.classifiers[classifier])
108                 break
109
110         if retval:
111             log.info(retval)
112         else:
113             log.debug("Unmatched: [%s] %s" % (bug.bug, bug.summary))
114
115         return retval
116
117     def email_text(self):
118         controls = ""
119
120         bc = BugClassifier()
121         for bug in bc.unclassified_bugs():
122             controls += bc.classify_bug(bug)
123
124         return controls
125
126 import smtplib
127 import email.Message
128
129 def send_email(commands, simulate):
130     global Cnf
131
132     Subst = {'__COMMANDS__' : commands,
133              "__DAK_ADDRESS__": Cnf["Dinstall::MyAdminAddress"]}
134
135     bts_mail_message = utils.TemplateSubst(
136         Subst,Cnf["Dir::Templates"]+"/bts-categorize")
137
138     if simulate:
139         print bts_mail_message
140     else:
141         utils.send_mail( bts_mail_message )
142
143 def main():
144     """
145     for now, we just dump a list of commands that could be sent for
146     control@b.d.o
147     """
148     global Cnf
149     Cnf = utils.get_conf()
150
151     for arg in arguments:
152         opt = "BtsCategorize::Options::%s" % arg[1]
153         if not Cnf.has_key(opt):
154             Cnf[opt] = ""
155
156     packages = apt_pkg.ParseCommandLine(Cnf, arguments, sys.argv)
157     Options = Cnf.SubTree('BtsCategorize::Options')
158
159     if Options["Help"]:
160         usage()
161         sys.exit( 0 )
162
163     if Options["Quiet"]:
164         level=logging.ERROR
165
166     elif Options["Verbose"]:
167         level=logging.DEBUG
168
169     else:
170         level=logging.INFO
171
172     logging.basicConfig( level=level,
173                          format='%(asctime)s %(levelname)s %(message)s',
174                          stream = sys.stderr )
175
176     body = BugClassifier().email_text()
177
178     if body:
179         send_email(body, Options["Simulate"])
180
181     else:
182         log.info( "nothing to do" )
183
184
185 if __name__ == '__main__':
186 #    import doctest
187 #    doctest.testmod()
188     main()