From 6c1e115434046dfe20ab62aee85a4a36e73809d6 Mon Sep 17 00:00:00 2001 From: James Vega Date: Tue, 13 Jan 2004 05:44:43 +0000 Subject: [PATCH] Finally put a small band-aid on the sourceforge functions. Now one can specify the search type, but you'll still get an error if the bug isn't on the first page. --- plugins/Sourceforge.py | 74 ++++++++++++++++++++++++++++------------ test/test_Sourceforge.py | 54 +++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 21 deletions(-) diff --git a/plugins/Sourceforge.py b/plugins/Sourceforge.py index 7a23b6352..6f5c990a3 100644 --- a/plugins/Sourceforge.py +++ b/plugins/Sourceforge.py @@ -35,6 +35,7 @@ Accesses Sourceforge.net for various things import re import sets +import getopt from itertools import ifilter, imap @@ -106,7 +107,7 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp, configurable.Mixin): _reopts = re.I _infoRe = re.compile(r'(\d+)([^<]+)', re.I) - _hrefOpts = '&set=custom&_assigned_to=0&_status=1&_category=100' \ + _hrefOpts = '&set=custom&_assigned_to=0&_status=%s&_category=100' \ '&_group=100&order=artifact_id&sort=DESC' _resolution=re.compile(r'(Resolution): (.+?)',_reopts) _assigned=re.compile(r'(Assigned To): (.+?)', _reopts) @@ -114,6 +115,7 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp, configurable.Mixin): _priority = re.compile(r'(Priority): (.+?)', _reopts) _status = re.compile(r'(Status): (.+?)', _reopts) _regexps =(_resolution, _assigned, _submitted, _priority, _status) + _statusOpt = {'any':100, 'open':1, 'closed':2, 'deleted':3, 'pending':4} configurables = configurable.Dictionary( [('tracker-snarfer', configurable.BoolType, False, @@ -146,7 +148,7 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp, configurable.Mixin): for item in ifilter(None, self._infoRe.findall(text)): yield (item[0], utils.htmlToText(item[2])) - def _getTrackerURL(self, project, regex): + def _getTrackerURL(self, project, regex, status): try: text = webutils.getUrl('%s%s' % (self._projectURL, project)) m = regex.search(text) @@ -154,7 +156,7 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp, configurable.Mixin): raise TrackerError, 'Invalid Tracker page' else: return 'http://sourceforge.net%s%s' % (utils.htmlToText( - m.group(1)), self._hrefOpts) + m.group(1)), self._hrefOpts % self._statusOpt[status]) except webutils.WebError, e: raise callbacks.Error, str(e) @@ -170,7 +172,7 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp, configurable.Mixin): raise callbacks.Error, 'No Trackers were found. (%s)' % \ conf.replyPossibleBug except webutils.WebError, e: - raise callbacks.Error, e.msg() + raise callbacks.Error, str(e) def _getTrackerInfo(self, irc, msg, url, num): try: @@ -182,16 +184,23 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp, configurable.Mixin): return irc.errorPossibleBug('No Trackers were found.') except webutils.WebError, e: - irc.error(e.msg()) + irc.error(str(e)) _bugLink = re.compile(r'"([^"]+)">Bugs') def bugs(self, irc, msg, args): - """[] + """[--{any,open,closed,deleted,pending}] [] Returns a list of the most recent bugs filed against . - is not needed if there is a default project set. + is not needed if there is a default project set. Search + defaults to open bugs. """ - project = privmsgs.getArgs(args, required=0, optional=1) + (optlist, rest) = getopt.getopt(args, '', self._statusOpt.keys()) + project = privmsgs.getArgs(rest, required=0, optional=1) + status = 'open' + for (option, _) in optlist: + option = option.lstrip('-').lower() + if option in self._statusOpt: + status = option try: int(project) # They want the bug command, they're giving us an id#. @@ -205,20 +214,27 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp, configurable.Mixin): if not project: raise callbacks.ArgumentError try: - url = self._getTrackerURL(project, self._bugLink) + url = self._getTrackerURL(project, self._bugLink, status) + self.log.warning(url) except TrackerError, e: irc.error('%s. Can\'t find the Bugs link.' % e) return irc.reply(self._getTrackerList(url)) def bug(self, irc, msg, args): - """[] + """[--{any,open,closed,deleted,pending}] [] Returns a description of the bug with Tracker id and the corresponding Tracker URL. is not needed if there is a - default project set. + default project set. Search defaults to open bugs. """ - (project, bugnum) = privmsgs.getArgs(args, optional=1) + (optlist, rest) = getopt.getopt(args, '', self._statusOpt.keys()) + (project, bugnum) = privmsgs.getArgs(rest, optional=1) + status = 'open' + for (option, _) in optlist: + option = option.lstrip('-').lower() + if option in self._statusOpt: + status = option if not bugnum: try: int(project) @@ -230,7 +246,8 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp, configurable.Mixin): if not project: raise callbacks.ArgumentError try: - url = self._getTrackerURL(project, self._bugLink) + url = self._getTrackerURL(project, self._bugLink, status) + self.log.warning(url) except TrackerError, e: irc.error('%s. Can\'t find the Bugs link.' % e) return @@ -238,12 +255,19 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp, configurable.Mixin): _rfeLink = re.compile(r'"([^"]+)">RFE') def rfes(self, irc, msg, args): - """[] + """[--{any,open,closed,deleted,pending}] [] Returns a list of the most recent RFEs filed against . - is not needed if there is a default project set. + is not needed if there is a default project set. Search + defaults to open RFEs. """ - project = privmsgs.getArgs(args, required=0, optional=1) + (optlist, rest) = getopt.getopt(args, '', self._statusOpt.keys()) + project = privmsgs.getArgs(rest, required=0, optional=1) + status = 'open' + for (option, _) in optlist: + option = option.lstrip('-').lower() + if option in self._statusOpt: + status = option try: int(project) # They want a specific RFE, they gave us its id#. @@ -257,20 +281,27 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp, configurable.Mixin): if not project: raise callbacks.ArgumentError try: - url = self._getTrackerURL(project, self._rfeLink) + url = self._getTrackerURL(project, self._rfeLink, status) + self.log.warning(url) except TrackerError, e: irc.error('%s. Can\'t find the RFEs link.' % e) return irc.reply(self._getTrackerList(url)) def rfe(self, irc, msg, args): - """[] + """[--{any,open,closed,deleted,pending}] [] Returns a description of the bug with Tracker id and the corresponding Tracker URL. is not needed if there is a - default project set. + default project set. Search defaults to open RFEs. """ - (project, rfenum) = privmsgs.getArgs(args, optional=1) + (optlist, rest) = getopt.getopt(args, '', self._statusOpt.keys()) + (project, rfenum) = privmsgs.getArgs(rest, optional=1) + status = 'open' + for (option, _) in optlist: + option = option.lstrip('-').lower() + if option in self._statusOpt: + status = option if not rfenum: try: int(project) @@ -282,7 +313,8 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp, configurable.Mixin): if not project: raise callbacks.ArgumentError try: - url = self._getTrackerURL(project, self._rfeLink) + url = self._getTrackerURL(project, self._rfeLink, status) + self.log.warning(url) except TrackerError, e: irc.error('%s. Can\'t find the RFEs link.' % e) return diff --git a/test/test_Sourceforge.py b/test/test_Sourceforge.py index 81541c768..3e4849615 100644 --- a/test/test_Sourceforge.py +++ b/test/test_Sourceforge.py @@ -45,6 +45,60 @@ if network: self.assertError('bug gaim') self.assertRegexp('bug lkadf 9', 'find the Bugs') + def testAny(self): + m = self.getMsg('bugs --any gaim') + self.failUnless(m, 'No response from Sourceforge.') + n = re.search('#(\d+)', m.args[1]).group(1) + self.assertNotError('bug --any gaim %s' % n) + m = self.getMsg('rfes --any gaim') + self.failUnless(m, 'No response from Sourceforge.') + n = re.search('#(\d+)', m.args[1]).group(1) + self.assertNotError('rfe --any gaim %s' % n) + + def testClosed(self): + m = self.getMsg('bugs --closed gaim') + self.failUnless(m, 'No response from Sourceforge.') + n = re.search('#(\d+)', m.args[1]).group(1) + self.assertNotError('bug --closed gaim %s' % n) + m = self.getMsg('rfes --closed gaim') + self.failUnless(m, 'No response from Sourceforge.') + n = re.search('#(\d+)', m.args[1]).group(1) + self.assertNotError('rfe --closed gaim %s' % n) + + def testDeleted(self): + m = self.getMsg('bugs --deleted gaim') + self.failUnless(m, 'No response from Sourceforge.') + n = re.search('#(\d+)', m.args[1]).group(1) + self.assertNotError('bug --deleted gaim %s' % n) + m = self.getMsg('rfes --deleted gaim') + self.failUnless(m, 'No response from Sourceforge.') + n = re.search('#(\d+)', m.args[1]).group(1) + self.assertNotError('rfe --deleted gaim %s' % n) + + def testOpen(self): + m = self.getMsg('bugs --open gaim') + self.failUnless(m, 'No response from Sourceforge.') + n = re.search('#(\d+)', m.args[1]).group(1) + self.assertNotError('bug --open gaim %s' % n) + m = self.getMsg('rfes --open gaim') + self.failUnless(m, 'No response from Sourceforge.') + n = re.search('#(\d+)', m.args[1]).group(1) + self.assertNotError('rfe --open gaim %s' % n) + + ''' + Just assume pending works since we're not 99% guaranteed to have a + project that has pending bugs/rfes like we do with the others. + def testPending(self): + m = self.getMsg('bugs --pending gaim') + self.failUnless(m, 'No response from Sourceforge.') + n = re.search('#(\d+)', m.args[1]).group(1) + self.assertNotError('bug --pending gaim %s' % n) + m = self.getMsg('rfes --pending gaim') + self.failUnless(m, 'No response from Sourceforge.') + n = re.search('#(\d+)', m.args[1]).group(1) + self.assertNotError('rfe --pending gaim %s' % n) + ''' + def testBugs(self): self.assertHelp('bugs') self.assertNotError('config defaultproject supybot')