14:e8f91e4a0cb5 draft
Anton Shestakov <av6@dwimlabs.net>, Fri, 19 Oct 2018 01:30:42 +0800
tests: more tests for base commands

next change 18:674e48fa93db
previous change 12:7c18de2de921

plugin.py

Permissions: -rw-r--r--

Other formats: Feeds:
###
# Copyright (c) 2007, 2009 Brendan Cully
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions, and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions, and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author of this software nor the name of
# contributors to this software may be used to endorse or promote products
# derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###
import supybot.utils as utils
from supybot.commands import *
import supybot.plugins as plugins
import supybot.ircutils as ircutils
import supybot.callbacks as callbacks
import os
import urllib
import logging
fields = {'issue':'title',
'msg':'content',
'file':'description',
}
def fetch_item(nodeid, kind='issue', tracker='http://mercurial.selenic.com/bts'):
"""Use Roundup's CSV exports to fetch arbitrary item descriptions
Default behavior is to return subject for a new issue:
>>> fetch_item(1201569)
'[issue1201569] allow running multiple instances of IDLE'
Can also fetch message contents:
>>> fetch_item(108, 'msg')
'Assigned to Guido for obvious reasons.'
Multiline messages have spurious quotes, thanks to CSV format:
>>> print fetch_item(81362, 'msg')
"Incorporated as:
2.7: r69419
3.1: r69421"
File descriptions work too:
>>> fetch_item(102, 'file')
'Example of message from frustrated user on c.l.py'
Missing descriptions show as 'None':
>>> fetch_item(12227, 'file')
'None'
"""
# This should be the smallest query able to fetch what we need
query_tpl = [('@action', 'export_csv'), ('@filter', 'id'),
('id', nodeid), ('@columns', fields[kind])]
# Request path + query
item_url = '/%s?%s' % (kind, urllib.urlencode(query_tpl))
content = urllib.urlopen(tracker + item_url).read().split('\r\n')
if content[0] == 'title':
# Got a single data row CSV, format and return it
return '[issue%s] %s' % (nodeid, content[1].strip())
elif content[0] == 'content':
return content[1].strip()
elif content[0] == 'description':
return content[1].strip()
def fetch(nodeid, debug=True):
''' Format input for fetch_item, add debug messages '''
kind = 'issue'
if nodeid.startswith('msg'):
kind = 'msg'
elif nodeid.startswith('file'):
kind = 'file'
nodeid = nodeid.replace(kind, '')
result = fetch_item(int(nodeid), kind)
if not result:
result = 'No item found for %s%s' % (kind, nodeid)
if debug:
logging.info('Fetched "%s: %s"' % (kind, result))
return result
def revparse(irc, msg, args, state):
if ':' in args[0]:
state.errorInvalid('revision', args[0],
'Contains ":".')
state.args.append(args.pop(0))
addConverter('revision', revparse)
class Hg(object):
def __init__(self, path):
self.path = path
def run(self, args):
fd = os.popen('HGPLAIN=1 %s %s' % (self.path, args))
out = fd.read()
fd.close()
return out
class Mercurial(callbacks.Plugin):
"""Add the help for "@plugin help Mercurial" here
This should describe *how* to use this plugin."""
threaded = True
def __init__(self, irc):
super(Mercurial, self).__init__(irc)
self.path = self.registryValue('path')
self.hg = Hg(self.path)
def hghelp(self, irc, msg, args, cmd):
"""runs hg help with the given args"""
def fmt(text):
lines = text.splitlines()
out = []
for line in lines[:3]:
line = line.strip()
if not line or line.startswith('aliases:'):
continue
if line.startswith('options') or line.startswith('enabled extensions:'):
break
out.append(line)
if out and ' extension - ' in out[0]:
out[0] = ircutils.bold(out[0])
elif len(out) > 1:
out[1] = ircutils.bold(out[1])
out = out[:10]
if out and out[0].startswith('Mercurial Distributed SCM'):
out = ['"%s": unknown command' % cmd]
return out
out = self.hg.run('help ' + cmd)
irc.replies(fmt(out))
hghelp = wrap(hghelp, ['text'])
def changeLog(self, repo, rev):
tmpl = '{rev}:{node|short}\n{date|age}\n{author|person}\n{files}\n{desc}'
cmd = "-R %s log -v --limit 1 --template '%s' -r %s" \
% (repo, tmpl, rev)
out = self.hg.run(cmd)
if not out:
return ['No result found.']
lines = [x for x in out.strip().splitlines() if x]
node, date, user, files = lines[:4]
lines = lines[4:]
node = ircutils.bold(node)
user = ircutils.mircColor(user, fg='green')
lines = ['%s %s %s' % (node, user, date)] + lines
baseurl = self.hg.run("-R %s paths default" % repo)
url = "%s/rev/%s" % (baseurl.strip("\n/"), rev)
return lines[:2] + [url]
def crew(self, irc, msg, args, rev):
"gets the changelog message for the given revision of the crew repository"
cl = self.changeLog('/home/brendan/hg/mirror/mercurial/crew', rev)
irc.replies(cl)
crew = wrap(crew, ['revision'])
def main(self, irc, msg, args, rev):
"gets the changelog message for the given revision of the crew repository"
cl = self.changeLog('/home/hg/repos/hg', rev)
irc.replies(cl)
main = wrap(main, ['revision'])
def bts(self, irc, msg, args, issue):
"""usage: bts (url|<issueno>)
url gets the url of the bts, <issueno> summarizes that bug
"""
url = 'http://mercurial.selenic.com/bts'
if issue == 'url':
irc.reply(url)
return None
title = fetch(issue)
link = None
if title.startswith('[issue'):
end = title.find(']')
link = '/'.join([url, title[1:end]])
title = ircutils.bold(title[:end+1]) + title[end+1:]
title = title.replace('\n', ' ')
irc.reply(title)
if link:
irc.reply(link)
bts = wrap(bts, ['text'])
def glossary(self, irc, msg, args, term):
"""usage: glossary <term>"""
raw = self.hg.run('help glossary').splitlines()
found = False
done = False
answer = []
for line in raw:
if not found and line.lower().startswith(' ' + term.lower()):
found = True
elif found and not (line.startswith(' ') or not line):
done = True
line = line.strip()
if found and not done and line:
answer.append(line)
if not answer:
answer = ['', 'no match found']
irc.reply(' '.join(answer[1:]))
glossary = wrap(glossary, ['text'])
Class = Mercurial