mirror of
https://github.com/Mikaela/Limnoria.git
synced 2024-12-18 16:12:42 +01:00
Merge remote-tracking branch 'supybot/master' into testing
Conflicts: .gitignore plugins/Alias/plugin.py plugins/Anonymous/plugin.py plugins/Anonymous/test.py setup.py src/callbacks.py
This commit is contained in:
commit
6f19088724
4
.gitignore
vendored
4
.gitignore
vendored
@ -26,3 +26,7 @@ test-logs/
|
|||||||
src/version.py
|
src/version.py
|
||||||
INSTALL
|
INSTALL
|
||||||
README.txt
|
README.txt
|
||||||
|
|
||||||
|
# Intellij PyCharm / IDEA related files
|
||||||
|
*.iml
|
||||||
|
.idea
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
###
|
###
|
||||||
# Copyright (c) 2002-2004, Jeremiah Fincher
|
# Copyright (c) 2002-2004, Jeremiah Fincher
|
||||||
# Copyright (c) 2009-2010, James McCoy
|
# Copyright (c) 2014, James McCoy
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without
|
# Redistribution and use in source and binary forms, with or without
|
||||||
@ -81,9 +81,6 @@ def getArgs(args, required=1, optional=0, wildcard=0):
|
|||||||
class AliasError(Exception):
|
class AliasError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class RecursiveAlias(AliasError):
|
|
||||||
pass
|
|
||||||
|
|
||||||
dollarRe = re.compile(r'\$(\d+)')
|
dollarRe = re.compile(r'\$(\d+)')
|
||||||
def findBiggestDollar(alias):
|
def findBiggestDollar(alias):
|
||||||
dollars = dollarRe.findall(alias)
|
dollars = dollarRe.findall(alias)
|
||||||
@ -214,11 +211,11 @@ def makeNewAlias(name, alias):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
everythingReplace(tokens)
|
everythingReplace(tokens)
|
||||||
maxNesting = conf.supybot.commands.nested.maximum()
|
# Limit memory use by constraining the size of the message being passed
|
||||||
if maxNesting and irc.nested+1 > maxNesting:
|
# in to the alias. Also tracking nesting to avoid endless recursion.
|
||||||
irc.error(_('You\'ve attempted more nesting than is '
|
maxLength = conf.supybot.reply.maximumLength()
|
||||||
'currently allowed on this bot.'), Raise=True)
|
tokens = [t[:maxLength] for t in tokens]
|
||||||
self.Proxy(irc, msg, tokens, nested=irc.nested+1)
|
self.Proxy(irc, msg, tokens, nested=irc.nested + 1)
|
||||||
flexargs = ''
|
flexargs = ''
|
||||||
if biggestDollar and (wildcard or biggestAt):
|
if biggestDollar and (wildcard or biggestAt):
|
||||||
flexargs = _(' at least')
|
flexargs = _(' at least')
|
||||||
@ -343,11 +340,8 @@ class Alias(callbacks.Plugin):
|
|||||||
(currentAlias, locked, _) = self.aliases[name]
|
(currentAlias, locked, _) = self.aliases[name]
|
||||||
if locked and currentAlias != alias:
|
if locked and currentAlias != alias:
|
||||||
raise AliasError(format('Alias %q is locked.', name))
|
raise AliasError(format('Alias %q is locked.', name))
|
||||||
try:
|
f = makeNewAlias(name, alias)
|
||||||
f = makeNewAlias(name, alias)
|
f = new.instancemethod(f, self, Alias)
|
||||||
f = types.MethodType(f, self)
|
|
||||||
except RecursiveAlias:
|
|
||||||
raise AliasError('You can\'t define a recursive alias.')
|
|
||||||
if '.' in name or '|' in name:
|
if '.' in name or '|' in name:
|
||||||
aliasGroup = self.registryValue('escapedaliases', value=False)
|
aliasGroup = self.registryValue('escapedaliases', value=False)
|
||||||
confname = escapeAlias(name)
|
confname = escapeAlias(name)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
###
|
###
|
||||||
# Copyright (c) 2005, Daniel DiPaolo
|
# Copyright (c) 2005, Daniel DiPaolo
|
||||||
# Copyright (c) 2010, James McCoy
|
# Copyright (c) 2014, James McCoy
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without
|
# Redistribution and use in source and binary forms, with or without
|
||||||
@ -78,17 +78,30 @@ class Anonymous(callbacks.Plugin):
|
|||||||
|
|
||||||
@internationalizeDocstring
|
@internationalizeDocstring
|
||||||
def say(self, irc, msg, args, target, text):
|
def say(self, irc, msg, args, target, text):
|
||||||
"""<channel|nick> <text>
|
"""<channel> <text>
|
||||||
|
|
||||||
Sends <text> to <channel|nick>. Can only send to <nick> if
|
Sends <text> to <channel>. Can only send to <nick> if
|
||||||
supybot.plugins.Anonymous.allowPrivateTarget is True.
|
supybot.plugins.Anonymous.allowPrivateTarget is True.
|
||||||
"""
|
"""
|
||||||
self._preCheck(irc, msg, target, 'say')
|
self._preCheck(irc, msg, target, 'say')
|
||||||
self.log.info('Saying %q to %s due to %s.',
|
self.log.info('Saying %q in %s due to %s.',
|
||||||
text, target, msg.prefix)
|
text, target, msg.prefix)
|
||||||
irc.reply(text, to=target, prefixNick=False,
|
irc.queueMsg(ircmsgs.privmsg(target, text))
|
||||||
private=not ircutils.isChannel(target))
|
irc.noReply()
|
||||||
say = wrap(say, [first('nick', 'inChannel'), 'text'])
|
say = wrap(say, ['inChannel', 'text'])
|
||||||
|
|
||||||
|
def tell(self, irc, msg, args, target, text):
|
||||||
|
"""<nick> <text>
|
||||||
|
|
||||||
|
Sends <text> to <nick>. Can only be used if
|
||||||
|
supybot.plugins.Anonymous.allowPrivateTarget is True.
|
||||||
|
"""
|
||||||
|
self._preCheck(irc, msg, target, 'tell')
|
||||||
|
self.log.info('Telling %q to %s due to %s.',
|
||||||
|
text, target, msg.prefix)
|
||||||
|
irc.queueMsg(ircmsgs.privmsg(target, text))
|
||||||
|
irc.noReply()
|
||||||
|
tell = wrap(tell, ['nick', 'text'])
|
||||||
|
|
||||||
@internationalizeDocstring
|
@internationalizeDocstring
|
||||||
def do(self, irc, msg, args, channel, text):
|
def do(self, irc, msg, args, channel, text):
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
###
|
###
|
||||||
# Copyright (c) 2005, Daniel DiPaolo
|
# Copyright (c) 2005, Daniel DiPaolo
|
||||||
# Copyright (c) 2010, James McCoy
|
# Copyright (c) 2014, James McCoy
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without
|
# Redistribution and use in source and binary forms, with or without
|
||||||
@ -34,16 +34,24 @@ class AnonymousTestCase(ChannelPluginTestCase):
|
|||||||
plugins = ('Anonymous',)
|
plugins = ('Anonymous',)
|
||||||
def testSay(self):
|
def testSay(self):
|
||||||
self.assertError('anonymous say %s I love you!' % self.channel)
|
self.assertError('anonymous say %s I love you!' % self.channel)
|
||||||
self.assertError('anonymous say %s I love you!' % self.nick)
|
origreg = conf.supybot.plugins.Anonymous.requireRegistration()
|
||||||
|
try:
|
||||||
|
conf.supybot.plugins.Anonymous.requireRegistration.setValue(False)
|
||||||
|
m = self.assertNotError('anonymous say %s foo!' % self.channel)
|
||||||
|
self.failUnless(m.args[1] == 'foo!')
|
||||||
|
finally:
|
||||||
|
conf.supybot.plugins.Anonymous.requireRegistration.setValue(origreg)
|
||||||
|
|
||||||
|
def testTell(self):
|
||||||
|
self.assertError('anonymous tell %s I love you!' % self.nick)
|
||||||
origreg = conf.supybot.plugins.Anonymous.requireRegistration()
|
origreg = conf.supybot.plugins.Anonymous.requireRegistration()
|
||||||
origpriv = conf.supybot.plugins.Anonymous.allowPrivateTarget()
|
origpriv = conf.supybot.plugins.Anonymous.allowPrivateTarget()
|
||||||
try:
|
try:
|
||||||
conf.supybot.plugins.Anonymous.requireRegistration.setValue(False)
|
conf.supybot.plugins.Anonymous.requireRegistration.setValue(False)
|
||||||
m = self.assertNotError('anonymous say %s foo!' % self.channel)
|
self.assertError('anonymous tell %s foo!' % self.channel)
|
||||||
self.assertEqual(m.args[1], 'foo!')
|
|
||||||
conf.supybot.plugins.Anonymous.allowPrivateTarget.setValue(True)
|
conf.supybot.plugins.Anonymous.allowPrivateTarget.setValue(True)
|
||||||
m = self.assertNotError('anonymous say %s foo!' % self.nick)
|
m = self.assertNotError('anonymous tell %s foo!' % self.nick)
|
||||||
self.assertEqual(m.args[1], 'foo!')
|
self.failUnless(m.args[1] == 'foo!')
|
||||||
finally:
|
finally:
|
||||||
conf.supybot.plugins.Anonymous.requireRegistration.setValue(origreg)
|
conf.supybot.plugins.Anonymous.requireRegistration.setValue(origreg)
|
||||||
conf.supybot.plugins.Anonymous.allowPrivateTarget.setValue(origpriv)
|
conf.supybot.plugins.Anonymous.allowPrivateTarget.setValue(origpriv)
|
||||||
|
@ -186,6 +186,3 @@ if __name__ == '__main__':
|
|||||||
# 'test-data', 'test-logs', 'tmp')
|
# 'test-data', 'test-logs', 'tmp')
|
||||||
# for fn in configFiles:
|
# for fn in configFiles:
|
||||||
# os.remove(fn)
|
# os.remove(fn)
|
||||||
|
|
||||||
# This is the part where we do our release on Freshmeat using XMLRPC and
|
|
||||||
# <gasp> ESR's software to do it: http://freshmeat.net/p/freshmeat-submit/
|
|
||||||
|
12
setup.py
12
setup.py
@ -274,7 +274,17 @@ setup(
|
|||||||
('share/man/man1', ['docs/man/supybot-adduser.1']),
|
('share/man/man1', ['docs/man/supybot-adduser.1']),
|
||||||
('share/man/man1', ['docs/man/supybot-plugin-doc.1']),
|
('share/man/man1', ['docs/man/supybot-plugin-doc.1']),
|
||||||
('share/man/man1', ['docs/man/supybot-plugin-create.1']),
|
('share/man/man1', ['docs/man/supybot-plugin-create.1']),
|
||||||
]
|
],
|
||||||
|
|
||||||
|
install_requires=[
|
||||||
|
# Time plugin
|
||||||
|
'python-dateutil <2.0,>=1.3',
|
||||||
|
'feedparser',
|
||||||
|
],
|
||||||
|
|
||||||
|
tests_require=[
|
||||||
|
'mock',
|
||||||
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# -*- coding: utf8 -*-
|
# -*- coding: utf8 -*-
|
||||||
###
|
###
|
||||||
# Copyright (c) 2002-2005, Jeremiah Fincher
|
# Copyright (c) 2002-2005, Jeremiah Fincher
|
||||||
# Copyright (c) 2008-2010, James McCoy
|
# Copyright (c) 2014, James McCoy
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without
|
# Redistribution and use in source and binary forms, with or without
|
||||||
@ -642,6 +642,7 @@ class NestedCommandsIrcProxy(ReplyIrcProxy):
|
|||||||
self.msg.prefix, maxNesting)
|
self.msg.prefix, maxNesting)
|
||||||
self.error(_('You\'ve attempted more nesting than is '
|
self.error(_('You\'ve attempted more nesting than is '
|
||||||
'currently allowed on this bot.'))
|
'currently allowed on this bot.'))
|
||||||
|
return
|
||||||
# The deepcopy here is necessary for Scheduler; it re-runs already
|
# The deepcopy here is necessary for Scheduler; it re-runs already
|
||||||
# tokenized commands. There's a possibility a simple copy[:] would
|
# tokenized commands. There's a possibility a simple copy[:] would
|
||||||
# work, but we're being careful.
|
# work, but we're being careful.
|
||||||
|
99
test/test_yn.py
Normal file
99
test/test_yn.py
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
###
|
||||||
|
# Copyright (c) 2014, Artur Krysiak
|
||||||
|
# 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.
|
||||||
|
###
|
||||||
|
|
||||||
|
from supybot import questions
|
||||||
|
from supybot.test import SupyTestCase
|
||||||
|
|
||||||
|
import mock
|
||||||
|
|
||||||
|
# so complicated construction because I want to
|
||||||
|
# gain the string 'y' instead of the character 'y'
|
||||||
|
# the reason of usage this construction is to prove
|
||||||
|
# that comparing strings by 'is' is wrong
|
||||||
|
# better solution is usage of '==' operator ;)
|
||||||
|
_yes_answer = ''.join(['', 'y'])
|
||||||
|
|
||||||
|
class TestYn(SupyTestCase):
|
||||||
|
def test_default_yes_selected(self):
|
||||||
|
questions.expect = mock.Mock(return_value=_yes_answer)
|
||||||
|
|
||||||
|
answer = questions.yn('up', default='y')
|
||||||
|
|
||||||
|
self.assertTrue(answer)
|
||||||
|
|
||||||
|
def test_default_no_selected(self):
|
||||||
|
questions.expect = mock.Mock(return_value='n')
|
||||||
|
|
||||||
|
answer = questions.yn('up', default='n')
|
||||||
|
|
||||||
|
self.assertFalse(answer)
|
||||||
|
|
||||||
|
def test_yes_selected_without_defaults(self):
|
||||||
|
questions.expect = mock.Mock(return_value=_yes_answer)
|
||||||
|
|
||||||
|
answer = questions.yn('up')
|
||||||
|
|
||||||
|
self.assertTrue(answer)
|
||||||
|
|
||||||
|
def test_no_selected_without_defaults(self):
|
||||||
|
questions.expect = mock.Mock(return_value='n')
|
||||||
|
|
||||||
|
answer = questions.yn('up')
|
||||||
|
|
||||||
|
self.assertFalse(answer)
|
||||||
|
|
||||||
|
def test_no_selected_with_default_yes(self):
|
||||||
|
questions.expect = mock.Mock(return_value='n')
|
||||||
|
|
||||||
|
answer = questions.yn('up', default='y')
|
||||||
|
|
||||||
|
self.assertFalse(answer)
|
||||||
|
|
||||||
|
def test_yes_selected_with_default_yes(self):
|
||||||
|
questions.expect = mock.Mock(return_value=_yes_answer)
|
||||||
|
|
||||||
|
answer = questions.yn('up', default='y')
|
||||||
|
|
||||||
|
self.assertTrue(answer)
|
||||||
|
|
||||||
|
def test_yes_selected_with_default_no(self):
|
||||||
|
questions.expect = mock.Mock(return_value=_yes_answer)
|
||||||
|
|
||||||
|
answer = questions.yn('up', default='n')
|
||||||
|
|
||||||
|
self.assertTrue(answer)
|
||||||
|
|
||||||
|
def test_no_selected_with_default_no(self):
|
||||||
|
questions.expect = mock.Mock(return_value='n')
|
||||||
|
|
||||||
|
answer = questions.yn('up', default='n')
|
||||||
|
|
||||||
|
self.assertFalse(answer)
|
||||||
|
|
||||||
|
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
|
Loading…
Reference in New Issue
Block a user