Subversion Repositories Scribus

Rev

Blame | Last modification | View Log | RSS feed

#!/usr/bin/env python
"""This script allows command line bug report submission to a Mantis
bug tracking system (http://www.mantisbt.org/)."""

###
# Copyright (c) 2008, Oleksandr Moskalenko
# All rights reserved.
#
#    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 3 of the License, 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, see <http://www.gnu.org/licenses/>.
###

import re, sys
import mechanize
import logging
from mechanize import Browser
from mechanize import CookieJar
from mechanize import LWPCookieJar

##############################################################################
# CONFIGURATION
##############################################################################
# USER CONFIGURATION - edit for your site.
#username = "xxxxxxxx"
#password = "xxxxxxxx"
baseurl = "http://bugs.scribus.net/main_page.php"
title = "Mantis Issue Tracker for Scribus"
filename = "mantisctl.cookies"
handlers = { '' : 0, 'ale' : 20, 'alexandre' : 362, 'avox' : 569, 'cbradney' : 2,
        'christoph_s' : 387, 'deejay1' : 12, 'fschmid' : 3, 'h_a_j_s' : 525,
        'Herm' : 1552, 'jghali' : 649, 'jo-hannes' : 114, 'ltning' : 651,
        'malex' : 73, 'mhanski' : 72, 'nimda' : 6, 'pierremarchand' : 1260,
        'plinnell' : 4, 'psmedley' : 1408, 'rajeev_jsv' : 665, 'ringerc' : 212,
        'sjc' : 28, 'subik' : 8, 'Tsoots' : 22 }
##############################################################################
# SYSTEM CONFIGURATION - you do not usually need to edit this.
severities = { 'feature' : '10', 'trivial': '20', 'text' : '30', 'tweak' : '40', 'minor'
: '50', 'major' : '60', 'crash' : '70', 'block' : '80'}
##############################################################################

class Mantisctl:
    """This class handles Mantis Bug Tracking system data retrieval, bug
    report submission, and control tasks."""

    def __init__(self):
        self.br = Browser()
        self.br.set_handle_redirect(True)
        self.br.set_handle_refresh(True, honor_time=False)
        self.br.set_handle_referer(True)
        (self.opts, self.args) = self._getopts()
        assert self._checkbts()

    def _checkbts(self):
        """ Checks if the URL for the front page could be opened."""
        try:
            self.br.open(self.baseurl)
            if self.br.title() == self.title:
                return True
            else:
                print "Main page does not correspond to the configuration."
            sys.exit(1)
        except:
            print "Cannot open the chosen Mantis Bug Tracker main page."
            sys.exit(1)

    def _usage(self):
        print 50*"#"
        print """\n
Usage: mantisctl.py [Options], version = mantisctl.py 0.1

Options:
  --version             show program's version number and exit
  -h, --help            show this help message and exit
  -T, --test            Test the script
  -L, --list            List the Mantis options
  -r, --report          Report a new bug
  -u USERNAME, --username=USERNAME
                        User name [optional if you set it in the script
                        itself]. [default: None]
  -w PASSWORD, --password=PASSWORD
                        User password [optional if you set it in the script
                        itself]. [default: None]
  -a ASSIGNTO, --assignto=ASSIGNTO
                        Assign to [optional]
  -c CATEGORY, --category=CATEGORY
                        Bug category <mandatory>
  -y SEVERITY, --severity=SEVERITY
                        Bug severity <mandatory>
  -s SUMMARY, --summary=SUMMARY
                        Bug summary <mandatory>
  -d DESCRIPTION, --desc=DESCRIPTION
                        Bug description [optional]
  -p PVERSION, --product=PVERSION
                        Product version <mandatory>
  -t TVERSION, --target=TVERSION
                        Target version [optional]
        """

        sys.exit(1)

    def _getopts(self):
        from optparse import OptionParser
        """This procedure parses options and arguments passed to the program and
    stores them in a dictionary (opts) and a list (args)"""

        try:
            self.title = title
        except:
            sys.exit("You must set the title of the base Mantis BTS page in the configuration section of this script.")
        try:
            self.baseurl = baseurl
        except:
            sys.exit("You must set base URL for Mantis BTS in the configuration section of this script.")
        try:
            self.username = username
        except:
            self.username = "None"
        try:
            self.password = password
        except:
            self.password = "None"
        usage = "%prog [Options], version = %prog 0.1"
        op = OptionParser(usage=usage, version='%prog 0.1')
        op.add_option("-T", "--test", action="store_true", dest="test", default=False, help="Test the script")
        op.add_option("-L", "--list", action="store_true", dest="list", default=False, help="List the Mantis options")
        op.add_option("-r", "--report", action="store_true", dest="report", default=False, help="Report a new bug")
        op.add_option("-u", "--username", dest="username", default=self.username, help="User name [optional if you set it in the script itself]. [default: %default]")
        op.add_option("-w", "--password", dest="password", default=self.password, help="User password [optional if you set it in the script itself]. [default: %default]")
        op.add_option("-a", "--assignto", dest="assignto", help="Assign to [optional]")
        op.add_option("-c", "--category", dest="category", help="Bug category <mandatory>")
        op.add_option("-y", "--severity", dest="severity", help="Bug severity <mandatory>")
        op.add_option("-s", "--summary", dest="summary", help="Bug summary <mandatory>")
        op.add_option("-d", "--desc", dest="description", help="Bug description [optional]")
        op.add_option("-p", "--product", dest="pversion", help="Product version <mandatory>")
        op.add_option("-t", "--target", dest="tversion", help="Target version [optional]")
        try:
            (opts, args) = op.parse_args()
        except:
            self._usage()
        return (opts, args)

    def _printcookies(self):
        for i in self.cj:
            print i

    def _setupcookies(self):
        policy = mechanize.DefaultCookiePolicy(rfc2965=True)
        cj = LWPCookieJar(policy=policy)
        self.br.set_cookiejar(cj)
        self.cj = cj

    def _savecookies(self, filename):
        self.cj.save(filename, ignore_discard = True, ignore_expires = True)

    def _loadcookies(self, filename):
        self.cj.load(filename, ignore_discard = True, ignore_expires = True)

    def _dologin(self):
        self.loginlink = self.br.links(text_regex=re.compile("Login")).next()
        self.br.follow_link(self.loginlink)
        self.br.select_form(name="login_form")
        self.br.form["username"] = self.opts.username
        self.br.form["password"] = self.opts.password
        self.br.submit()

    def _login(self):
        self.filename = filename
        try:
            self._loadcookies(self.filename)
            if not self.cj.as_lwp_str():
                self._dologin()
        except IOError:
            self._dologin()
        self.cj.save(self.filename)

    def _getmantisopts(self):
        self.handlers = handlers
        self.severities = severities
        self.category_control = self.br.form.find_control("category")
        self.category_list = []
        for i in self.category_control.items:
            self.category_list.append(i.name)
        self.severity_control = self.br.form.find_control("severity")
        self.severity_list = []
        for i in self.severity_control.items:
            self.severity_list.append(i.name)
        self.handler_control = self.br.form.find_control("handler_id")
        self.handler_list = []
        for i in self.handler_control.items:
            self.handler_list.append(int(i.name))
        self.pversion_control = self.br.form.find_control("product_version")
        self.pversion_list = []
        for i in self.pversion_control.items:
            self.pversion_list.append(i.name)
        self.tversion_control = self.br.form.find_control("target_version")
        self.tversion_list = []
        for i in self.tversion_control.items:
            self.tversion_list.append(i.name)

    def _checkopts(self):
        if not self.opts.summary:
            sys.exit("You must provide a bug summary!")
        if not self.opts.description:
            self.opts.description = self.opts.summary
        elif len(self.opts.description.strip()) < 1:
            self.opts.description = self.opts.summary
        for i in self.handler_list:
            if i not in self.handlers.values():
                sys.exit("Developer list at the top of this script is not complete.")
        if self.opts.assignto and len(self.opts.assignto) > 0:
            if self.opts.assignto not in self.handlers.keys():
                print "You must specify a developer to assign bug to from the following list: \n", self.handlers.keys()
                sys.exit(1)
            else:
                self.handler = str(self.handlers[self.opts.assignto])
        else:
            self.handler = '0'
        if not self.opts.category:
            print "You must specify a category from the following list: \n", self.category_list
            sys.exit(1)
        else:
            if self.opts.category in self.category_list:
                pass
            else:
                print "Your category is not in the list: \n", self.category_list
                sys.exit(1)
        for i in self.severity_list:
            if i not in self.severities.values():
                sys.exit("Severity list at the top of this script is not complete.")
        if not self.opts.severity:
            print "You must specify a severity from the following list: \n", self.severities.keys()
            sys.exit(1)
        else:
            if self.opts.severity in self.severities.keys():
                self.severity = self.severities[self.opts.severity]
            else:
                print "Your severity is not in the list: \n", self.severities.keys()
                sys.exit(1)
        if not self.opts.pversion:
            print "You must specify a product version from the following list: \n", self.pversion_list
            sys.exit(1)
        else:
            if self.opts.pversion in self.pversion_list:
                pass
            else:
                print "Your product version is not in the list: \n", self.pversion_list
                sys.exit(1)
        if self.opts.tversion:
            if self.opts.tversion in self.tversion_list:
                pass
            else:
                print "Your target version is not in the list: \n", self.tversion_list
                sys.exit(1)

    def _setupreportform(self):
        self._getmantisopts()
        if self.opts.list:
            print "Severities: \n", "\t", self.severities.keys(), "\n"
            print "Categories: \n", "\t", self.category_list, "\n"
            print "Developers: \n", "\t", self.handlers.keys(), "\n"
            print "Product Versions: \n", "\t", self.pversion_list, "\n"
            sys.exit(0)
        self._checkopts()
        self.br.form["category"] = [self.opts.category]
        self.br.form["severity"] = [self.severity]
        self.br.form["handler_id"] = [self.handler]
        self.br.form["product_version"] = [self.opts.pversion]
        if self.opts.tversion:
            self.br.form["target_version"] = [self.opts.tversion]
        self.br.form["summary"] = self.opts.summary
        self.br.form["description"] = self.opts.description

    def reportbug(self):
        reportlink = self.br.links(text_regex=re.compile("Report Issue")).next()
        self.br.follow_link(reportlink)
        self.br.select_form(name="report_bug_form")
        self._setupreportform()

    def doreportbug(self):
        self.reportbug()
        try:
            self.br.submit()
        except:
            pass
        self.br.close()
        print "\nBug report submission appears to be successful! The following data have been submitted:\n"
        print "\tCategory: \t\t%s" % self.opts.category
        print "\tSeverity: \t\t%s" % self.opts.severity
        print "\tAssigned To: \t\t%s" % self.opts.assignto
        print "\tProduct Version: \t%s" % self.opts.pversion
        print "\tTarget Version: \t%s" % self.opts.tversion
        print "\tSummary: \t\t%s" % self.opts.summary
        print "\tDescription: \t\t%s" % self.opts.description
        sys.exit(0)

    def _checkcredentials(self):
        if self.opts.username == 'None':
            print "\nUsername is not specified either in the script configuration or on the command line."
            self._usage()
        if self.opts.password == 'None':
            print "\nPassword is not specified either in the script or on the command line."
            self._usage()

    def dorun(self):
        self._checkcredentials()
        self._setupcookies()
        self._login()
        if self.opts.list:
            print "Listing the Mantis options...\n"
            self.reportbug()
        if self.opts.test:
            print "Testing the script...",
            self.reportbug()
            print "everything seems to be fine."
            sys.exit(0)
        if self.opts.report:
            self.doreportbug()

if __name__=='__main__':
    if len(sys.argv) == 1:
        sys.argv.append("--help")
    else:
        browser = Mantisctl()
        browser.dorun()
# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: