]> git.decadent.org.uk Git - dak.git/blob - dak/bts_categorize.py
move bts_categorize into dak, send email
[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 def usage():
26     print """
27 SYNOPSIS
28     dak bts-categorize [options] command
29
30 COMMANDS
31     list-categories
32         List the currently defind categorizations for bugs
33
34     categorize
35         Find the bugs filed against ftp.debian.org which have no usertag
36         and see if we can categorize the bug by adding a usertag by matching
37         the subject against a list of regexps.
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 import sys
64 import re
65 import logging
66 log = logging.getLogger()
67
68 import apt_pkg
69 from daklib import utils
70 from btsutils.debbugs import debbugs
71
72 class BugClassifier(object):
73     """
74     classify bugs using usertags based on the bug subject lines
75
76     >>> BugClassifier.rm_re.match( "RM: asdf" ) != None
77     True
78     >>> BugClassifier.rm_re.match( "[dak] Packages.diff/Index broken" ) != None
79     False
80     >>> BugClassifier.dak_re.match( "[dak] Packages.diff/Index broken" ) != None
81     True
82     """
83     rm_re = re.compile( "^RM" )
84     dak_re = re.compile( "^\[dak\]" )
85     arch_re = re.compile( "^\[Architectures\]" )
86
87     classifiers = { rm_re: 'remove',
88                     dak_re: 'dak',
89                     arch_re: 'archs'}
90
91     def __init__( self ):
92         self.bts = debbugs()
93         self.bts.setUsers(['ftp.debian.org@packages.debian.org'])
94
95
96     def unclassified_bugs(self):
97         """
98         Returns a list of open bugs which have not yet been classified
99         by one of our usertags.
100         """
101         return [ bug for bug in self.bts.query("pkg:ftp.debian.org") \
102                      if bug.status=='pending' and not bug.usertags ]
103
104
105     def classify_bug(self, bug):
106         """
107         if any of our classifiers match, return a newline terminated
108         command to set an appropriate usertag, otherwise return an
109         empty string
110         """
111         retval = ""
112
113         for classifier in self.classifiers.keys():
114             if classifier.match(bug.summary):
115                 retval = "usertag %s %s\n" % (bug.bug,
116                                             self.classifiers[classifier])
117                 break
118
119         if retval:
120             log.info(retval)
121         else:
122             log.debug("Unmatched: [%s] %s" % (bug.bug, bug.summary))
123
124         return retval
125
126     def email_text(self):
127         controls = 'user ftp.debian.org@packages.debian.org\n'
128
129         bc = BugClassifier()
130         for bug in bc.unclassified_bugs():
131             controls += bc.classify_bug(bug)
132
133         return controls
134
135
136 import smtplib
137 import email.Message
138
139 def send_email(body):
140     to = 'control@bugs.debian.org'
141     sender = 'ak@ries.debian.org'
142     message = email.Message.Message()
143     message["To"] = to
144     message["From"] = sender
145     message.set_payload(body)
146     mailServer = smtplib.SMTP('localhost')
147     mailServer.sendmail(sender, to, message.as_string())
148     mailServer.quit()
149
150 def main():
151     """
152     for now, we just dump a list of commands that could be sent for
153     control@b.d.o
154     """
155     global Cnf
156     Cnf = utils.get_conf()
157
158     for arg in arguments:
159         opt = "BtsCategorize::Options::%s" % arg[1]
160         if not Cnf.has_key(opt):
161             Cnf[opt] = ""
162
163     packages = apt_pkg.ParseCommandLine(Cnf, arguments, sys.argv)
164     Options = Cnf.SubTree('BtsCategorize::Options')
165
166     if Options["Help"]:
167         usage()
168         sys.exit( 0 )
169
170     if Options["Quiet"]:
171         level=logging.ERROR
172
173     elif Options["Verbose"]:
174         level=logging.DEBUG
175
176     else:
177         level=logging.INFO
178
179     logging.basicConfig( level=level,
180                          format='%(asctime)s %(levelname)s %(message)s',
181                          stream = sys.stderr )
182
183     body = BugClassifier().email_text()
184
185     if Options["Simulate"]:
186         print body
187
188     else:
189         send_email(body)
190
191
192 if __name__ == '__main__':
193 #    import doctest
194 #    doctest.testmod()
195     main()