Subversion Repositories Scribus

Rev

Rev 12491 | Rev 12494 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
12491 malex 1
#!/usr/bin/env python
2
"""This script allows command line bug report submission to a Mantis
3
bug tracking system (http://www.mantisbt.org/)."""
4
###
5
# Copyright (c) 2008, Oleksandr Moskalenko
6
# All rights reserved.
7
#
8
#    This program is free software: you can redistribute it and/or modify
9
#    it under the terms of the GNU General Public License as published by
10
#    the Free Software Foundation, either version 3 of the License, or
11
#    (at your option) any later version.
12
#
13
#    This program is distributed in the hope that it will be useful,
14
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
#    GNU General Public License for more details.
17
#
18
#    You should have received a copy of the GNU General Public License
19
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
###
12493 malex 21
# Changelog:
22
# Version:
23
#   0.1: Initial release - bug reporting to Mantis is working.
24
#   0.2:
25
#       - Added a confirmation message and an option to override it.
26
#       - Fixed a bug in the option parsing method that would not correctly
27
#         return options when script is run with no arguments.
28
###
12491 malex 29
 
30
import re, sys
31
import mechanize
32
import logging
33
from mechanize import Browser
34
from mechanize import CookieJar
35
from mechanize import LWPCookieJar
36
 
37
##############################################################################
38
# CONFIGURATION
39
##############################################################################
40
# USER CONFIGURATION - edit for your site.
41
#username = "xxxxxxxx"
42
#password = "xxxxxxxx"
43
baseurl = "http://bugs.scribus.net/main_page.php"
44
title = "Mantis Issue Tracker for Scribus"
45
filename = "mantisctl.cookies"
46
handlers = { '' : 0, 'ale' : 20, 'alexandre' : 362, 'avox' : 569, 'cbradney' : 2,
47
        'christoph_s' : 387, 'deejay1' : 12, 'fschmid' : 3, 'h_a_j_s' : 525,
48
        'Herm' : 1552, 'jghali' : 649, 'jo-hannes' : 114, 'ltning' : 651,
49
        'malex' : 73, 'mhanski' : 72, 'nimda' : 6, 'pierremarchand' : 1260,
50
        'plinnell' : 4, 'psmedley' : 1408, 'rajeev_jsv' : 665, 'ringerc' : 212,
51
        'sjc' : 28, 'subik' : 8, 'Tsoots' : 22 }
52
##############################################################################
53
# SYSTEM CONFIGURATION - you do not usually need to edit this.
54
severities = { 'feature' : '10', 'trivial': '20', 'text' : '30', 'tweak' : '40', 'minor'
55
: '50', 'major' : '60', 'crash' : '70', 'block' : '80'}
56
##############################################################################
57
 
58
class Mantisctl:
59
    """This class handles Mantis Bug Tracking system data retrieval, bug
60
    report submission, and control tasks."""
61
    def __init__(self):
62
        self.br = Browser()
63
        self.br.set_handle_redirect(True)
64
        self.br.set_handle_refresh(True, honor_time=False)
65
        self.br.set_handle_referer(True)
66
        (self.opts, self.args) = self._getopts()
67
        assert self._checkbts()
68
 
12493 malex 69
    def _askconfirm(self):
70
        print "\nYou will submit a bug report with the following data:\n"
71
        self._printdata()
72
        yes = ['y', 'Y']
73
        var = raw_input("Press 'y' to submit the report or any other key to abort and hit ENTER: ")
74
        print var
75
        if var in yes:
76
            print "Submitting your bug report..."
77
        else:
78
            print "Exiting without submitting the report..."
79
            sys.exit(0)
80
 
12491 malex 81
    def _checkbts(self):
82
        """ Checks if the URL for the front page could be opened."""
83
        try:
84
            self.br.open(self.baseurl)
85
            if self.br.title() == self.title:
86
                return True
87
            else:
88
                print "Main page does not correspond to the configuration."
89
            sys.exit(1)
90
        except:
91
            print "Cannot open the chosen Mantis Bug Tracker main page."
92
            sys.exit(1)
93
 
94
    def _usage(self):
12493 malex 95
        print "\n", 78*"#"
12491 malex 96
        print """\n
12493 malex 97
Usage: mantisctl.py [Options], version = mantisctl.py 0.2
12491 malex 98
 
99
Options:
100
  --version             show program's version number and exit
101
  -h, --help            show this help message and exit
102
  -T, --test            Test the script
103
  -L, --list            List the Mantis options
104
  -r, --report          Report a new bug
12493 malex 105
  -n, --noconfirm       Do not ask for confirmation before submitting a report
12491 malex 106
  -u USERNAME, --username=USERNAME
107
                        User name [optional if you set it in the script
108
                        itself]. [default: None]
109
  -w PASSWORD, --password=PASSWORD
110
                        User password [optional if you set it in the script
111
                        itself]. [default: None]
112
  -a ASSIGNTO, --assignto=ASSIGNTO
113
                        Assign to [optional]
114
  -c CATEGORY, --category=CATEGORY
115
                        Bug category <mandatory>
116
  -y SEVERITY, --severity=SEVERITY
117
                        Bug severity <mandatory>
118
  -s SUMMARY, --summary=SUMMARY
119
                        Bug summary <mandatory>
120
  -d DESCRIPTION, --desc=DESCRIPTION
121
                        Bug description [optional]
122
  -p PVERSION, --product=PVERSION
123
                        Product version <mandatory>
124
  -t TVERSION, --target=TVERSION
125
                        Target version [optional]
126
        """
127
        sys.exit(1)
128
 
129
    def _getopts(self):
130
        from optparse import OptionParser
12493 malex 131
        """This procedure parses options and arguments passed to the program
132
        and stores them in a dictionary (opts) and a list (args)"""
12491 malex 133
        try:
134
            self.title = title
135
        except:
136
            sys.exit("You must set the title of the base Mantis BTS page in the configuration section of this script.")
137
        try:
138
            self.baseurl = baseurl
139
        except:
140
            sys.exit("You must set base URL for Mantis BTS in the configuration section of this script.")
141
        try:
142
            self.username = username
143
        except:
144
            self.username = "None"
145
        try:
146
            self.password = password
147
        except:
148
            self.password = "None"
12493 malex 149
        usage = "%prog [Options], version = %prog 0.2"
150
        op = OptionParser(usage=usage, version='%prog 0.2')
12491 malex 151
        op.add_option("-T", "--test", action="store_true", dest="test", default=False, help="Test the script")
152
        op.add_option("-L", "--list", action="store_true", dest="list", default=False, help="List the Mantis options")
153
        op.add_option("-r", "--report", action="store_true", dest="report", default=False, help="Report a new bug")
12493 malex 154
        op.add_option("-n", "--noconfirm", action="store_true", dest="noconfirm", default=False, help="Do not ask for confirmation before submitting a report")
12491 malex 155
        op.add_option("-u", "--username", dest="username", default=self.username, help="User name [optional if you set it in the script itself]. [default: %default]")
156
        op.add_option("-w", "--password", dest="password", default=self.password, help="User password [optional if you set it in the script itself]. [default: %default]")
157
        op.add_option("-a", "--assignto", dest="assignto", help="Assign to [optional]")
158
        op.add_option("-c", "--category", dest="category", help="Bug category <mandatory>")
159
        op.add_option("-y", "--severity", dest="severity", help="Bug severity <mandatory>")
160
        op.add_option("-s", "--summary", dest="summary", help="Bug summary <mandatory>")
161
        op.add_option("-d", "--desc", dest="description", help="Bug description [optional]")
162
        op.add_option("-p", "--product", dest="pversion", help="Product version <mandatory>")
163
        op.add_option("-t", "--target", dest="tversion", help="Target version [optional]")
12493 malex 164
        return op.parse_args()
12491 malex 165
 
166
    def _printcookies(self):
167
        for i in self.cj:
168
            print i
169
 
170
    def _setupcookies(self):
171
        policy = mechanize.DefaultCookiePolicy(rfc2965=True)
172
        cj = LWPCookieJar(policy=policy)
173
        self.br.set_cookiejar(cj)
174
        self.cj = cj
175
 
176
    def _savecookies(self, filename):
177
        self.cj.save(filename, ignore_discard = True, ignore_expires = True)
178
 
179
    def _loadcookies(self, filename):
180
        self.cj.load(filename, ignore_discard = True, ignore_expires = True)
181
 
182
    def _dologin(self):
183
        self.loginlink = self.br.links(text_regex=re.compile("Login")).next()
184
        self.br.follow_link(self.loginlink)
185
        self.br.select_form(name="login_form")
186
        self.br.form["username"] = self.opts.username
187
        self.br.form["password"] = self.opts.password
188
        self.br.submit()
189
 
190
    def _login(self):
191
        self.filename = filename
192
        try:
193
            self._loadcookies(self.filename)
194
            if not self.cj.as_lwp_str():
195
                self._dologin()
196
        except IOError:
197
            self._dologin()
198
        self.cj.save(self.filename)
199
 
200
    def _getmantisopts(self):
201
        self.handlers = handlers
202
        self.severities = severities
203
        self.category_control = self.br.form.find_control("category")
204
        self.category_list = []
205
        for i in self.category_control.items:
206
            self.category_list.append(i.name)
207
        self.severity_control = self.br.form.find_control("severity")
208
        self.severity_list = []
209
        for i in self.severity_control.items:
210
            self.severity_list.append(i.name)
211
        self.handler_control = self.br.form.find_control("handler_id")
212
        self.handler_list = []
213
        for i in self.handler_control.items:
214
            self.handler_list.append(int(i.name))
215
        self.pversion_control = self.br.form.find_control("product_version")
216
        self.pversion_list = []
217
        for i in self.pversion_control.items:
218
            self.pversion_list.append(i.name)
219
        self.tversion_control = self.br.form.find_control("target_version")
220
        self.tversion_list = []
221
        for i in self.tversion_control.items:
222
            self.tversion_list.append(i.name)
223
 
224
    def _checkopts(self):
225
        if not self.opts.summary:
226
            sys.exit("You must provide a bug summary!")
227
        if not self.opts.description:
228
            self.opts.description = self.opts.summary
229
        elif len(self.opts.description.strip()) < 1:
230
            self.opts.description = self.opts.summary
231
        for i in self.handler_list:
232
            if i not in self.handlers.values():
233
                sys.exit("Developer list at the top of this script is not complete.")
234
        if self.opts.assignto and len(self.opts.assignto) > 0:
235
            if self.opts.assignto not in self.handlers.keys():
236
                print "You must specify a developer to assign bug to from the following list: \n", self.handlers.keys()
237
                sys.exit(1)
238
            else:
239
                self.handler = str(self.handlers[self.opts.assignto])
240
        else:
241
            self.handler = '0'
242
        if not self.opts.category:
243
            print "You must specify a category from the following list: \n", self.category_list
244
            sys.exit(1)
245
        else:
246
            if self.opts.category in self.category_list:
247
                pass
248
            else:
249
                print "Your category is not in the list: \n", self.category_list
250
                sys.exit(1)
251
        for i in self.severity_list:
252
            if i not in self.severities.values():
253
                sys.exit("Severity list at the top of this script is not complete.")
254
        if not self.opts.severity:
255
            print "You must specify a severity from the following list: \n", self.severities.keys()
256
            sys.exit(1)
257
        else:
258
            if self.opts.severity in self.severities.keys():
259
                self.severity = self.severities[self.opts.severity]
260
            else:
261
                print "Your severity is not in the list: \n", self.severities.keys()
262
                sys.exit(1)
263
        if not self.opts.pversion:
264
            print "You must specify a product version from the following list: \n", self.pversion_list
265
            sys.exit(1)
266
        else:
267
            if self.opts.pversion in self.pversion_list:
268
                pass
269
            else:
270
                print "Your product version is not in the list: \n", self.pversion_list
271
                sys.exit(1)
272
        if self.opts.tversion:
273
            if self.opts.tversion in self.tversion_list:
274
                pass
275
            else:
276
                print "Your target version is not in the list: \n", self.tversion_list
277
                sys.exit(1)
278
 
279
    def _setupreportform(self):
280
        self._getmantisopts()
281
        if self.opts.list:
282
            print "Severities: \n", "\t", self.severities.keys(), "\n"
283
            print "Categories: \n", "\t", self.category_list, "\n"
284
            print "Developers: \n", "\t", self.handlers.keys(), "\n"
285
            print "Product Versions: \n", "\t", self.pversion_list, "\n"
286
            sys.exit(0)
287
        self._checkopts()
288
        self.br.form["category"] = [self.opts.category]
289
        self.br.form["severity"] = [self.severity]
290
        self.br.form["handler_id"] = [self.handler]
291
        self.br.form["product_version"] = [self.opts.pversion]
292
        if self.opts.tversion:
293
            self.br.form["target_version"] = [self.opts.tversion]
294
        self.br.form["summary"] = self.opts.summary
295
        self.br.form["description"] = self.opts.description
296
 
297
    def reportbug(self):
298
        reportlink = self.br.links(text_regex=re.compile("Report Issue")).next()
299
        self.br.follow_link(reportlink)
300
        self.br.select_form(name="report_bug_form")
301
        self._setupreportform()
302
 
12493 malex 303
    def _printdata(self):
304
        print "\tCategory: \t\t%s" % self.opts.category
305
        print "\tSeverity: \t\t%s" % self.opts.severity
306
        print "\tAssigned To: \t\t%s" % self.opts.assignto
307
        print "\tProduct Version: \t%s" % self.opts.pversion
308
        print "\tTarget Version: \t%s" % self.opts.tversion
309
        print "\tSummary: \t\t%s" % self.opts.summary
310
        print "\tDescription: \t\t%s" % self.opts.description
311
 
12491 malex 312
    def doreportbug(self):
313
        self.reportbug()
12493 malex 314
        if not self.opts.noconfirm:
315
            self._askconfirm()
12491 malex 316
        try:
317
            self.br.submit()
318
        except:
319
            pass
320
        self.br.close()
321
        print "\nBug report submission appears to be successful! The following data have been submitted:\n"
12493 malex 322
        self._printdata()
12491 malex 323
        sys.exit(0)
324
 
325
    def _checkcredentials(self):
326
        if self.opts.username == 'None':
327
            print "\nUsername is not specified either in the script configuration or on the command line."
328
            self._usage()
329
        if self.opts.password == 'None':
330
            print "\nPassword is not specified either in the script or on the command line."
331
            self._usage()
332
 
333
    def dorun(self):
334
        self._checkcredentials()
335
        self._setupcookies()
336
        self._login()
337
        if self.opts.list:
338
            print "Listing the Mantis options...\n"
339
            self.reportbug()
340
        if self.opts.test:
341
            print "Testing the script...",
342
            self.reportbug()
343
            print "everything seems to be fine."
344
            sys.exit(0)
345
        if self.opts.report:
346
            self.doreportbug()
347
 
348
if __name__=='__main__':
349
    if len(sys.argv) == 1:
350
        sys.argv.append("--help")
12493 malex 351
        browser = Mantisctl()
12491 malex 352
    else:
353
        browser = Mantisctl()
354
        browser.dorun()
355
# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: