Subversion Repositories Scribus

Rev

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