From 57e0e75c20f29bb09b9ad26d23be8cd3a61cb004 Mon Sep 17 00:00:00 2001 From: James Vega Date: Wed, 5 Nov 2003 02:13:41 +0000 Subject: [PATCH] Finally caught Bug #835371. Also refactored the plugin and added some tests --- plugins/Sourceforge.py | 166 ++++++++++++++++++++++----------------- test/test_Sourceforge.py | 39 ++++++--- 2 files changed, 122 insertions(+), 83 deletions(-) diff --git a/plugins/Sourceforge.py b/plugins/Sourceforge.py index b50f74193..fa723b307 100644 --- a/plugins/Sourceforge.py +++ b/plugins/Sourceforge.py @@ -74,19 +74,8 @@ def configure(onStart, afterConnect, advanced): if project: onStart.append('Sourceforge defaultproject %s' % project) -example = utils.wrapLines(""" -<@jamessan|work> @bugs -< 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 -<@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 -""") +class TrackerError(Exception): + pass class Sourceforge(callbacks.PrivmsgCommandAndRegexp, plugins.Toggleable): """ @@ -110,28 +99,25 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp, plugins.Toggleable): toggles = plugins.ToggleDictionary({'tracker' : True}) project = None + _projectURL = 'http://sourceforge.net/projects/' def __init__(self): callbacks.PrivmsgCommandAndRegexp.__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 contain the bug/rfe information. """ - - matches = [] - try: - int(num) - for item in ifilter(lambda s, n=num: s is not None and n in s, + if num: + for item in ifilter(lambda s, n=num: s and n in s, self._infoRe.findall(text)): - matches.append((ircutils.bold(utils.htmlToText(item[2])), - utils.htmlToText(item[1]))) - except ValueError: + yield (ircutils.bold(utils.htmlToText(item[2])), + utils.htmlToText(item[1])) + else: for item in ifilter(None, self._infoRe.findall(text)): - matches.append((item[0], utils.htmlToText(item[2]))) - return matches + yield (item[0], utils.htmlToText(item[2])) def defaultproject(self, irc, msg, args): """[] @@ -143,47 +129,49 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp, plugins.Toggleable): self.project = project irc.reply(msg, conf.replySuccess) defaultproject = privmsgs.checkCapability(defaultproject, 'admin') - - def _getTrackerInfo(self, irc, msg, url, regex, num): + + def _getTrackerURL(self, project, regex): try: - fd = urllib2.urlopen(url) + fd = urllib2.urlopen('%s%s' % (self._projectURL, project)) text = fd.read() fd.close() m = regex.search(text) if m is None: - irc.reply(msg, 'Can\'t find the proper Tracker link.') - return + raise TrackerError, 'Invalid Tracker page' else: - url = 'http://sourceforge.net%s%s' %\ - (utils.htmlToText(m.group(1)), self._hrefOpts) - except ValueError, e: - irc.error(msg, str(e)) + return 'http://sourceforge.net%s%s' % (utils.htmlToText( + m.group(1)), self._hrefOpts) except urllib2.HTTPError, e: - irc.error(msg, e.msg()) + raise callbacks.Error, e.msg() except Exception, e: - irc.error(msg, debug.exnToString(e)) + raise callbacks.Error, debug.exnToString(e) + def _getTrackerList(self, url): try: fd = urllib2.urlopen(url) text = fd.read() fd.close() - resp = [] - if num: - head = '%s ' - for match in self._formatResp(num, text): - resp.append(head % match) - if resp: - irc.reply(msg, resp[0]) - return - else: - head = '#%s: %s' - for entry in self._formatResp(num, text): - resp.append(head % entry) - if resp: - if len(resp) > 10: - resp = map(lambda s: utils.ellipsisify(s, 50), resp) - irc.reply(msg, '%s' % utils.commaAndify(resp)) - return + head = '#%s: %s' + resp = [head % entry for entry in self._formatResp(text)] + if resp: + if len(resp) > 10: + resp = map(lambda s: utils.ellipsisify(s, 50), 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 ' + resp = [head % match for match in self._formatResp(text,num)] + if resp: + irc.reply(msg, resp[0]) + return irc.error(msg, 'No Trackers were found. (%s)' % conf.replyPossibleBug) except ValueError, e: @@ -193,45 +181,83 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp, plugins.Toggleable): _bugLink = re.compile(r'"([^"]+)">Bugs') def bugs(self, irc, msg, args): - """[] [] + """[] Returns a list of the most recent bugs filed against . Defaults to searching for bugs in the project set by defaultproject. - If 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 if not project: raise callbacks.ArgumentError - elif not bugnum: + try: + url = self._getTrackerURL(project, self._bugLink) + except TrackerError: + irc.error(msg, 'Can\'t find the Bugs link.') + return + irc.reply(msg, self._getTrackerList(url)) + + def bug(self, irc, msg, args): + """[] + + Returns a description of the bug with Tracker id 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: - bugnum = int(project) - project = self.project + int(project) except ValueError: - pass - url = 'http://sourceforge.net/projects/%s' % project - self._getTrackerInfo(irc, msg, url, self._bugLink, bugnum) + irc.error(msg, '"%s" is not a proper bugnumber.' % project) + bugnum = project + 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') def rfes(self, irc, msg, args): - """[] [] + """[] Returns a list of the most recent RFEs filed against . Defaults to searching for RFEs in the project set by defaultproject. - If 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 if not project: raise callbacks.ArgumentError - elif not rfenum: + try: + url = self._getTrackerURL(project, self._rfeLink) + 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): + """[] + + Returns a description of the bug with Tracker id 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: - rfenum = int(project) - project = self.project + int(project) except ValueError: - pass - url = 'http://sourceforge.net/projects/%s' % project - self._getTrackerInfo(irc, msg, url, self._rfeLink, rfenum) + irc.error(msg, '"%s" is not a proper rfenumber.' % project) + rfenum = str(int(project)) + 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:] _sfTitle = re.compile(r'Detail:(\d+) - ([^<]+)', re.I) diff --git a/test/test_Sourceforge.py b/test/test_Sourceforge.py index ad20fed7d..0acbffa2d 100644 --- a/test/test_Sourceforge.py +++ b/test/test_Sourceforge.py @@ -35,23 +35,34 @@ from test import * class SourceforgeTest(ChannelPluginTestCase, PluginDocumentation): plugins = ('Sourceforge',) - def testBugs(self): - self.assertHelp('bugs') - self.assertResponse('bugs alkjfi83fa8', 'Can\'t find the proper '\ - 'Tracker link.') - self.assertNotError('bugs gaim') + def testBug(self): + self.assertHelp('bug') m = self.getMsg('bugs gaim') 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): self.assertHelp('rfes') - self.assertResponse('rfes alkjfi83hfa8', 'Can\'t find the proper '\ - 'Tracker link.') + self.assertNotError('defaultproject gaim') + self.assertNotError('rfes') + self.assertError('rfes alkjfi83hfa8') self.assertNotError('rfes gaim') - m = self.getMsg('rfes gaim') - n = re.search('#(\d+)', m.args[1]).group(1) - self.assertNotError('rfes gaim %s' % n) + self.assertNotError('defaultproject') def testDefaultproject(self): self.assertHelp('bugs') @@ -59,8 +70,10 @@ class SourceforgeTest(ChannelPluginTestCase, PluginDocumentation): self.assertNotError('bugs') m = self.getMsg('bugs') n = re.search('#(\d+)', m.args[1]).group(1) - # This should have the same effect as calling 'bugs supybot %s' - self.assertNotError('bugs %s' % n) + self.assertNotError('bug supybot %s' % n) + # This should have the same effect as calling 'bug supybot %s' + self.assertNotError('bug %s' % n) + self.assertNotError('defaultproject') def testSnarfer(self): s = r'.*Status.*: \w+'