mirror of
https://github.com/Mikaela/Limnoria.git
synced 2024-11-23 19:19:32 +01:00
Changed to use utils.abbrev to allow any unambiguous abbreviation.
This commit is contained in:
parent
e0cfe722c7
commit
94041acb9b
@ -37,8 +37,7 @@ Bugzilla bug retriever
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import string
|
import string
|
||||||
import urllib
|
import urllib2
|
||||||
import base64
|
|
||||||
import xml.dom.minidom as minidom
|
import xml.dom.minidom as minidom
|
||||||
from htmlentitydefs import entitydefs as entities
|
from htmlentitydefs import entitydefs as entities
|
||||||
|
|
||||||
@ -47,36 +46,26 @@ import sqlite
|
|||||||
import conf
|
import conf
|
||||||
import utils
|
import utils
|
||||||
import plugins
|
import plugins
|
||||||
|
import ircutils
|
||||||
import privmsgs
|
import privmsgs
|
||||||
import callbacks
|
import callbacks
|
||||||
import ircutils
|
import structures
|
||||||
|
|
||||||
dbfilename = os.path.join(conf.dataDir, 'Bugzilla.db')
|
dbfilename = os.path.join(conf.dataDir, 'Bugzilla.db')
|
||||||
def makeDb(filename):
|
def makeDb(filename):
|
||||||
if os.path.exists(filename):
|
if os.path.exists(filename):
|
||||||
return sqlite.connect(filename)
|
d = structures.PersistentDictionary(filename)
|
||||||
db = sqlite.connect(filename)
|
else:
|
||||||
cursor = db.cursor()
|
d = structures.PersistentDictionary(filename)
|
||||||
cursor.execute("""CREATE TABLE bugzillas (
|
d['gcc'] = ['http://gcc.gnu.org/bugzilla', 'GCC']
|
||||||
shorthand TEXT UNIQUE ON CONFLICT REPLACE,
|
d['rh'] = ['http://bugzilla.redhat.com/bugzilla', 'Red Hat']
|
||||||
url TEXT,
|
d['gnome'] = ['http://bugzilla.gnome.org/bugzilla', 'Gnome']
|
||||||
description TEXT
|
d['mozilla'] = ['http://bugzilla.mozilla.org', 'Mozilla']
|
||||||
)""")
|
d['ximian'] = ['http://bugzilla.ximian.com/bugzilla', 'Ximian Gnome']
|
||||||
cursor = db.cursor();
|
d.flush()
|
||||||
cursor.execute("""INSERT INTO bugzillas VALUES (%s, %s, %s)""",
|
return d
|
||||||
'rh', 'http://bugzilla.redhat.com/bugzilla', 'Red Hat')
|
|
||||||
cursor.execute("""INSERT INTO bugzillas VALUES (%s, %s, %s)""",
|
|
||||||
'gnome', 'http://bugzilla.gnome.org', 'Gnome')
|
|
||||||
cursor.execute("""INSERT INTO bugzillas VALUES (%s, %s, %s)""",
|
|
||||||
'xim', 'http://bugzilla.ximian.com', 'Ximian')
|
|
||||||
cursor.execute("""INSERT INTO bugzillas VALUES (%s, %s, %s)""",
|
|
||||||
'moz', 'http://bugzilla.mozilla.org', 'Mozilla')
|
|
||||||
cursor.execute("""INSERT INTO bugzillas VALUES (%s, %s, %s)""",
|
|
||||||
'gcc', 'http://gcc.gnu.org/bugzilla', 'GCC')
|
|
||||||
db.commit()
|
|
||||||
return db
|
|
||||||
|
|
||||||
class BugError(Exception):
|
class BugzillaError(Exception):
|
||||||
"""A bugzilla error"""
|
"""A bugzilla error"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -91,6 +80,8 @@ def configure(onStart, afterConnect, advanced):
|
|||||||
if yn('Do you want the Bugzilla snarfer enabled by default?') == 'n':
|
if yn('Do you want the Bugzilla snarfer enabled by default?') == 'n':
|
||||||
onStart.append('Bugzilla config bug-snarfer off')
|
onStart.append('Bugzilla config bug-snarfer off')
|
||||||
|
|
||||||
|
replyNoBugzilla = 'I don\'t have a bugzilla %r'
|
||||||
|
|
||||||
class Bugzilla(callbacks.PrivmsgCommandAndRegexp, plugins.Configurable):
|
class Bugzilla(callbacks.PrivmsgCommandAndRegexp, plugins.Configurable):
|
||||||
"""Show a link to a bug report with a brief description"""
|
"""Show a link to a bug report with a brief description"""
|
||||||
threaded = True
|
threaded = True
|
||||||
@ -104,28 +95,28 @@ class Bugzilla(callbacks.PrivmsgCommandAndRegexp, plugins.Configurable):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
callbacks.PrivmsgCommandAndRegexp.__init__(self)
|
callbacks.PrivmsgCommandAndRegexp.__init__(self)
|
||||||
self.entre = re.compile('&(\S*?);')
|
self.entre = re.compile('&(\S*?);')
|
||||||
|
# Schema: {name, [url, description]}
|
||||||
self.db = makeDb(dbfilename)
|
self.db = makeDb(dbfilename)
|
||||||
|
self.shorthand = utils.abbrev(self.db.keys())
|
||||||
|
|
||||||
def die(self):
|
def die(self):
|
||||||
self.db.close()
|
self.db.close()
|
||||||
del self.db
|
del self.db
|
||||||
|
|
||||||
def add(self, irc, msg, args):
|
def add(self, irc, msg, args):
|
||||||
"""<abbreviation> <url> <description>
|
"""<name> <url> <description>
|
||||||
|
|
||||||
Add a bugzilla <url> to the list of defined bugzillae. <abbreviation>
|
Add a bugzilla <url> to the list of defined bugzillae. <name>
|
||||||
is the name that will be used to reference the zilla in all other
|
is the name that will be used to reference the zilla in all
|
||||||
commands. <description> is the common name for the bugzilla and will
|
commands. Unambiguous abbreviations of <name> will be accepted also.
|
||||||
|
<description> is the common name for the bugzilla and will
|
||||||
be listed with the bugzilla query.
|
be listed with the bugzilla query.
|
||||||
"""
|
"""
|
||||||
(shorthand, url, description) = privmsgs.getArgs(args, required=3)
|
(name, url, description) = privmsgs.getArgs(args, required=3)
|
||||||
cursor = self.db.cursor()
|
cursor = self.db.cursor()
|
||||||
cursor.execute("""INSERT INTO bugzillas VALUES (%s, %s, %s)""",
|
self.db[name] = [url, description]
|
||||||
shorthand, url, description)
|
self.shorthand = utils.abbrev(self.db.keys())
|
||||||
self.db.commit()
|
irc.reply(msg, conf.replySuccess)
|
||||||
irc.reply(msg, 'Added bugzilla entry for "%s" with shorthand "%s"' % (
|
|
||||||
description, shorthand))
|
|
||||||
return
|
|
||||||
|
|
||||||
def remove(self, irc, msg, args):
|
def remove(self, irc, msg, args):
|
||||||
"""<abbreviation>
|
"""<abbreviation>
|
||||||
@ -133,19 +124,14 @@ class Bugzilla(callbacks.PrivmsgCommandAndRegexp, plugins.Configurable):
|
|||||||
Remove the bugzilla associated with <abbreviation> from the list of
|
Remove the bugzilla associated with <abbreviation> from the list of
|
||||||
defined bugzillae.
|
defined bugzillae.
|
||||||
"""
|
"""
|
||||||
shorthand = privmsgs.getArgs(args)
|
name = privmsgs.getArgs(args)
|
||||||
cursor = self.db.cursor()
|
try:
|
||||||
cursor.execute("""SELECT * from bugzillas where shorthand = %s""",
|
name = self.shorthand[name]
|
||||||
shorthand)
|
del self.db[name]
|
||||||
if cursor.rowcount == 0:
|
self.shorthand = utils.abbrev(self.db.keys())
|
||||||
irc.reply(msg, 'Bugzilla "%s" not defined. Try list.' %
|
irc.reply(msg, conf.replySuccess)
|
||||||
shorthand)
|
except KeyError:
|
||||||
return
|
irc.error(msg, replyNoBugzilla % name)
|
||||||
cursor.execute("""DELETE FROM bugzillas where shorthand = %s""",
|
|
||||||
shorthand)
|
|
||||||
self.db.commit()
|
|
||||||
irc.reply(msg, 'Deleted bugzilla "%s"' % shorthand)
|
|
||||||
return
|
|
||||||
|
|
||||||
def list(self, irc, msg, args):
|
def list(self, irc, msg, args):
|
||||||
"""[<abbreviation>]
|
"""[<abbreviation>]
|
||||||
@ -153,26 +139,21 @@ class Bugzilla(callbacks.PrivmsgCommandAndRegexp, plugins.Configurable):
|
|||||||
List defined bugzillae. If <abbreviation> is specified, list the
|
List defined bugzillae. If <abbreviation> is specified, list the
|
||||||
information for that bugzilla.
|
information for that bugzilla.
|
||||||
"""
|
"""
|
||||||
shorthand = privmsgs.getArgs(args, required=0, optional=1)
|
name = privmsgs.getArgs(args, required=0, optional=1)
|
||||||
if shorthand:
|
if name:
|
||||||
cursor = self.db.cursor()
|
try:
|
||||||
cursor.execute("""SELECT url,description from bugzillas where
|
name = self.shorthand[name]
|
||||||
shorthand = %s""", shorthand)
|
(url, description) = self.db[name]
|
||||||
if cursor.rowcount == 0:
|
irc.reply(msg, '%s: %s, %s' % (name, description, url))
|
||||||
irc.reply(msg, 'No such bugzilla defined: "%s".' % shorthand)
|
except KeyError:
|
||||||
return
|
irc.error(msg, replyNoBugzilla % name)
|
||||||
url, description = cursor.fetchone()
|
|
||||||
irc.reply(msg, '%s: %s, %s' % (shorthand, description, url))
|
|
||||||
return
|
|
||||||
else:
|
else:
|
||||||
cursor = self.db.cursor()
|
if self.db:
|
||||||
cursor.execute("""SELECT shorthand from bugzillas""")
|
L = self.db.keys()
|
||||||
if cursor.rowcount == 0:
|
L.sort()
|
||||||
irc.reply(msg, 'No bugzillae defined. Add some with "add"!')
|
irc.reply(msg, utils.commaAndify(L))
|
||||||
return
|
else:
|
||||||
results = ['%s' % (item[0]) for item in cursor.fetchall()]
|
irc.reply(msg, 'I have no defined bugzillae.')
|
||||||
irc.reply(msg, 'Defined bugzillae: %s' % ' '.join(results))
|
|
||||||
return
|
|
||||||
|
|
||||||
def bzSnarfer(self, irc, msg, match):
|
def bzSnarfer(self, irc, msg, match):
|
||||||
r"(http://\S+)/show_bug.cgi\?id=([0-9]+)"
|
r"(http://\S+)/show_bug.cgi\?id=([0-9]+)"
|
||||||
@ -182,7 +163,7 @@ class Bugzilla(callbacks.PrivmsgCommandAndRegexp, plugins.Configurable):
|
|||||||
try:
|
try:
|
||||||
summary = self._get_short_bug_summary(queryurl, 'Snarfed '\
|
summary = self._get_short_bug_summary(queryurl, 'Snarfed '\
|
||||||
'Bugzilla URL', match.group(2))
|
'Bugzilla URL', match.group(2))
|
||||||
except BugError, e:
|
except BugzillaError, e:
|
||||||
irc.reply(msg, str(e))
|
irc.reply(msg, str(e))
|
||||||
return
|
return
|
||||||
except IOError, e:
|
except IOError, e:
|
||||||
@ -205,34 +186,28 @@ class Bugzilla(callbacks.PrivmsgCommandAndRegexp, plugins.Configurable):
|
|||||||
|
|
||||||
Look up bug <number> in the bugzilla associated with <abbreviation>.
|
Look up bug <number> in the bugzilla associated with <abbreviation>.
|
||||||
"""
|
"""
|
||||||
(shorthand, num) = privmsgs.getArgs(args, required=2)
|
(name, number) = privmsgs.getArgs(args, required=2)
|
||||||
cursor = self.db.cursor()
|
|
||||||
cursor.execute("""SELECT url,description from bugzillas where
|
|
||||||
shorthand = %s""", shorthand)
|
|
||||||
if cursor.rowcount == 0:
|
|
||||||
irc.reply(msg, 'Bugzilla "%s" is not defined.' % shorthand)
|
|
||||||
return
|
|
||||||
if not self._is_bug_number(num):
|
|
||||||
irc.reply(msg, '"%s" does not seem to be a number' % num)
|
|
||||||
return
|
|
||||||
url, desc = cursor.fetchone()
|
|
||||||
queryurl = '%s/xml.cgi?id=%s' % (url, num)
|
|
||||||
try:
|
try:
|
||||||
summary = self._get_short_bug_summary(queryurl, desc, num)
|
name = self.shorthand[name]
|
||||||
except BugError, e:
|
(url, description) = self.db[name]
|
||||||
irc.reply(msg, str(e))
|
except KeyError:
|
||||||
|
irc.error(msg, replyNoBugzilla % name)
|
||||||
|
return
|
||||||
|
queryurl = '%s/xml.cgi?id=%s' % (url, number)
|
||||||
|
try:
|
||||||
|
summary = self._get_short_bug_summary(queryurl,description,number)
|
||||||
|
except BugzillaError, e:
|
||||||
|
irc.error(msg, str(e))
|
||||||
return
|
return
|
||||||
except IOError, e:
|
except IOError, e:
|
||||||
msgtouser = '%s. Try yourself: %s' % (e, queryurl)
|
s = '%s. Try yourself: %s' % (e, queryurl)
|
||||||
irc.reply(msg, msgtouser)
|
irc.error(msg, s)
|
||||||
return
|
|
||||||
|
|
||||||
report = {}
|
report = {}
|
||||||
report['zilla'] = str(desc)
|
report['zilla'] = description
|
||||||
report['id'] = str(num)
|
report['id'] = number
|
||||||
report['url'] = str('%s/show_bug.cgi?id=%s' % (url, num))
|
report['url'] = '%s/show_bug.cgi?id=%s' % (url, number)
|
||||||
report['title'] = str(summary['title'])
|
report['title'] = str(summary['title'])
|
||||||
report['summary'] = str(self._mk_summary_string(summary))
|
report['summary'] = self._mk_summary_string(summary)
|
||||||
s = '%(zilla)s bug #%(id)s: %(title)s %(summary)s %(url)s' % report
|
s = '%(zilla)s bug #%(id)s: %(title)s %(summary)s %(url)s' % report
|
||||||
irc.reply(msg, s)
|
irc.reply(msg, s)
|
||||||
|
|
||||||
@ -250,27 +225,20 @@ class Bugzilla(callbacks.PrivmsgCommandAndRegexp, plugins.Configurable):
|
|||||||
L.append(ircutils.bold('Status: ') + summary['status'])
|
L.append(ircutils.bold('Status: ') + summary['status'])
|
||||||
if 'resolution' in summary:
|
if 'resolution' in summary:
|
||||||
L.append(ircutils.bold('Resolution: ') + summary['resolution'])
|
L.append(ircutils.bold('Resolution: ') + summary['resolution'])
|
||||||
return ', '.join(L)
|
return ', '.join(map(str, L))
|
||||||
|
|
||||||
def _is_bug_number(self, bug):
|
def _get_short_bug_summary(self, url, desc, number):
|
||||||
try:
|
|
||||||
int(bug)
|
|
||||||
return True
|
|
||||||
except ValueError:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _get_short_bug_summary(self, url, desc, num):
|
|
||||||
bugxml = self._getbugxml(url, desc)
|
bugxml = self._getbugxml(url, desc)
|
||||||
try: zilladom = minidom.parseString(bugxml)
|
try:
|
||||||
|
zilladom = minidom.parseString(bugxml)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
msg = 'Could not parse XML returned by %s bugzilla: %s'
|
s = 'Could not parse XML returned by %s bugzilla: %s' % (desc, e)
|
||||||
raise BugError, msg % (desc, e)
|
raise BugzillaError, 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')
|
||||||
zilladom.unlink()
|
s = 'Error getting %s bug #%s: %s' % (desc, number, errtxt)
|
||||||
msg = 'Error getting %s bug #%s: %s' % (desc, num, errtxt)
|
raise BugzillaError, s
|
||||||
raise BugError(str(msg))
|
|
||||||
summary = {}
|
summary = {}
|
||||||
try:
|
try:
|
||||||
node = bug_n.getElementsByTagName('short_desc')[0]
|
node = bug_n.getElementsByTagName('short_desc')[0]
|
||||||
@ -291,17 +259,15 @@ class Bugzilla(callbacks.PrivmsgCommandAndRegexp, plugins.Configurable):
|
|||||||
node = bug_n.getElementsByTagName('bug_severity')[0]
|
node = bug_n.getElementsByTagName('bug_severity')[0]
|
||||||
summary['severity'] = self._getnodetxt(node)
|
summary['severity'] = self._getnodetxt(node)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
zilladom.unlink()
|
s = 'Could not parse XML returned by %s bugzilla: %s' % (desc, e)
|
||||||
msg = 'Could not parse XML returned by %s bugzilla: %s'
|
raise BugzillaError, s
|
||||||
raise BugError(str(msg % (desc, e)))
|
|
||||||
zilladom.unlink()
|
|
||||||
return summary
|
return summary
|
||||||
|
|
||||||
def _getbugxml(self, url, desc):
|
def _getbugxml(self, url, desc):
|
||||||
try:
|
try:
|
||||||
fh = urllib.urlopen(url)
|
fh = urllib2.urlopen(url)
|
||||||
except:
|
except urllib2.UrlError, e:
|
||||||
raise IOError('Connection to %s bugzilla failed' % desc)
|
raise IOError, 'Connection to %s bugzilla failed' % desc
|
||||||
bugxml = fh.read()
|
bugxml = fh.read()
|
||||||
fh.close()
|
fh.close()
|
||||||
if not bugxml:
|
if not bugxml:
|
||||||
@ -324,9 +290,9 @@ class Bugzilla(callbacks.PrivmsgCommandAndRegexp, plugins.Configurable):
|
|||||||
while self.entre.search(val):
|
while self.entre.search(val):
|
||||||
entity = self.entre.search(val).group(1)
|
entity = self.entre.search(val).group(1)
|
||||||
if entity in entities:
|
if entity in entities:
|
||||||
val = re.sub(self.entre, entities[entity], val)
|
val = self.entre.sub(entities[entity], val)
|
||||||
else:
|
else:
|
||||||
val = re.sub(self.entre, '_', val)
|
val = self.entre.sub('?', val)
|
||||||
return val
|
return val
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user