Bugtracker: Add Python 3 support (by Mattia Rizzolo)

This commit is contained in:
Krytarik Raido
2018-05-16 23:45:04 +02:00
parent a1d7ef03d0
commit 45ae48b53a
2 changed files with 94 additions and 80 deletions

View File

@ -2,6 +2,7 @@
### ###
# Copyright (c) 2005-2007 Dennis Kaarsemaker # Copyright (c) 2005-2007 Dennis Kaarsemaker
# Copyright (c) 2008-2010 Terence Simpson # Copyright (c) 2008-2010 Terence Simpson
# Copyright (c) 2017- Krytarik Raido
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of version 2 of the GNU General Public License as # it under the terms of version 2 of the GNU General Public License as
@ -21,19 +22,22 @@ This plugin will display bug information when requested.
import supybot import supybot
import supybot.world as world import supybot.world as world
__version__ = "2.5.1" from imp import reload
__author__ = supybot.Author("Terence Simpson", "tsimpson", "tsimpson@ubuntu.com")
__contributors__ = {
supybot.Author("Dennis Kaarsemaker","Seveas","dennis@kaarsemaker.net"): ['Original Author']
}
__url__ = 'https://launchpad.net/ubuntu-bots/'
import config __version__ = "2.6.0"
__author__ = supybot.Author("Krytarik Raido", "krytarik", "krytarik@tuxgarage.com")
__contributors__ = {
supybot.Author("Dennis Kaarsemaker", "Seveas", "dennis@kaarsemaker.net"): ['Original Author'],
supybot.Author("Terence Simpson", "tsimpson", "tsimpson@ubuntu.com"): ['Original Author']
}
__url__ = 'https://launchpad.net/ubuntu-bots'
from . import config
reload(config) reload(config)
import plugin from . import plugin
reload(plugin) reload(plugin)
if world.testing: if world.testing:
import test from . import test
Class = plugin.Class Class = plugin.Class
configure = config.configure configure = config.configure

View File

@ -2,6 +2,7 @@
### ###
# Copyright (c) 2005-2007 Dennis Kaarsemaker # Copyright (c) 2005-2007 Dennis Kaarsemaker
# Copyright (c) 2008-2010 Terence Simpson # Copyright (c) 2008-2010 Terence Simpson
# Copyright (c) 2017- Krytarik Raido
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of version 2 of the GNU General Public License as # it under the terms of version 2 of the GNU General Public License as
@ -24,12 +25,15 @@ import supybot.registry as registry
import supybot.schedule as schedule import supybot.schedule as schedule
import supybot.log as supylog import supybot.log as supylog
from functools import cmp_to_key
#import imaplib #import imaplib
import re, os, time, commands import re, os, sys, time, subprocess
import xml.dom.minidom as minidom import xml.dom.minidom as minidom
from htmlentitydefs import entitydefs as entities from html.entities import entitydefs as entities
import email.FeedParser from email.parser import FeedParser
import SOAPpy if sys.version_info < (3,0):
import SOAPpy
# All the words below will be censored when reporting bug information # All the words below will be censored when reporting bug information
bad_words = set(["fuck","fuk","fucking","fuking","fukin","fuckin","fucked","fuked","fucker","shit","cunt","bastard","nazi","nigger","nigga","cock","bitches","bitch"]) bad_words = set(["fuck","fuk","fucking","fuking","fukin","fuckin","fucked","fuked","fucker","shit","cunt","bastard","nazi","nigger","nigga","cock","bitches","bitch"])
@ -52,7 +56,7 @@ def registerBugtracker(name, url='', description='', trackertype=''):
if description: if description:
DESC.setValue(description) DESC.setValue(description)
if trackertype: if trackertype:
if defined_bugtrackers.has_key(trackertype.lower()): if trackertype.lower() in defined_bugtrackers:
TRACKERTYPE.setValue(trackertype.lower()) TRACKERTYPE.setValue(trackertype.lower())
else: else:
raise BugtrackerError("Unknown trackertype: %s" % trackertype) raise BugtrackerError("Unknown trackertype: %s" % trackertype)
@ -64,7 +68,7 @@ def _getnodetxt(node):
if childnode.nodeType == childnode.TEXT_NODE: if childnode.nodeType == childnode.TEXT_NODE:
L.append(childnode.data) L.append(childnode.data)
if not L: if not L:
raise ValueError, "No text nodes" raise ValueError("No text nodes")
val = ''.join(L) val = ''.join(L)
if node.hasAttribute('encoding'): if node.hasAttribute('encoding'):
encoding = node.getAttribute('encoding') encoding = node.getAttribute('encoding')
@ -103,11 +107,11 @@ class Bugtracker(callbacks.PluginRegexp):
for name in self.registryValue('bugtrackers'): for name in self.registryValue('bugtrackers'):
registerBugtracker(name) registerBugtracker(name)
group = self.registryValue('bugtrackers.%s' % name.replace('.','\\.'), value=False) group = self.registryValue('bugtrackers.%s' % name.replace('.','\\.'), value=False)
if group.trackertype() in defined_bugtrackers.keys(): if group.trackertype() in defined_bugtrackers:
self.db[name] = defined_bugtrackers[group.trackertype()](name, group.url(), group.description()) self.db[name] = defined_bugtrackers[group.trackertype()](name, group.url(), group.description())
else: else:
self.log.warning("Bugtracker: Unknown trackertype: %s (%s)" % (group.trackertype(), name)) self.log.warning("Bugtracker: Unknown trackertype: %s (%s)" % (group.trackertype(), name))
self.shorthand = utils.abbrev(self.db.keys()) self.shorthand = utils.abbrev(list(self.db.keys()))
self.shown = {} self.shown = {}
# # Schedule bug reporting # # Schedule bug reporting
@ -134,7 +138,7 @@ class Bugtracker(callbacks.PluginRegexp):
def is_ok(self, channel, tracker, bug): def is_ok(self, channel, tracker, bug):
'''Flood/repeat protection''' '''Flood/repeat protection'''
now = time.time() now = time.time()
for k in self.shown.keys(): for k in list(self.shown.keys()):
if self.shown[k] < now - self.registryValue('repeatdelay', channel): if self.shown[k] < now - self.registryValue('repeatdelay', channel):
self.shown.pop(k) self.shown.pop(k)
if (channel, tracker, bug) not in self.shown: if (channel, tracker, bug) not in self.shown:
@ -171,7 +175,7 @@ class Bugtracker(callbacks.PluginRegexp):
# # Read all new mail # # Read all new mail
# for m in new_mail: # for m in new_mail:
# msg = sc.fetch(m, 'RFC822')[1][0][1] # msg = sc.fetch(m, 'RFC822')[1][0][1]
# fp = email.FeedParser.FeedParser() # fp = FeedParser()
# sc.store(m, '+FLAGS', "(\Deleted)") # Mark message deleted so we don't have to process it again # sc.store(m, '+FLAGS', "(\Deleted)") # Mark message deleted so we don't have to process it again
# fp.feed(msg) # fp.feed(msg)
# bug = fp.close() # bug = fp.close()
@ -258,7 +262,7 @@ class Bugtracker(callbacks.PluginRegexp):
irc.error("Bugtrackers of type '%s' are not understood" % trackertype) irc.error("Bugtrackers of type '%s' are not understood" % trackertype)
return return
registerBugtracker(name, url, description, trackertype) registerBugtracker(name, url, description, trackertype)
self.shorthand = utils.abbrev(self.db.keys()) self.shorthand = utils.abbrev(list(self.db.keys()))
irc.replySuccess() irc.replySuccess()
add = wrap(add, [('checkCapability', 'admin'), 'something', 'something', 'url', additional('text')]) add = wrap(add, [('checkCapability', 'admin'), 'something', 'something', 'url', additional('text')])
@ -272,7 +276,7 @@ class Bugtracker(callbacks.PluginRegexp):
name = self.shorthand[name.lower()] name = self.shorthand[name.lower()]
del self.db[name] del self.db[name]
self.registryValue('bugtrackers').remove(name) self.registryValue('bugtrackers').remove(name)
self.shorthand = utils.abbrev(self.db.keys()) self.shorthand = utils.abbrev(list(self.db.keys()))
irc.replySuccess() irc.replySuccess()
except KeyError: except KeyError:
s = self.registryValue('replyNoBugtracker', ircutils.isChannel(msg.args[0]) and msg.args[0] or None) s = self.registryValue('replyNoBugtracker', ircutils.isChannel(msg.args[0]) and msg.args[0] or None)
@ -294,7 +298,7 @@ class Bugtracker(callbacks.PluginRegexp):
registerBugtracker(newname, group.url(), d, group.trackertype()) registerBugtracker(newname, group.url(), d, group.trackertype())
del self.db[name] del self.db[name]
self.registryValue('bugtrackers').remove(name) self.registryValue('bugtrackers').remove(name)
self.shorthand = utils.abbrev(self.db.keys()) self.shorthand = utils.abbrev(list(self.db.keys()))
irc.replySuccess() irc.replySuccess()
except KeyError: except KeyError:
s = self.registryValue('replyNoBugtracker', ircutils.isChannel(msg.args[0]) and msg.args[0] or None) s = self.registryValue('replyNoBugtracker', ircutils.isChannel(msg.args[0]) and msg.args[0] or None)
@ -319,7 +323,7 @@ class Bugtracker(callbacks.PluginRegexp):
irc.error(s % name) irc.error(s % name)
else: else:
if self.db: if self.db:
L = self.db.keys() L = list(self.db.keys())
L.sort() L.sort()
irc.reply(utils.str.commaAndify(L)) irc.reply(utils.str.commaAndify(L))
else: else:
@ -355,7 +359,7 @@ class Bugtracker(callbacks.PluginRegexp):
# filter out bug number that are 4 numbers, start with '1' and end in '04' or '10 # filter out bug number that are 4 numbers, start with '1' and end in '04' or '10
# (let's fix this for 2020 ;) # (let's fix this for 2020 ;)
if match.group('bt').lower() == 'ubuntu': if match.group('bt').lower() == 'ubuntu':
bugids = filter(lambda bugnum: not (len(bugnum) == 4 and bugnum[0] == '1' and bugnum[2:] in ('04', '10')), bugids) bugids = [bugnum for bugnum in bugids if not (len(bugnum) == 4 and bugnum[0] == '1' and bugnum[2:] in ('04', '10'))]
# End HACK # End HACK
if not sure_bug: if not sure_bug:
@ -364,7 +368,7 @@ class Bugtracker(callbacks.PluginRegexp):
bugids = list(set(bugids)) ## remove dups bugids = list(set(bugids)) ## remove dups
msg.tag('nbugs', nbugs + len(bugids)) msg.tag('nbugs', nbugs + len(bugids))
bt = map(lambda x: x.lower(), match.group('bt').split()) bt = [x.lower() for x in match.group('bt').split()]
# Strip off trailing ':' from the tracker name. Allows for (LP: #nnnnnn) # Strip off trailing ':' from the tracker name. Allows for (LP: #nnnnnn)
if bt and bt[0].endswith(':'): if bt and bt[0].endswith(':'):
bt[0] = bt[:-1] bt[0] = bt[:-1]
@ -407,7 +411,7 @@ class Bugtracker(callbacks.PluginRegexp):
except BugNotFoundError: except BugNotFoundError:
if self.registryValue('replyWhenNotFound'): if self.registryValue('replyWhenNotFound'):
irc.error("%s bug %d could not be found" % (tracker.description, bugid)) irc.error("%s bug %d could not be found" % (tracker.description, bugid))
except BugtrackerError, e: except BugtrackerError as e:
# if 'private' in str(e): # if 'private' in str(e):
# irc.reply("Bug %d on http://launchpad.net/bugs/%d is private" % (bugid, bugid)) # irc.reply("Bug %d on http://launchpad.net/bugs/%d is private" % (bugid, bugid))
# return # return
@ -433,9 +437,9 @@ class Bugtracker(callbacks.PluginRegexp):
if not tracker: if not tracker:
return return
report = self.get_bug(channel, tracker, int(match.group('bug')), self.registryValue('showassignee', channel), do_url = False) report = self.get_bug(channel, tracker, int(match.group('bug')), self.registryValue('showassignee', channel), do_url = False)
except BugtrackerError, e: except BugtrackerError as e:
irc.error(str(e)) irc.error(str(e))
except BugNotFoundError, e: except BugNotFoundError as e:
irc.error("%s bug %s not found" % (tracker, match.group('bug'))) irc.error("%s bug %s not found" % (tracker, match.group('bug')))
else: else:
for r in report: for r in report:
@ -463,7 +467,7 @@ class Bugtracker(callbacks.PluginRegexp):
if not self.is_ok(channel, 'cve', cve): if not self.is_ok(channel, 'cve', cve):
return return
url = 'http://cve.mitre.org/cgi-bin/cvename.cgi?name=%s' % cve url = 'http://cve.mitre.org/cgi-bin/cvename.cgi?name=%s' % cve
cvedata = utils.web.getUrl(url) cvedata = utils.web.getUrl(url).decode('utf-8')
m = cvere.search(cvedata) m = cvere.search(cvedata)
if m: if m:
cve = m.group(1).replace('\n', ' ') cve = m.group(1).replace('\n', ' ')
@ -500,7 +504,7 @@ class Bugtracker(callbacks.PluginRegexp):
if 'sourceforge.net' in snarfurl: # See below if 'sourceforge.net' in snarfurl: # See below
return None return None
for t in self.db.keys(): for t in list(self.db.keys()):
tracker = self.db.get(t, None) tracker = self.db.get(t, None)
if not tracker: if not tracker:
self.log.error("No tracker for key %r" % t) self.log.error("No tracker for key %r" % t)
@ -525,7 +529,7 @@ class Bugtracker(callbacks.PluginRegexp):
tracker = Bugzilla().get_tracker(snarfurl) tracker = Bugzilla().get_tracker(snarfurl)
if tracker: if tracker:
self.db[tracker.name] = tracker self.db[tracker.name] = tracker
self.shorthand = utils.abbrev(self.db.keys()) self.shorthand = utils.abbrev(list(self.db.keys()))
return tracker return tracker
return None return None
@ -613,16 +617,16 @@ class Bugzilla(IBugtracker):
try: try:
bugxml = utils.web.getUrl(url) bugxml = utils.web.getUrl(url)
zilladom = minidom.parseString(bugxml) zilladom = minidom.parseString(bugxml)
except Exception, e: except Exception as e:
s = 'Could not parse XML returned by %s: %s (%s)' % (self.description, e, url) s = 'Could not parse XML returned by %s: %s (%s)' % (self.description, e, url)
raise BugtrackerError, s raise BugtrackerError(s)
bug_n = zilladom.getElementsByTagName('bug')[0] bug_n = zilladom.getElementsByTagName('bug')[0]
if bug_n.hasAttribute('error'): if bug_n.hasAttribute('error'):
errtxt = bug_n.getAttribute('error') errtxt = bug_n.getAttribute('error')
if errtxt == 'NotFound': if errtxt == 'NotFound':
raise BugNotFoundError raise BugNotFoundError
s = 'Error getting %s bug #%s: %s' % (self.description, id, errtxt) s = 'Error getting %s bug #%s: %s' % (self.description, id, errtxt)
raise BugtrackerError, s raise BugtrackerError(s)
try: try:
title = _getnodetxt(bug_n.getElementsByTagName('short_desc')[0]) title = _getnodetxt(bug_n.getElementsByTagName('short_desc')[0])
status = _getnodetxt(bug_n.getElementsByTagName('bug_status')[0]) status = _getnodetxt(bug_n.getElementsByTagName('bug_status')[0])
@ -637,9 +641,9 @@ class Bugzilla(IBugtracker):
assignee = _getnodetxt(bug_n.getElementsByTagName('assigned_to')[0]) assignee = _getnodetxt(bug_n.getElementsByTagName('assigned_to')[0])
except: except:
pass pass
except Exception, e: except Exception as e:
s = 'Could not parse XML returned by %s bugzilla: %s (%s)' % (self.description, e, url) s = 'Could not parse XML returned by %s bugzilla: %s (%s)' % (self.description, e, url)
raise BugtrackerError, s raise BugtrackerError(s)
return [(id, component, title, severity, status, assignee, "%s/show_bug.cgi?id=%d" % (self.url, id))] return [(id, component, title, severity, status, assignee, "%s/show_bug.cgi?id=%d" % (self.url, id))]
class Issuezilla(Bugzilla): class Issuezilla(Bugzilla):
@ -705,7 +709,7 @@ class Launchpad(IBugtracker):
supylog.exception("Unknown exception while accessing the Launchpad API") supylog.exception("Unknown exception while accessing the Launchpad API")
def _parse(self, task): #Depricated def _parse(self, task): #Depricated
parser = email.FeedParser.FeedParser() parser = FeedParser()
parser.feed(task) parser.feed(task)
return parser.close() return parser.close()
@ -769,7 +773,7 @@ class Launchpad(IBugtracker):
try: try:
bugdata = self.lp.bugs[id] bugdata = self.lp.bugs[id]
if bugdata.private: if bugdata.private:
raise BugtrackerError, "This bug is private" raise BugtrackerError("This bug is private")
dup = bugdata.duplicate_of dup = bugdata.duplicate_of
summary_prefix = '' # Used to made dups easier summary_prefix = '' # Used to made dups easier
while dup: while dup:
@ -784,14 +788,14 @@ class Launchpad(IBugtracker):
if tasks.total_size != 1: if tasks.total_size != 1:
tasks = list(tasks) tasks = list(tasks)
try: try:
tasks.sort(self._sort) tasks = sorted(tasks, key=cmp_to_key(self._sort))
taskdata = tasks[-1] taskdata = tasks[-1]
except ValueError: except ValueError:
tasks = [_ for _ in tasks if _.bug_target_name.endswith(u'(Ubuntu)')] tasks = [_ for _ in tasks if _.bug_target_name.endswith('(Ubuntu)')]
if tasks: if tasks:
if len(tasks) != 1: if len(tasks) != 1:
try: try:
tasks.sort(self._sort) tasks = sorted(tasks, key=cmp_to_key(self._sort))
taskdata = tasks[-1] taskdata = tasks[-1]
except ValueError: except ValueError:
taskdata = bugdata.bug_tasks[bugdata.bug_tasks.total_size - 1] taskdata = bugdata.bug_tasks[bugdata.bug_tasks.total_size - 1]
@ -806,24 +810,24 @@ class Launchpad(IBugtracker):
t = taskdata.bug_target_display_name #task name t = taskdata.bug_target_display_name #task name
if assignee: # "Diaplay Name (Launchpad ID)" if assignee: # "Diaplay Name (Launchpad ID)"
assignee = u"%s (%s)" % (assignee.display_name, assignee.name) assignee = "%s (%s)" % (assignee.display_name, assignee.name)
else: else:
assignee = '' assignee = ''
except Exception, e: except Exception as e:
if type(e).__name__ == 'HTTPError': # messy, but saves trying to import lazr.restfulclient.errors.HTPError if type(e).__name__ == 'HTTPError': # messy, but saves trying to import lazr.restfulclient.errors.HTPError
if e.response.status == 404: if e.response.status == 404:
bugNo = e.content.split(None)[-1][2:-1] # extract the real bug number bugNo = e.content.split(None)[-1][2:-1] # extract the real bug number
if bugNo != str(id): # A duplicate of a private bug, at least we know it exists if bugNo != str(id): # A duplicate of a private bug, at least we know it exists
raise BugtrackerError, 'Bug #%s is a duplicate of bug #%s, but it is private (%s/bugs/%s)' % (id, bugNo, self.url, bugNo) raise BugtrackerError('Bug #%s is a duplicate of bug #%s, but it is private (%s/bugs/%s)' % (id, bugNo, self.url, bugNo))
raise BugtrackerError, "Bug #%s (%s/bugs/%d) is private or doesn't exist" % (id, self.url, id) # Could be private, could just not exist raise BugtrackerError("Bug #%s (%s/bugs/%d) is private or doesn't exist" % (id, self.url, id)) # Could be private, could just not exist
supylog.exception("Error gathering bug data for %s bug #%d" % (self.description, id)) supylog.exception("Error gathering bug data for %s bug #%d" % (self.description, id))
raise BugtrackerError, "Could not gather data from %s for bug #%s (%s/bugs/%s). The error has been logged" % (self.description, id, self.url, id) raise BugtrackerError("Could not gather data from %s for bug #%s (%s/bugs/%s). The error has been logged" % (self.description, id, self.url, id))
elif isinstance(e, KeyError): elif isinstance(e, KeyError):
raise BugNotFoundError raise BugNotFoundError
supylog.exception("Error gathering bug data for %s bug %d" % (self.description, id)) supylog.exception("Error gathering bug data for %s bug %d" % (self.description, id))
raise BugtrackerError, "Could not gather data from %s for bug #%s (%s/bugs/%s). The error has been logged" % (self.description, id, self.url, id) raise BugtrackerError("Could not gather data from %s for bug #%s (%s/bugs/%s). The error has been logged" % (self.description, id, self.url, id))
extinfo = "(affected: %d, heat: %d)" % (affected, heat) extinfo = "(affected: %d, heat: %d)" % (affected, heat)
@ -832,34 +836,34 @@ class Launchpad(IBugtracker):
def get_bug_old(self, id): #Depricated def get_bug_old(self, id): #Depricated
if id == 1: if id == 1:
raise BugtrackerError, "https://bugs.launchpad.net/ubuntu/+bug/1 (Not reporting large bug)" raise BugtrackerError("https://bugs.launchpad.net/ubuntu/+bug/1 (Not reporting large bug)")
try: try:
bugdata = utils.web.getUrl("%s/bugs/%d/+text" % (self.url,id)) bugdata = utils.web.getUrl("%s/bugs/%d/+text" % (self.url,id)).decode('utf-8')
except Exception, e: except Exception as e:
if '404' in str(e): if '404' in str(e):
raise BugNotFoundError raise BugNotFoundError
s = 'Could not parse data returned by %s: %s (%s/bugs/%d)' % (self.description, e, self.url, id) s = 'Could not parse data returned by %s: %s (%s/bugs/%d)' % (self.description, e, self.url, id)
raise BugtrackerError, s raise BugtrackerError(s)
summary = {} summary = {}
# Trap private bugs # Trap private bugs
if "<!-- 4a. didn't try to log in last time: -->" in bugdata: if "<!-- 4a. didn't try to log in last time: -->" in bugdata:
raise BugtrackerError, "This bug is private" raise BugtrackerError("This bug is private")
try: try:
# Split bug data into separate pieces (bug data, task data) # Split bug data into separate pieces (bug data, task data)
data = bugdata.split('\n\n') data = bugdata.split('\n\n')
bugdata = data[0] bugdata = data[0]
taskdata = data[1:] taskdata = data[1:]
parser = email.FeedParser.FeedParser() parser = FeedParser()
parser.feed(bugdata) parser.feed(bugdata)
bugdata = parser.close() bugdata = parser.close()
taskdata = map(self._parse, taskdata) taskdata = list(map(self._parse, taskdata))
taskdata.sort(self._old_sort) taskdata = sorted(taskdata, key=cmp_to_key(self._old_sort))
taskdata = taskdata[-1] taskdata = taskdata[-1]
except Exception, e: except Exception as e:
s = 'Could not parse data returned by %s: %s (%s/bugs/%d)' % (self.description, e, self.url, id) s = 'Could not parse data returned by %s: %s (%s/bugs/%d)' % (self.description, e, self.url, id)
raise BugtrackerError, s raise BugtrackerError(s)
# Try and find duplicates # Try and find duplicates
t = taskdata['task'] t = taskdata['task']
if '(' in t: if '(' in t:
@ -868,9 +872,9 @@ class Launchpad(IBugtracker):
bugNo = bugdata['duplicate-of'] bugNo = bugdata['duplicate-of']
try: try:
data = self.get_bug(int(bugdata['duplicate-of'])) data = self.get_bug(int(bugdata['duplicate-of']))
except Exception, e: except Exception as e:
if '404' in str(e): if '404' in str(e):
raise BugtrackerError, 'Bug #%s is a duplicate of Bug #%s, but it is private. (%s/bugs/%s)' % (id, bugNo, self.url, bugNo) raise BugtrackerError('Bug #%s is a duplicate of Bug #%s, but it is private. (%s/bugs/%s)' % (id, bugNo, self.url, bugNo))
data = list(data[0]) data = list(data[0])
data[2] = ('duplicate for #%d ' % id) + data[2] data[2] = ('duplicate for #%d ' % id) + data[2]
return [tuple(data)] return [tuple(data)]
@ -889,6 +893,9 @@ class Launchpad(IBugtracker):
# </rant> # </rant>
class Debbugs(IBugtracker): class Debbugs(IBugtracker):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
if not sys.version_info < (3,0):
# XXX python3 does not have SOAPpy, so just quit here (for now)
return
IBugtracker.__init__(self, *args, **kwargs) IBugtracker.__init__(self, *args, **kwargs)
self.soap_proxy = SOAPpy.SOAPProxy("bugs.debian.org/cgi-bin/soap.cgi", "Debbugs/SOAP/Status") self.soap_proxy = SOAPpy.SOAPProxy("bugs.debian.org/cgi-bin/soap.cgi", "Debbugs/SOAP/Status")
self.soap_proxy.soapaction = "Debbugs/SOAP/Status#get_status" self.soap_proxy.soapaction = "Debbugs/SOAP/Status#get_status"
@ -897,9 +904,9 @@ class Debbugs(IBugtracker):
bug_url = "http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=%d" % id bug_url = "http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=%d" % id
try: try:
raw = self.soap_proxy.get_status(id) raw = self.soap_proxy.get_status(id)
except Exception, e: except Exception as e:
s = 'Could not parse data returned by %s: %s' % (self.description, e) s = 'Could not parse data returned by %s: %s' % (self.description, e)
raise BugtrackerError, s raise BugtrackerError(s)
if not raw: if not raw:
raise BugNotFoundError raise BugNotFoundError
raw = raw['item']['value'] raw = raw['item']['value']
@ -909,12 +916,15 @@ class Debbugs(IBugtracker):
else: else:
status = 'Open' status = 'Open'
return [(id, raw['package'], raw['subject'], raw['severity'], status, '', "%s/%s" % (self.url, id))] return [(id, raw['package'], raw['subject'], raw['severity'], status, '', "%s/%s" % (self.url, id))]
except Exception, e: except Exception as e:
s = 'Could not parse data returned by %s bugtracker: %s (%s)' % (self.description, e, bug_url) s = 'Could not parse data returned by %s bugtracker: %s (%s)' % (self.description, e, bug_url)
raise BugtrackerError, s raise BugtrackerError(s)
class Mantis(IBugtracker): class Mantis(IBugtracker):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
if not sys.version_info < (3,0):
# XXX python3 does not have SOAPpy, so just quit here (for now)
return
IBugtracker.__init__(self, *args, **kwargs) IBugtracker.__init__(self, *args, **kwargs)
self.soap_proxy = SOAPpy.SOAPProxy(self.url + "/api/soap/mantisconnect.php", "http://futureware.biz/mantisconnect") self.soap_proxy = SOAPpy.SOAPProxy(self.url + "/api/soap/mantisconnect.php", "http://futureware.biz/mantisconnect")
self.soap_proxy.soapaction = "http://futureware.biz/mantisconnect#mc_issue_get" self.soap_proxy.soapaction = "http://futureware.biz/mantisconnect#mc_issue_get"
@ -923,16 +933,16 @@ class Mantis(IBugtracker):
url = self.url + "/view.php?id=%i" % id url = self.url + "/view.php?id=%i" % id
try: try:
raw = self.soap_proxy.mc_issue_get('', "", id) raw = self.soap_proxy.mc_issue_get('', "", id)
except Exception, e: except Exception as e:
s = 'Could not parse data returned by %s: %s (%s)' % (self.description, e, url) s = 'Could not parse data returned by %s: %s (%s)' % (self.description, e, url)
raise BugtrackerError, s raise BugtrackerError(s)
if not raw: if not raw:
raise BugNotFoundError raise BugNotFoundError
try: try:
return [(id, raw['project']['name'], raw['summary'], raw['priority']['name'], raw['resolution']['name'], '', url)] return [(id, raw['project']['name'], raw['summary'], raw['priority']['name'], raw['resolution']['name'], '', url)]
except Exception, e: except Exception as e:
s = 'Could not parse data returned by %s bugtracker: %s (%s)' % (self.description, e, url) s = 'Could not parse data returned by %s bugtracker: %s (%s)' % (self.description, e, url)
raise BugtrackerError, s raise BugtrackerError(s)
# For trac based trackers we get the tab-separated-values format. # For trac based trackers we get the tab-separated-values format.
# The other option is a comma-separated-values format, but if the description # The other option is a comma-separated-values format, but if the description
@ -942,12 +952,12 @@ class Trac(IBugtracker):
def get_bug(self, id): # This is still a little rough, but it works :) def get_bug(self, id): # This is still a little rough, but it works :)
bug_url = "%s/%d" % (self.url, id) bug_url = "%s/%d" % (self.url, id)
try: try:
raw = utils.web.getUrl("%s?format=tab" % bug_url) raw = utils.web.getUrl("%s?format=tab" % bug_url).decode('utf-8')
except Exception, e: except Exception as e:
if 'HTTP Error 500' in str(e): if 'HTTP Error 500' in str(e):
raise BugNotFoundError raise BugNotFoundError
s = 'Could not parse data returned by %s: %s' % (self.description, e, bug_url) s = 'Could not parse data returned by %s: %s' % (self.description, e, bug_url)
raise BugtrackerError, s raise BugtrackerError(s)
raw = raw.replace("\r\n", '\n') raw = raw.replace("\r\n", '\n')
(headers, rest) = raw.split('\n', 1) (headers, rest) = raw.split('\n', 1)
headers = headers.strip().split('\t') headers = headers.strip().split('\t')
@ -977,12 +987,12 @@ class WikiForms(IBugtracker):
url = "%s/%05d" % (self.url, id) url = "%s/%05d" % (self.url, id)
try: try:
bugdata = utils.web.getUrl(url) bugdata = utils.web.getUrl(url).decode('utf-8')
except Exception, e: except Exception as e:
if 'HTTP Error 404' in str(e): if 'HTTP Error 404' in str(e):
raise BugNotFoundError raise BugNotFoundError
s = 'Could not parse data returned by %s: %s (%s)' % (self.description, e, url) s = 'Could not parse data returned by %s: %s (%s)' % (self.description, e, url)
raise BugtrackerError, s raise BugtrackerError(s)
for l in bugdata.split("\n"): for l in bugdata.split("\n"):
l2 = l.lower() l2 = l.lower()
if '<dt>importance</dt>' in l2: if '<dt>importance</dt>' in l2:
@ -1003,10 +1013,10 @@ class Str(IBugtracker):
return s return s
url = "%s?L%d" % (self.url, id) url = "%s?L%d" % (self.url, id)
try: try:
bugdata = utils.web.getUrl(url) bugdata = utils.web.getUrl(url).decode('utf-8')
except Exception, e: except Exception as e:
s = 'Could not parse data returned by %s: %s (%s)' % (self.description, e, url) s = 'Could not parse data returned by %s: %s (%s)' % (self.description, e, url)
raise BugtrackerError, s raise BugtrackerError(s)
for l in bugdata.split("\n"): for l in bugdata.split("\n"):
l2 = l.lower() l2 = l.lower()
if 'nowrap>priority:</th>' in l2: if 'nowrap>priority:</th>' in l2:
@ -1043,10 +1053,10 @@ class Sourceforge(IBugtracker):
def get_bug(self, id): def get_bug(self, id):
url = self._sf_url % id url = self._sf_url % id
try: try:
bugdata = utils.web.getUrl(url) bugdata = utils.web.getUrl(url).decode('utf-8')
except Exception, e: except Exception as e:
s = 'Could not parse data returned by %s: %s (%s)' % (self.description, e, url) s = 'Could not parse data returned by %s: %s (%s)' % (self.description, e, url)
raise BugtrackerError, s raise BugtrackerError(s)
try: try:
reo = sfre.search(bugdata) reo = sfre.search(bugdata)
status = reo.group('status') status = reo.group('status')
@ -1060,7 +1070,7 @@ class Sourceforge(IBugtracker):
# Introspection is quite cool # Introspection is quite cool
defined_bugtrackers = {} defined_bugtrackers = {}
v = vars() v = vars()
for k in v.keys(): for k in list(v.keys()):
if type(v[k]) == type(IBugtracker) and issubclass(v[k], IBugtracker) and not (v[k] == IBugtracker): if type(v[k]) == type(IBugtracker) and issubclass(v[k], IBugtracker) and not (v[k] == IBugtracker):
defined_bugtrackers[k.lower()] = v[k] defined_bugtrackers[k.lower()] = v[k]