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.
This commit is contained in:
James Vega 2004-01-13 05:44:43 +00:00
parent 6a48344a98
commit 6c1e115434
2 changed files with 107 additions and 21 deletions

View File

@ -35,6 +35,7 @@ Accesses Sourceforge.net for various things
import re import re
import sets import sets
import getopt
from itertools import ifilter, imap from itertools import ifilter, imap
@ -106,7 +107,7 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp, configurable.Mixin):
_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>', 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' '&_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)
_assigned=re.compile(r'<b>(Assigned To):</b> <a.+?<br>(.+?)</td>', _reopts) _assigned=re.compile(r'<b>(Assigned To):</b> <a.+?<br>(.+?)</td>', _reopts)
@ -114,6 +115,7 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp, configurable.Mixin):
_priority = re.compile(r'<b>(Priority):</b> <a.+?<br>(.+?)</td>', _reopts) _priority = re.compile(r'<b>(Priority):</b> <a.+?<br>(.+?)</td>', _reopts)
_status = re.compile(r'<b>(Status):</b> <a.+?<br>(.+?)</td>', _reopts) _status = re.compile(r'<b>(Status):</b> <a.+?<br>(.+?)</td>', _reopts)
_regexps =(_resolution, _assigned, _submitted, _priority, _status) _regexps =(_resolution, _assigned, _submitted, _priority, _status)
_statusOpt = {'any':100, 'open':1, 'closed':2, 'deleted':3, 'pending':4}
configurables = configurable.Dictionary( configurables = configurable.Dictionary(
[('tracker-snarfer', configurable.BoolType, False, [('tracker-snarfer', configurable.BoolType, False,
@ -146,7 +148,7 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp, configurable.Mixin):
for item in ifilter(None, self._infoRe.findall(text)): for item in ifilter(None, self._infoRe.findall(text)):
yield (item[0], utils.htmlToText(item[2])) yield (item[0], utils.htmlToText(item[2]))
def _getTrackerURL(self, project, regex): def _getTrackerURL(self, project, regex, status):
try: try:
text = webutils.getUrl('%s%s' % (self._projectURL, project)) text = webutils.getUrl('%s%s' % (self._projectURL, project))
m = regex.search(text) m = regex.search(text)
@ -154,7 +156,7 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp, configurable.Mixin):
raise TrackerError, 'Invalid Tracker page' raise TrackerError, 'Invalid Tracker page'
else: else:
return 'http://sourceforge.net%s%s' % (utils.htmlToText( 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: except webutils.WebError, e:
raise callbacks.Error, str(e) raise callbacks.Error, str(e)
@ -170,7 +172,7 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp, configurable.Mixin):
raise callbacks.Error, 'No Trackers were found. (%s)' % \ raise callbacks.Error, 'No Trackers were found. (%s)' % \
conf.replyPossibleBug conf.replyPossibleBug
except webutils.WebError, e: except webutils.WebError, e:
raise callbacks.Error, e.msg() raise callbacks.Error, str(e)
def _getTrackerInfo(self, irc, msg, url, num): def _getTrackerInfo(self, irc, msg, url, num):
try: try:
@ -182,16 +184,23 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp, configurable.Mixin):
return return
irc.errorPossibleBug('No Trackers were found.') irc.errorPossibleBug('No Trackers were found.')
except webutils.WebError, e: except webutils.WebError, e:
irc.error(e.msg()) irc.error(str(e))
_bugLink = re.compile(r'"([^"]+)">Bugs') _bugLink = re.compile(r'"([^"]+)">Bugs')
def bugs(self, irc, msg, args): def bugs(self, irc, msg, args):
"""[<project>] """[--{any,open,closed,deleted,pending}] [<project>]
Returns a list of the most recent bugs filed against <project>. Returns a list of the most recent bugs filed against <project>.
<project> is not needed if there is a default project set. <project> 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: try:
int(project) int(project)
# They want the bug command, they're giving us an id#. # They want the bug command, they're giving us an id#.
@ -205,20 +214,27 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp, configurable.Mixin):
if not project: if not project:
raise callbacks.ArgumentError raise callbacks.ArgumentError
try: try:
url = self._getTrackerURL(project, self._bugLink) url = self._getTrackerURL(project, self._bugLink, status)
self.log.warning(url)
except TrackerError, e: except TrackerError, e:
irc.error('%s. Can\'t find the Bugs link.' % e) irc.error('%s. Can\'t find the Bugs link.' % e)
return return
irc.reply(self._getTrackerList(url)) irc.reply(self._getTrackerList(url))
def bug(self, irc, msg, args): def bug(self, irc, msg, args):
"""[<project>] <num> """[--{any,open,closed,deleted,pending}] [<project>] <num>
Returns a description of the bug with Tracker id <num> and the Returns a description of the bug with Tracker id <num> and the
corresponding Tracker URL. <project> is not needed if there is a corresponding Tracker URL. <project> 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: if not bugnum:
try: try:
int(project) int(project)
@ -230,7 +246,8 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp, configurable.Mixin):
if not project: if not project:
raise callbacks.ArgumentError raise callbacks.ArgumentError
try: try:
url = self._getTrackerURL(project, self._bugLink) url = self._getTrackerURL(project, self._bugLink, status)
self.log.warning(url)
except TrackerError, e: except TrackerError, e:
irc.error('%s. Can\'t find the Bugs link.' % e) irc.error('%s. Can\'t find the Bugs link.' % e)
return return
@ -238,12 +255,19 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp, configurable.Mixin):
_rfeLink = re.compile(r'"([^"]+)">RFE') _rfeLink = re.compile(r'"([^"]+)">RFE')
def rfes(self, irc, msg, args): def rfes(self, irc, msg, args):
"""[<project>] """[--{any,open,closed,deleted,pending}] [<project>]
Returns a list of the most recent RFEs filed against <project>. Returns a list of the most recent RFEs filed against <project>.
<project> is not needed if there is a default project set. <project> 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: try:
int(project) int(project)
# They want a specific RFE, they gave us its id#. # They want a specific RFE, they gave us its id#.
@ -257,20 +281,27 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp, configurable.Mixin):
if not project: if not project:
raise callbacks.ArgumentError raise callbacks.ArgumentError
try: try:
url = self._getTrackerURL(project, self._rfeLink) url = self._getTrackerURL(project, self._rfeLink, status)
self.log.warning(url)
except TrackerError, e: except TrackerError, e:
irc.error('%s. Can\'t find the RFEs link.' % e) irc.error('%s. Can\'t find the RFEs link.' % e)
return return
irc.reply(self._getTrackerList(url)) irc.reply(self._getTrackerList(url))
def rfe(self, irc, msg, args): def rfe(self, irc, msg, args):
"""[<project>] <num> """[--{any,open,closed,deleted,pending}] [<project>] <num>
Returns a description of the bug with Tracker id <num> and the Returns a description of the bug with Tracker id <num> and the
corresponding Tracker URL. <project> is not needed if there is a corresponding Tracker URL. <project> 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: if not rfenum:
try: try:
int(project) int(project)
@ -282,7 +313,8 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp, configurable.Mixin):
if not project: if not project:
raise callbacks.ArgumentError raise callbacks.ArgumentError
try: try:
url = self._getTrackerURL(project, self._rfeLink) url = self._getTrackerURL(project, self._rfeLink, status)
self.log.warning(url)
except TrackerError, e: except TrackerError, e:
irc.error('%s. Can\'t find the RFEs link.' % e) irc.error('%s. Can\'t find the RFEs link.' % e)
return return

View File

@ -45,6 +45,60 @@ if network:
self.assertError('bug gaim') self.assertError('bug gaim')
self.assertRegexp('bug lkadf 9', 'find the Bugs') 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): def testBugs(self):
self.assertHelp('bugs') self.assertHelp('bugs')
self.assertNotError('config defaultproject supybot') self.assertNotError('config defaultproject supybot')