mirror of
https://github.com/Mikaela/Limnoria.git
synced 2024-11-07 19:49:23 +01:00
Finally caught Bug #835371. Also refactored the plugin and added some tests
This commit is contained in:
parent
09a64b7bea
commit
57e0e75c20
@ -74,19 +74,8 @@ def configure(onStart, afterConnect, advanced):
|
|||||||
if project:
|
if project:
|
||||||
onStart.append('Sourceforge defaultproject %s' % project)
|
onStart.append('Sourceforge defaultproject %s' % project)
|
||||||
|
|
||||||
example = utils.wrapLines("""
|
class TrackerError(Exception):
|
||||||
<@jamessan|work> @bugs
|
pass
|
||||||
< supybot> jamessan|work: Bug #820702: ChannelDB bugs in stats., Bug #797823: Time reporting errors on win9x, Bug #794330: Website documentation isn't finished., Bug #708327: FreeBSD plugin doesn't automatically download the new INDEX, and Bug #708158: FreeBSD plugin's searchports doesn't do depends correctly.
|
|
||||||
<@jamessan|work> @bugs supybot 797823
|
|
||||||
< supybot> jamessan|work: Time reporting errors on win9x <http://sourceforge.net/tracker/index.php?func=detail&aid=797823&group_id=58965&atid=489447>
|
|
||||||
<@jamessan|work> @bugs gaim
|
|
||||||
< supybot> jamessan|work: Bug #821118: MSN Plugin cannot be loaded
|
|
||||||
in 0.71, Bug #820961: dock icon doesn't show up with..., Bug #820879: Cannot connect to a particular irc..., Bug #820831: © or ® render im null, Bug #820776: gaim 0.70 segfaults using certain..., Bug #820691: gaim 0.70 fails to start up on..., Bug #820687: MSN duplicating buddies at signon, Bug (6 more messages)
|
|
||||||
<@jamessan|work> @rfes pythoggoras
|
|
||||||
< supybot> jamessan|work: RFE #728701: Ability to specify 'themed' configs at command line, RFE #720757: Improve CLI interface, RFE #719248: Add config file support, and RFE #717761: Tracker for adding GUI
|
|
||||||
<@jamessan|work> @rfes pythoggoras 720757
|
|
||||||
< supybot> jamessan|work: Improve CLI interface <http://sourceforge.net/tracker/index.php?func=detail&aid=720757&group_id=75946&atid=545548>
|
|
||||||
""")
|
|
||||||
|
|
||||||
class Sourceforge(callbacks.PrivmsgCommandAndRegexp, plugins.Toggleable):
|
class Sourceforge(callbacks.PrivmsgCommandAndRegexp, plugins.Toggleable):
|
||||||
"""
|
"""
|
||||||
@ -110,28 +99,25 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp, plugins.Toggleable):
|
|||||||
|
|
||||||
toggles = plugins.ToggleDictionary({'tracker' : True})
|
toggles = plugins.ToggleDictionary({'tracker' : True})
|
||||||
project = None
|
project = None
|
||||||
|
_projectURL = 'http://sourceforge.net/projects/'
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
callbacks.PrivmsgCommandAndRegexp.__init__(self)
|
callbacks.PrivmsgCommandAndRegexp.__init__(self)
|
||||||
plugins.Toggleable.__init__(self)
|
plugins.Toggleable.__init__(self)
|
||||||
|
|
||||||
def _formatResp(self, num, text):
|
def _formatResp(self, text, num=''):
|
||||||
"""
|
"""
|
||||||
Parses the Sourceforge query to return a list of tuples that
|
Parses the Sourceforge query to return a list of tuples that
|
||||||
contain the bug/rfe information.
|
contain the bug/rfe information.
|
||||||
"""
|
"""
|
||||||
|
if num:
|
||||||
matches = []
|
for item in ifilter(lambda s, n=num: s and n in s,
|
||||||
try:
|
|
||||||
int(num)
|
|
||||||
for item in ifilter(lambda s, n=num: s is not None and n in s,
|
|
||||||
self._infoRe.findall(text)):
|
self._infoRe.findall(text)):
|
||||||
matches.append((ircutils.bold(utils.htmlToText(item[2])),
|
yield (ircutils.bold(utils.htmlToText(item[2])),
|
||||||
utils.htmlToText(item[1])))
|
utils.htmlToText(item[1]))
|
||||||
except ValueError:
|
else:
|
||||||
for item in ifilter(None, self._infoRe.findall(text)):
|
for item in ifilter(None, self._infoRe.findall(text)):
|
||||||
matches.append((item[0], utils.htmlToText(item[2])))
|
yield (item[0], utils.htmlToText(item[2]))
|
||||||
return matches
|
|
||||||
|
|
||||||
def defaultproject(self, irc, msg, args):
|
def defaultproject(self, irc, msg, args):
|
||||||
"""[<project>]
|
"""[<project>]
|
||||||
@ -144,45 +130,47 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp, plugins.Toggleable):
|
|||||||
irc.reply(msg, conf.replySuccess)
|
irc.reply(msg, conf.replySuccess)
|
||||||
defaultproject = privmsgs.checkCapability(defaultproject, 'admin')
|
defaultproject = privmsgs.checkCapability(defaultproject, 'admin')
|
||||||
|
|
||||||
def _getTrackerInfo(self, irc, msg, url, regex, num):
|
def _getTrackerURL(self, project, regex):
|
||||||
try:
|
try:
|
||||||
fd = urllib2.urlopen(url)
|
fd = urllib2.urlopen('%s%s' % (self._projectURL, project))
|
||||||
text = fd.read()
|
text = fd.read()
|
||||||
fd.close()
|
fd.close()
|
||||||
m = regex.search(text)
|
m = regex.search(text)
|
||||||
if m is None:
|
if m is None:
|
||||||
irc.reply(msg, 'Can\'t find the proper Tracker link.')
|
raise TrackerError, 'Invalid Tracker page'
|
||||||
return
|
|
||||||
else:
|
else:
|
||||||
url = 'http://sourceforge.net%s%s' %\
|
return 'http://sourceforge.net%s%s' % (utils.htmlToText(
|
||||||
(utils.htmlToText(m.group(1)), self._hrefOpts)
|
m.group(1)), self._hrefOpts)
|
||||||
except ValueError, e:
|
|
||||||
irc.error(msg, str(e))
|
|
||||||
except urllib2.HTTPError, e:
|
except urllib2.HTTPError, e:
|
||||||
irc.error(msg, e.msg())
|
raise callbacks.Error, e.msg()
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
irc.error(msg, debug.exnToString(e))
|
raise callbacks.Error, debug.exnToString(e)
|
||||||
|
|
||||||
|
def _getTrackerList(self, url):
|
||||||
try:
|
try:
|
||||||
fd = urllib2.urlopen(url)
|
fd = urllib2.urlopen(url)
|
||||||
text = fd.read()
|
text = fd.read()
|
||||||
fd.close()
|
fd.close()
|
||||||
resp = []
|
|
||||||
if num:
|
|
||||||
head = '%s <http://sourceforge.net%s>'
|
|
||||||
for match in self._formatResp(num, text):
|
|
||||||
resp.append(head % match)
|
|
||||||
if resp:
|
|
||||||
irc.reply(msg, resp[0])
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
head = '#%s: %s'
|
head = '#%s: %s'
|
||||||
for entry in self._formatResp(num, text):
|
resp = [head % entry for entry in self._formatResp(text)]
|
||||||
resp.append(head % entry)
|
|
||||||
if resp:
|
if resp:
|
||||||
if len(resp) > 10:
|
if len(resp) > 10:
|
||||||
resp = map(lambda s: utils.ellipsisify(s, 50), resp)
|
resp = map(lambda s: utils.ellipsisify(s, 50), resp)
|
||||||
irc.reply(msg, '%s' % utils.commaAndify(resp))
|
return '%s' % utils.commaAndify(resp)
|
||||||
|
raise callbacks.Error, 'No Trackers were found. (%s)' %\
|
||||||
|
conf.replyPossibleBug
|
||||||
|
except Exception, e:
|
||||||
|
raise callbacks.Error, debug.exnToString(e)
|
||||||
|
|
||||||
|
def _getTrackerInfo(self, irc, msg, url, num):
|
||||||
|
try:
|
||||||
|
fd = urllib2.urlopen(url)
|
||||||
|
text = fd.read()
|
||||||
|
fd.close()
|
||||||
|
head = '%s <http://sourceforge.net%s>'
|
||||||
|
resp = [head % match for match in self._formatResp(text,num)]
|
||||||
|
if resp:
|
||||||
|
irc.reply(msg, resp[0])
|
||||||
return
|
return
|
||||||
irc.error(msg, 'No Trackers were found. (%s)' %
|
irc.error(msg, 'No Trackers were found. (%s)' %
|
||||||
conf.replyPossibleBug)
|
conf.replyPossibleBug)
|
||||||
@ -193,45 +181,83 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp, plugins.Toggleable):
|
|||||||
|
|
||||||
_bugLink = re.compile(r'"([^"]+)">Bugs')
|
_bugLink = re.compile(r'"([^"]+)">Bugs')
|
||||||
def bugs(self, irc, msg, args):
|
def bugs(self, irc, msg, args):
|
||||||
"""[<project>] [<num>]
|
"""[<project>]
|
||||||
|
|
||||||
Returns a list of the most recent bugs filed against <project>.
|
Returns a list of the most recent bugs filed against <project>.
|
||||||
Defaults to searching for bugs in the project set by defaultproject.
|
Defaults to searching for bugs in the project set by defaultproject.
|
||||||
If <num> is specified, the bug description and link are retrieved.
|
|
||||||
"""
|
"""
|
||||||
(project, bugnum) = privmsgs.getArgs(args, needed=0, optional=2)
|
project = privmsgs.getArgs(args, needed=0, optional=1)
|
||||||
project = project or self.project
|
project = project or self.project
|
||||||
if not project:
|
if not project:
|
||||||
raise callbacks.ArgumentError
|
raise callbacks.ArgumentError
|
||||||
elif not bugnum:
|
|
||||||
try:
|
try:
|
||||||
bugnum = int(project)
|
url = self._getTrackerURL(project, self._bugLink)
|
||||||
project = self.project
|
except TrackerError:
|
||||||
|
irc.error(msg, 'Can\'t find the Bugs link.')
|
||||||
|
return
|
||||||
|
irc.reply(msg, self._getTrackerList(url))
|
||||||
|
|
||||||
|
def bug(self, irc, msg, args):
|
||||||
|
"""[<project>] <num>
|
||||||
|
|
||||||
|
Returns a description of the bug with Tracker id <num> and the
|
||||||
|
corresponding Tracker URL. Defaults to searching for bugs in the
|
||||||
|
project set by defaultproject.
|
||||||
|
"""
|
||||||
|
(project, bugnum) = privmsgs.getArgs(args, optional=1)
|
||||||
|
if not bugnum:
|
||||||
|
try:
|
||||||
|
int(project)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
irc.error(msg, '"%s" is not a proper bugnumber.' % project)
|
||||||
url = 'http://sourceforge.net/projects/%s' % project
|
bugnum = project
|
||||||
self._getTrackerInfo(irc, msg, url, self._bugLink, bugnum)
|
project = self.project
|
||||||
|
try:
|
||||||
|
url = self._getTrackerURL(project, self._bugLink)
|
||||||
|
except TrackerError:
|
||||||
|
irc.error(msg, 'Can\'t find the Bugs link.')
|
||||||
|
return
|
||||||
|
self._getTrackerInfo(irc, msg, url, bugnum)
|
||||||
|
|
||||||
_rfeLink = re.compile(r'"([^"]+)">RFE')
|
_rfeLink = re.compile(r'"([^"]+)">RFE')
|
||||||
def rfes(self, irc, msg, args):
|
def rfes(self, irc, msg, args):
|
||||||
"""[<project>] [<num>]
|
"""[<project>]
|
||||||
|
|
||||||
Returns a list of the most recent RFEs filed against <project>.
|
Returns a list of the most recent RFEs filed against <project>.
|
||||||
Defaults to searching for RFEs in the project set by defaultproject.
|
Defaults to searching for RFEs in the project set by defaultproject.
|
||||||
If <num> is specified, the rfe description and link are retrieved.
|
|
||||||
"""
|
"""
|
||||||
(project, rfenum) = privmsgs.getArgs(args, needed=0, optional=2)
|
project = privmsgs.getArgs(args, needed=0, optional=1)
|
||||||
project = project or self.project
|
project = project or self.project
|
||||||
if not project:
|
if not project:
|
||||||
raise callbacks.ArgumentError
|
raise callbacks.ArgumentError
|
||||||
elif not rfenum:
|
|
||||||
try:
|
try:
|
||||||
rfenum = int(project)
|
url = self._getTrackerURL(project, self._rfeLink)
|
||||||
project = self.project
|
except TrackerError, e:
|
||||||
|
irc.error(msg, 'Can\'t find the RFEs link.')
|
||||||
|
return
|
||||||
|
irc.reply(msg, self._getTrackerList(url))
|
||||||
|
|
||||||
|
def rfe(self, irc, msg, args):
|
||||||
|
"""[<project>] <num>
|
||||||
|
|
||||||
|
Returns a description of the bug with Tracker id <num> and the
|
||||||
|
corresponding Tracker URL. Defaults to searching for bugs in the
|
||||||
|
project set by defaultproject.
|
||||||
|
"""
|
||||||
|
(project, rfenum) = privmsgs.getArgs(args, optional=1)
|
||||||
|
if not rfenum:
|
||||||
|
try:
|
||||||
|
int(project)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
irc.error(msg, '"%s" is not a proper rfenumber.' % project)
|
||||||
url = 'http://sourceforge.net/projects/%s' % project
|
rfenum = str(int(project))
|
||||||
self._getTrackerInfo(irc, msg, url, self._rfeLink, rfenum)
|
project = self.project
|
||||||
|
try:
|
||||||
|
url = self._getTrackerURL(project, self._rfeLink)
|
||||||
|
except TrackerError:
|
||||||
|
irc.error(msg, 'Can\'t find the RFE link.')
|
||||||
|
return
|
||||||
|
self._getTrackerInfo(irc, msg, url, rfenum)
|
||||||
|
|
||||||
_bold = lambda self, m: (ircutils.bold(m[0]),) + m[1:]
|
_bold = lambda self, m: (ircutils.bold(m[0]),) + m[1:]
|
||||||
_sfTitle = re.compile(r'Detail:(\d+) - ([^<]+)</title>', re.I)
|
_sfTitle = re.compile(r'Detail:(\d+) - ([^<]+)</title>', re.I)
|
||||||
|
@ -35,23 +35,34 @@ from test import *
|
|||||||
|
|
||||||
class SourceforgeTest(ChannelPluginTestCase, PluginDocumentation):
|
class SourceforgeTest(ChannelPluginTestCase, PluginDocumentation):
|
||||||
plugins = ('Sourceforge',)
|
plugins = ('Sourceforge',)
|
||||||
def testBugs(self):
|
def testBug(self):
|
||||||
self.assertHelp('bugs')
|
self.assertHelp('bug')
|
||||||
self.assertResponse('bugs alkjfi83fa8', 'Can\'t find the proper '\
|
|
||||||
'Tracker link.')
|
|
||||||
self.assertNotError('bugs gaim')
|
|
||||||
m = self.getMsg('bugs gaim')
|
m = self.getMsg('bugs gaim')
|
||||||
n = re.search('#(\d+)', m.args[1]).group(1)
|
n = re.search('#(\d+)', m.args[1]).group(1)
|
||||||
self.assertNotError('bugs gaim %s' % n)
|
self.assertNotError('bug gaim %s' % n)
|
||||||
|
self.assertError('bug gaim')
|
||||||
|
|
||||||
|
def testBugs(self):
|
||||||
|
self.assertHelp('bugs')
|
||||||
|
self.assertNotError('defaultproject supybot')
|
||||||
|
self.assertNotError('bugs')
|
||||||
|
self.assertError('bugs alkjfi83fa8')
|
||||||
|
self.assertNotError('bugs gaim')
|
||||||
|
self.assertNotError('defaultproject')
|
||||||
|
|
||||||
|
def testRfe(self):
|
||||||
|
m = self.getMsg('rfes gaim')
|
||||||
|
n = re.search('#(\d+)', m.args[1]).group(1)
|
||||||
|
self.assertNotError('rfe gaim %s' % n)
|
||||||
|
self.assertError('rfe gaim')
|
||||||
|
|
||||||
def testRfes(self):
|
def testRfes(self):
|
||||||
self.assertHelp('rfes')
|
self.assertHelp('rfes')
|
||||||
self.assertResponse('rfes alkjfi83hfa8', 'Can\'t find the proper '\
|
self.assertNotError('defaultproject gaim')
|
||||||
'Tracker link.')
|
self.assertNotError('rfes')
|
||||||
|
self.assertError('rfes alkjfi83hfa8')
|
||||||
self.assertNotError('rfes gaim')
|
self.assertNotError('rfes gaim')
|
||||||
m = self.getMsg('rfes gaim')
|
self.assertNotError('defaultproject')
|
||||||
n = re.search('#(\d+)', m.args[1]).group(1)
|
|
||||||
self.assertNotError('rfes gaim %s' % n)
|
|
||||||
|
|
||||||
def testDefaultproject(self):
|
def testDefaultproject(self):
|
||||||
self.assertHelp('bugs')
|
self.assertHelp('bugs')
|
||||||
@ -59,8 +70,10 @@ class SourceforgeTest(ChannelPluginTestCase, PluginDocumentation):
|
|||||||
self.assertNotError('bugs')
|
self.assertNotError('bugs')
|
||||||
m = self.getMsg('bugs')
|
m = self.getMsg('bugs')
|
||||||
n = re.search('#(\d+)', m.args[1]).group(1)
|
n = re.search('#(\d+)', m.args[1]).group(1)
|
||||||
# This should have the same effect as calling 'bugs supybot %s'
|
self.assertNotError('bug supybot %s' % n)
|
||||||
self.assertNotError('bugs %s' % n)
|
# This should have the same effect as calling 'bug supybot %s'
|
||||||
|
self.assertNotError('bug %s' % n)
|
||||||
|
self.assertNotError('defaultproject')
|
||||||
|
|
||||||
def testSnarfer(self):
|
def testSnarfer(self):
|
||||||
s = r'.*Status.*: \w+'
|
s = r'.*Status.*: \w+'
|
||||||
|
Loading…
Reference in New Issue
Block a user