mirror of
https://github.com/Mikaela/Limnoria.git
synced 2024-11-23 11:09:23 +01:00
Consolidate @bugs, @rfes into @trackers and add support for retrieving info
on patches. Add (commented out) infrastructure for supporting usage of @bugs, @rfes, and @trackers depending on the value of a config var.
This commit is contained in:
parent
5f00a39ce4
commit
553a61515c
@ -96,6 +96,11 @@ conf.registerChannelValue(conf.supybot.plugins.Sourceforge, 'trackerSnarfer',
|
|||||||
conf.registerChannelValue(conf.supybot.plugins.Sourceforge, 'defaultProject',
|
conf.registerChannelValue(conf.supybot.plugins.Sourceforge, 'defaultProject',
|
||||||
registry.String('', """Sets the default project to use in the case that no
|
registry.String('', """Sets the default project to use in the case that no
|
||||||
explicit project is given."""))
|
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):
|
class Sourceforge(callbacks.PrivmsgCommandAndRegexp):
|
||||||
"""
|
"""
|
||||||
@ -107,7 +112,7 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp):
|
|||||||
|
|
||||||
_reopts = re.I
|
_reopts = re.I
|
||||||
_infoRe = re.compile(r'<td nowrap>(\d+)</td><td><a href='
|
_infoRe = re.compile(r'<td nowrap>(\d+)</td><td><a href='
|
||||||
r'"([^"]+)">([^<]+)</a>', re.I)
|
r'"([^"]+)">([^<]+)</a>', _reopts)
|
||||||
_hrefOpts = '&set=custom&_assigned_to=0&_status=%s&_category=100' \
|
_hrefOpts = '&set=custom&_assigned_to=0&_status=%s&_category=100' \
|
||||||
'&_group=100&order=artifact_id&sort=DESC'
|
'&_group=100&order=artifact_id&sort=DESC'
|
||||||
_resolution=re.compile(r'<b>(Resolution):</b> <a.+?<br>(.+?)</td>',_reopts)
|
_resolution=re.compile(r'<b>(Resolution):</b> <a.+?<br>(.+?)</td>',_reopts)
|
||||||
@ -124,9 +129,19 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp):
|
|||||||
_projectURL = 'http://sourceforge.net/projects/'
|
_projectURL = 'http://sourceforge.net/projects/'
|
||||||
_trackerURL = 'http://sourceforge.net/support/tracker.php?aid='
|
_trackerURL = 'http://sourceforge.net/support/tracker.php?aid='
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
callbacks.PrivmsgCommandAndRegexp.__init__(self)
|
super(Sourceforge, self).__init__()
|
||||||
self.__class__.sf = self.__class__.sourceforge
|
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=''):
|
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
|
||||||
@ -212,37 +227,47 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp):
|
|||||||
except TrackerError, e:
|
except TrackerError, e:
|
||||||
irc.error(str(e))
|
irc.error(str(e))
|
||||||
|
|
||||||
_bugLink = re.compile(r'"([^"]+)">Bugs')
|
_trackerLink = {'bugs': re.compile(r'"([^"]+)">Bugs'),
|
||||||
def bugs(self, irc, msg, args):
|
'rfes': re.compile(r'"([^"]+)">RFE'),
|
||||||
"""[--{any,open,closed,deleted,pending}] [<project>]
|
'patches': re.compile(r'"([^"]+)">Patches'),
|
||||||
|
}
|
||||||
|
def trackers(self, irc, msg, args):
|
||||||
|
"""[--{any,open,closed,deleted,pending}] {bugs,patches,rfes}
|
||||||
|
[<project>]
|
||||||
|
|
||||||
Returns a list of the most recent bugs filed against <project>.
|
Returns a list of the most recent trackers filed against <project>.
|
||||||
<project> is not needed if there is a default project set. Search
|
<project> is not needed if there is a default project set. Search
|
||||||
defaults to open bugs.
|
defaults to open trackers.
|
||||||
"""
|
"""
|
||||||
(optlist, rest) = getopt.getopt(args, '', self._statusOpt.keys())
|
(optlist, rest) = getopt.getopt(args, '', self._statusOpt.keys())
|
||||||
project = privmsgs.getArgs(rest, required=0, optional=1)
|
(tracker, project) = privmsgs.getArgs(rest, optional=1)
|
||||||
status = 'open'
|
status = 'open'
|
||||||
for (option, _) in optlist:
|
for (option, _) in optlist:
|
||||||
option = option.lstrip('-').lower()
|
option = option.lstrip('-').lower()
|
||||||
if option in self._statusOpt:
|
if option in self._statusOpt:
|
||||||
status = option
|
status = option
|
||||||
try:
|
try:
|
||||||
int(project)
|
int(tracker)
|
||||||
# They want the bug command, they're giving us an id#.
|
# They want the tracker command, they're giving us an id#.
|
||||||
s = 'Use the bug command to get information about a specific bug.'
|
s = 'Use the tracker command (e.g., tracker %s) for info about a'\
|
||||||
|
' specific tracker.' % tracker
|
||||||
irc.error(s)
|
irc.error(s)
|
||||||
return
|
return
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
tracker = tracker.lower()
|
||||||
|
if tracker not in self._trackerLink:
|
||||||
|
raise callbacks.ArgumentError
|
||||||
if not project:
|
if not project:
|
||||||
project = self.registryValue('defaultProject', msg.args[0])
|
project = self.registryValue('defaultProject', msg.args[0])
|
||||||
if not project:
|
if not project:
|
||||||
raise callbacks.ArgumentError
|
raise callbacks.ArgumentError
|
||||||
try:
|
try:
|
||||||
url = self._getTrackerURL(project, self._bugLink, status)
|
url = self._getTrackerURL(project, self._trackerLink[tracker],
|
||||||
|
status)
|
||||||
except TrackerError, e:
|
except TrackerError, e:
|
||||||
irc.error('%s. I can\'t find the Bugs link.' % e)
|
irc.error('%s. I can\'t find the %s link.' %
|
||||||
|
(e, tracker.capitalize()))
|
||||||
return
|
return
|
||||||
irc.reply(self._getTrackerList(url))
|
irc.reply(self._getTrackerList(url))
|
||||||
|
|
||||||
@ -265,8 +290,6 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp):
|
|||||||
else:
|
else:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
# TODO: consolidate total* into one command which takes options for all
|
|
||||||
# the viable statistics that can be snarfed from the project page
|
|
||||||
def total(self, irc, msg, args):
|
def total(self, irc, msg, args):
|
||||||
"""[bugs|rfes] [<project>]
|
"""[bugs|rfes] [<project>]
|
||||||
|
|
||||||
@ -315,40 +338,6 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp):
|
|||||||
else:
|
else:
|
||||||
irc.error('Could not find RFE statistics.')
|
irc.error('Could not find RFE statistics.')
|
||||||
|
|
||||||
_rfeLink = re.compile(r'"([^"]+)">RFE')
|
|
||||||
def rfes(self, irc, msg, args):
|
|
||||||
"""[--{any,open,closed,deleted,pending}] [<project>]
|
|
||||||
|
|
||||||
Returns a list of the most recent Requests For Enhancement (RFEs)
|
|
||||||
filed against <project>. <project> is not needed if there is a
|
|
||||||
default project set. Search defaults to open RFEs.
|
|
||||||
"""
|
|
||||||
(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#.
|
|
||||||
s = 'Use the rfe command to get information about a specific rfe.'
|
|
||||||
irc.error(s)
|
|
||||||
return
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
if not project:
|
|
||||||
project = self.registryValue('defaultProject', msg.args[0])
|
|
||||||
if not project:
|
|
||||||
raise callbacks.ArgumentError
|
|
||||||
try:
|
|
||||||
url = self._getTrackerURL(project, self._rfeLink, status)
|
|
||||||
except TrackerError, e:
|
|
||||||
irc.error('%s. I can\'t find the RFEs link.' % e)
|
|
||||||
return
|
|
||||||
irc.reply(self._getTrackerList(url))
|
|
||||||
|
|
||||||
def fight(self, irc, msg, args):
|
def fight(self, irc, msg, args):
|
||||||
"""[--{bugs,rfes}] [--{open,closed}] <project name> <project name>
|
"""[--{bugs,rfes}] [--{open,closed}] <project name> <project name>
|
||||||
|
|
||||||
|
@ -33,82 +33,73 @@ import re
|
|||||||
|
|
||||||
from testsupport import *
|
from testsupport import *
|
||||||
|
|
||||||
if network:
|
import supybot.plugins.Sourceforge
|
||||||
|
Sf = conf.supybot.plugins.Sourceforge
|
||||||
|
|
||||||
class SourceforgeTest(ChannelPluginTestCase):
|
class SourceforgeTest(ChannelPluginTestCase):
|
||||||
plugins = ('Sourceforge',)
|
plugins = ('Sourceforge',)
|
||||||
|
if network:
|
||||||
def testAny(self):
|
def testAny(self):
|
||||||
m = self.getMsg('bugs --any gaim')
|
m = self.getMsg('trackers --any bugs gaim')
|
||||||
self.failUnless(m, 'No response from Sourceforge.')
|
self.failUnless(m, 'No response from Sourceforge.')
|
||||||
n = re.search('#(\d+)', m.args[1]).group(1)
|
n = re.search('#(\d+)', m.args[1]).group(1)
|
||||||
self.assertNotError('tracker %s' % n)
|
self.assertNotError('tracker %s' % n)
|
||||||
m = self.getMsg('rfes --any gaim')
|
m = self.getMsg('trackers --any rfes gaim')
|
||||||
self.failUnless(m, 'No response from Sourceforge.')
|
self.failUnless(m, 'No response from Sourceforge.')
|
||||||
n = re.search('#(\d+)', m.args[1]).group(1)
|
n = re.search('#(\d+)', m.args[1]).group(1)
|
||||||
self.assertNotError('tracker %s' % n)
|
self.assertNotError('tracker %s' % n)
|
||||||
|
|
||||||
def testClosed(self):
|
def testClosed(self):
|
||||||
m = self.getMsg('bugs --closed gaim')
|
m = self.getMsg('trackers --closed bugs gaim')
|
||||||
self.failUnless(m, 'No response from Sourceforge.')
|
self.failUnless(m, 'No response from Sourceforge.')
|
||||||
n = re.search('#(\d+)', m.args[1]).group(1)
|
n = re.search('#(\d+)', m.args[1]).group(1)
|
||||||
self.assertNotError('tracker %s' % n)
|
self.assertNotError('tracker %s' % n)
|
||||||
m = self.getMsg('rfes --closed gaim')
|
m = self.getMsg('trackers --closed patches gaim')
|
||||||
self.failUnless(m, 'No response from Sourceforge.')
|
self.failUnless(m, 'No response from Sourceforge.')
|
||||||
n = re.search('#(\d+)', m.args[1]).group(1)
|
n = re.search('#(\d+)', m.args[1]).group(1)
|
||||||
self.assertNotError('tracker %s' % n)
|
self.assertNotError('tracker %s' % n)
|
||||||
|
|
||||||
def testDeleted(self):
|
def testDeleted(self):
|
||||||
m = self.getMsg('bugs --deleted gaim')
|
m = self.getMsg('trackers --deleted bugs gaim')
|
||||||
self.failUnless(m, 'No response from Sourceforge.')
|
self.failUnless(m, 'No response from Sourceforge.')
|
||||||
n = re.search('#(\d+)', m.args[1]).group(1)
|
n = re.search('#(\d+)', m.args[1]).group(1)
|
||||||
self.assertNotError('tracker %s' % n)
|
self.assertNotError('tracker %s' % n)
|
||||||
m = self.getMsg('rfes --deleted gaim')
|
m = self.getMsg('trackers --deleted rfes gaim')
|
||||||
self.failUnless(m, 'No response from Sourceforge.')
|
self.failUnless(m, 'No response from Sourceforge.')
|
||||||
n = re.search('#(\d+)', m.args[1]).group(1)
|
n = re.search('#(\d+)', m.args[1]).group(1)
|
||||||
self.assertNotError('tracker %s' % n)
|
self.assertNotError('tracker %s' % n)
|
||||||
|
|
||||||
def testOpen(self):
|
def testOpen(self):
|
||||||
m = self.getMsg('bugs --open gaim')
|
m = self.getMsg('trackers --open bugs gaim')
|
||||||
self.failUnless(m, 'No response from Sourceforge.')
|
self.failUnless(m, 'No response from Sourceforge.')
|
||||||
n = re.search('#(\d+)', m.args[1]).group(1)
|
n = re.search('#(\d+)', m.args[1]).group(1)
|
||||||
self.assertNotError('tracker %s' % n)
|
self.assertNotError('tracker %s' % n)
|
||||||
m = self.getMsg('rfes --open gaim')
|
m = self.getMsg('trackers --open rfes gaim')
|
||||||
self.failUnless(m, 'No response from Sourceforge.')
|
self.failUnless(m, 'No response from Sourceforge.')
|
||||||
n = re.search('#(\d+)', m.args[1]).group(1)
|
n = re.search('#(\d+)', m.args[1]).group(1)
|
||||||
self.assertNotError('tracker %s' % n)
|
self.assertNotError('tracker %s' % n)
|
||||||
|
|
||||||
def testBugs(self):
|
def testTrackers(self):
|
||||||
self.assertHelp('bugs')
|
self.assertHelp('trackers bugs')
|
||||||
self.assertRegexp('bugs 83423', 'Use the bug command')
|
self.assertRegexp('trackers bugs 83423', 'find the Bug')
|
||||||
try:
|
try:
|
||||||
original = conf.supybot.plugins.Sourceforge.defaultProject()
|
original = Sf.defaultProject()
|
||||||
conf.supybot.plugins.Sourceforge.defaultProject.set('supybot')
|
Sf.defaultProject.set('supybot')
|
||||||
self.assertRegexp('bugs alkjfi83fa8', 'find the Bugs')
|
self.assertRegexp('trackers bugs alkjfi83fa8', 'find the Bugs')
|
||||||
self.assertNotError('bugs gaim')
|
self.assertNotError('trackers rfes gaim')
|
||||||
self.assertNotError('bugs')
|
self.assertNotError('trackers patches')
|
||||||
finally:
|
finally:
|
||||||
conf.supybot.plugins.Sourceforge.defaultProject.set(original)
|
Sf.defaultProject.set(original)
|
||||||
|
|
||||||
def testRfes(self):
|
|
||||||
self.assertHelp('rfes')
|
|
||||||
self.assertRegexp('rfes 83423', 'Use the rfe command')
|
|
||||||
try:
|
|
||||||
original = conf.supybot.plugins.Sourceforge.defaultProject()
|
|
||||||
conf.supybot.plugins.Sourceforge.defaultProject.set('gaim')
|
|
||||||
self.assertNotError('rfes')
|
|
||||||
self.assertRegexp('rfes alkjfi83hfa8', 'find the RFEs')
|
|
||||||
self.assertNotError('rfes gaim')
|
|
||||||
finally:
|
|
||||||
conf.supybot.plugins.Sourceforge.defaultProject.set(original)
|
|
||||||
|
|
||||||
def testDefaultproject(self):
|
def testDefaultproject(self):
|
||||||
try:
|
try:
|
||||||
original = conf.supybot.plugins.Sourceforge.defaultProject()
|
original = Sf.defaultProject()
|
||||||
conf.supybot.plugins.Sourceforge.defaultProject.setValue('supybot')
|
Sf.defaultProject.setValue('supybot')
|
||||||
self.assertNotError('bugs')
|
self.assertNotError('trackers bugs')
|
||||||
conf.supybot.plugins.Sourceforge.defaultProject.setValue('')
|
Sf.defaultProject.setValue('')
|
||||||
self.assertHelp('bugs')
|
self.assertHelp('trackers bugs')
|
||||||
finally:
|
finally:
|
||||||
conf.supybot.plugins.Sourceforge.defaultProject.set(original)
|
Sf.defaultProject.set(original)
|
||||||
|
|
||||||
def testTracker(self):
|
def testTracker(self):
|
||||||
bug = r'Bug.*Status.*: \w+'
|
bug = r'Bug.*Status.*: \w+'
|
||||||
@ -121,8 +112,8 @@ if network:
|
|||||||
def testSnarfer(self):
|
def testSnarfer(self):
|
||||||
s = r'.*Status.*: \w+'
|
s = r'.*Status.*: \w+'
|
||||||
try:
|
try:
|
||||||
original = conf.supybot.plugins.Sourceforge.trackerSnarfer()
|
original = Sf.trackerSnarfer()
|
||||||
conf.supybot.plugins.Sourceforge.trackerSnarfer.setValue(True)
|
Sf.trackerSnarfer.setValue(True)
|
||||||
self.assertSnarfRegexp('http://sourceforge.net/tracker/index.'
|
self.assertSnarfRegexp('http://sourceforge.net/tracker/index.'
|
||||||
'php?func=detail&aid=589953&group_id='
|
'php?func=detail&aid=589953&group_id='
|
||||||
'58965&atid=489447',
|
'58965&atid=489447',
|
||||||
@ -166,8 +157,7 @@ if network:
|
|||||||
self.assertSnarfNoResponse('https://sourceforge.net/tracker/?'
|
self.assertSnarfNoResponse('https://sourceforge.net/tracker/?'
|
||||||
'group_id=58965&atid=489447')
|
'group_id=58965&atid=489447')
|
||||||
finally:
|
finally:
|
||||||
conf.supybot.plugins.Sourceforge.trackerSnarfer.setValue(
|
Sf.trackerSnarfer.setValue(original)
|
||||||
original)
|
|
||||||
|
|
||||||
def testTotal(self):
|
def testTotal(self):
|
||||||
self.assertRegexp('total bugs gaim', r'\d+ open / \d+ total')
|
self.assertRegexp('total bugs gaim', r'\d+ open / \d+ total')
|
||||||
|
Loading…
Reference in New Issue
Block a user