diff --git a/plugins/Sourceforge.py b/plugins/Sourceforge.py index c51ce8a10..a31729aaf 100644 --- a/plugins/Sourceforge.py +++ b/plugins/Sourceforge.py @@ -96,11 +96,6 @@ conf.registerChannelValue(conf.supybot.plugins.Sourceforge, 'trackerSnarfer', conf.registerChannelValue(conf.supybot.plugins.Sourceforge, 'defaultProject', registry.String('', """Sets the default project to use in the case that no explicit project is given.""")) -#conf.registerGlobalValue(conf.supybot.plugins.Sourceforge, -# 'enableSeparateTrackersCommands', -# registry.Boolean(True, """Determines whether the bot will recognize the -# tracker types as commands. For example, "@bugs supybot" would be the same -# as calling "@trackers bugs supybot".""")) class Sourceforge(callbacks.PrivmsgCommandAndRegexp): """ @@ -112,7 +107,7 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp): _reopts = re.I _infoRe = re.compile(r'(\d+)([^<]+)', _reopts) + r'"([^"]+)">([^<]+)', re.I) _hrefOpts = '&set=custom&_assigned_to=0&_status=%s&_category=100' \ '&_group=100&order=artifact_id&sort=DESC' _resolution=re.compile(r'(Resolution): (.+?)',_reopts) @@ -132,20 +127,10 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp): super(Sourceforge, self).__init__() self.__class__.sf = self.__class__.sourceforge -# def isCommand(self, methodName): -# if hasattr(self, methodName): -# return True -# if methodName not in ('bugs', 'rfes', 'patches'): -# return False -# elif self.registryValue('enableSeparateTrackersCommands'): -# return True -# else: -# return False - def _formatResp(self, text, num=''): """ Parses the Sourceforge query to return a list of tuples that - contain the bug/rfe information. + contain the tracker information. """ if num: for item in ifilter(lambda s, n=num: s and n in s, @@ -157,6 +142,9 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp): yield (item[0], utils.htmlToText(item[2])) def _getTrackerURL(self, project, regex, status): + """ + Searches the project's Summary page to find the proper tracker link. + """ try: text = webutils.getUrl('%s%s' % (self._projectURL, project)) m = regex.search(text) @@ -169,6 +157,9 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp): raise callbacks.Error, str(e) def _getTrackerList(self, url): + """ + Searches the tracker list page and returns a list of the trackers. + """ try: text = webutils.getUrl(url) if "No matches found." in text: @@ -188,6 +179,9 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp): _sfTitle = re.compile(r'Detail:(\d+) - ([^<]+)', re.I) _linkType = re.compile(r'(\w+ \w+|\w+): Tracker Detailed View', re.I) def _getTrackerInfo(self, url): + """ + Parses the specific tracker page, returning useful information. + """ try: s = webutils.getUrl(url) resp = [] @@ -231,33 +225,22 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp): 'rfes': re.compile(r'"([^"]+)">RFE'), 'patches': re.compile(r'"([^"]+)">Patches'), } - def trackers(self, irc, msg, args): - """[--{any,open,closed,deleted,pending}] {bugs,patches,rfes} - [] - - Returns a list of the most recent trackers filed against . - is not needed if there is a default project set. Search - defaults to open trackers. - """ + def _trackers(self, irc, args, msg, tracker): (optlist, rest) = getopt.getopt(args, '', self._statusOpt.keys()) - (tracker, project) = privmsgs.getArgs(rest, optional=1) + 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(tracker) - # They want the tracker command, they're giving us an id#. - s = 'Use the tracker command (e.g., tracker %s) for info about a'\ - ' specific tracker.' % tracker + int(project) + s = 'Use the tracker command to get information about a specific'\ + 'tracker.' irc.error(s) return except ValueError: pass - tracker = tracker.lower() - if tracker not in self._trackerLink: - raise callbacks.ArgumentError if not project: project = self.registryValue('defaultProject', msg.args[0]) if not project: @@ -271,6 +254,33 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp): return irc.reply(self._getTrackerList(url)) + 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. Search + defaults to open bugs. + """ + self._trackers(irc, args, msg, 'bugs') + + 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. Search + defaults to open rfes. + """ + self._trackers(irc, args, msg, 'rfes') + + def patches(self, irc, msg, args): + """[--{any,open,closed,deleted,pending}] [] + + Returns a list of the most recent patches filed against . + is not needed if there is a default project set. Search + defaults to open patches. + """ + self._trackers(irc, args, msg, 'patches') + _totbugs = re.compile(r'Bugs\s+?\( ([^<]+)', re.S | re.I) def _getNumBugs(self, project): text = webutils.getUrl('%s%s' % (self._projectURL, project)) @@ -291,7 +301,7 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp): return '' def total(self, irc, msg, args): - """[bugs|rfes] [] + """{bugs,rfes} [] Returns the total count of open bugs or rfes. is only necessary if a default project is not set. diff --git a/test/test_Sourceforge.py b/test/test_Sourceforge.py index 35aafd615..0fbe19b45 100644 --- a/test/test_Sourceforge.py +++ b/test/test_Sourceforge.py @@ -40,54 +40,54 @@ class SourceforgeTest(ChannelPluginTestCase): plugins = ('Sourceforge',) if network: def testAny(self): - m = self.getMsg('trackers --any bugs gaim') + m = self.getMsg('bugs --any gaim') self.failUnless(m, 'No response from Sourceforge.') n = re.search('#(\d+)', m.args[1]).group(1) self.assertNotError('tracker %s' % n) - m = self.getMsg('trackers --any rfes gaim') + m = self.getMsg('rfes --any gaim') self.failUnless(m, 'No response from Sourceforge.') n = re.search('#(\d+)', m.args[1]).group(1) self.assertNotError('tracker %s' % n) def testClosed(self): - m = self.getMsg('trackers --closed bugs gaim') + m = self.getMsg('bugs --closed gaim') self.failUnless(m, 'No response from Sourceforge.') n = re.search('#(\d+)', m.args[1]).group(1) self.assertNotError('tracker %s' % n) - m = self.getMsg('trackers --closed patches gaim') + m = self.getMsg('patches --closed gaim') self.failUnless(m, 'No response from Sourceforge.') n = re.search('#(\d+)', m.args[1]).group(1) self.assertNotError('tracker %s' % n) def testDeleted(self): - m = self.getMsg('trackers --deleted bugs gaim') + m = self.getMsg('bugs --deleted gaim') self.failUnless(m, 'No response from Sourceforge.') n = re.search('#(\d+)', m.args[1]).group(1) self.assertNotError('tracker %s' % n) - m = self.getMsg('trackers --deleted rfes gaim') + m = self.getMsg('rfes --deleted gaim') self.failUnless(m, 'No response from Sourceforge.') n = re.search('#(\d+)', m.args[1]).group(1) self.assertNotError('tracker %s' % n) def testOpen(self): - m = self.getMsg('trackers --open bugs gaim') + m = self.getMsg('bugs --open gaim') self.failUnless(m, 'No response from Sourceforge.') n = re.search('#(\d+)', m.args[1]).group(1) self.assertNotError('tracker %s' % n) - m = self.getMsg('trackers --open rfes gaim') + m = self.getMsg('rfes --open gaim') self.failUnless(m, 'No response from Sourceforge.') n = re.search('#(\d+)', m.args[1]).group(1) self.assertNotError('tracker %s' % n) def testTrackers(self): - self.assertHelp('trackers bugs') - self.assertRegexp('trackers bugs 83423', 'find the Bug') + self.assertHelp('bugs') + self.assertRegexp('bugs 83423', 'use the tracker') try: original = Sf.defaultProject() Sf.defaultProject.set('supybot') - self.assertRegexp('trackers bugs alkjfi83fa8', 'find the Bugs') - self.assertNotError('trackers rfes gaim') - self.assertNotError('trackers patches') + self.assertRegexp('bugs alkjfi83fa8', 'find the Bugs') + self.assertNotError('rfes gaim') + self.assertNotError('patches') finally: Sf.defaultProject.set(original) @@ -95,9 +95,9 @@ class SourceforgeTest(ChannelPluginTestCase): try: original = Sf.defaultProject() Sf.defaultProject.setValue('supybot') - self.assertNotError('trackers bugs') + self.assertNotError('bugs') Sf.defaultProject.setValue('') - self.assertHelp('trackers bugs') + self.assertHelp('bugs') finally: Sf.defaultProject.set(original)