Finally caught Bug #835371. Also refactored the plugin and added some tests

This commit is contained in:
James Vega 2003-11-05 02:13:41 +00:00
parent 09a64b7bea
commit 57e0e75c20
2 changed files with 122 additions and 83 deletions

View File

@ -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: &copy; or &reg; 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)

View File

@ -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+'