diff --git a/plugins/Conditional/plugin.py b/plugins/Conditional/plugin.py index 0a1b14ea7..921e65732 100644 --- a/plugins/Conditional/plugin.py +++ b/plugins/Conditional/plugin.py @@ -35,6 +35,7 @@ import supybot.ircutils as ircutils import supybot.callbacks as callbacks import re +import collections try: from supybot.i18n import PluginInternationalization @@ -297,6 +298,45 @@ class Conditional(callbacks.Plugin): else: irc.reply('false') nle = wrap(nle, ['float', 'float']) + + def iferror(self, irc, msg, args, testcommand, ifcommand, elsecommand): + """ + + Runs if raises an error, runs + otherwise. + """ + tokens = callbacks.tokenize(testcommand) + InvalidCommand = collections.namedtuple('InvalidCommand', + 'command') + replies = [] + errors = [] + class ErrorReportingProxy(self.Proxy): + def reply(self2, s, *args, **kwargs): + replies.append(s) + def error(self2, s, Raise=False, *args, **kwargs): + errors.append(s) + if Raise: + raise ArgumentError + def _callInvalidCommands(self2): + errors.append(InvalidCommand(self2.args)) + def evalArgs(self2): + # We don't want the replies in the nested command to + # be stored here. + super(ErrorReportingProxy, self2).evalArgs(withClass=self.Proxy) + + try: + ErrorReportingProxy(irc.irc, msg, tokens) + except callbacks.ArgumentError as e: + pass + # TODO: do something with the results + if errors: + tokens = callbacks.tokenize(ifcommand) + self.Proxy(irc, msg, tokens) + else: + tokens = callbacks.tokenize(elsecommand) + self.Proxy(irc, msg, tokens) + iferror = wrap(iferror, ['something', 'something', 'something']) + Condition = internationalizeDocstring(Conditional) Class = Conditional diff --git a/plugins/Conditional/test.py b/plugins/Conditional/test.py index a6fcd174e..562a324a0 100644 --- a/plugins/Conditional/test.py +++ b/plugins/Conditional/test.py @@ -145,5 +145,28 @@ class ConditionalTestCase(PluginTestCase): self.assertRegexp('nle 4 3', 'false') self.assertError('nle 3 4 5') self.assertError('nle 1 bla') + + def testIferror(self): + self.assertResponse( + 'iferror "echo hi" "foo" "bar"', + 'Error: "bar" is not a valid command.') + self.assertResponse( + 'iferror "echo hi" "echo 1 error" "echo 0 errors"', + '0 errors') + self.assertResponse( + 'iferror "foobarbaz" "echo 1 error" "echo 0 errors"', + '1 error') + self.assertResponse( + 'iferror "help foobarbaz" "echo 1 error" "echo 0 errors"', + '1 error') + self.assertResponse( + r'iferror "iferror \"help foobarbaz\" \"echo hi\" \"foobarbaz\"" ' + r'"foo" "bar"', + 'Error: "bar" is not a valid command.') + self.assertResponse( + r'iferror "iferror \"help foobarbaz\" \"echo hi\" \"foobarbaz\"" ' + r'"echo 0 errors" "echo 1 error"', + '1 error') + # vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: diff --git a/src/callbacks.py b/src/callbacks.py index 2bec92362..e198b54a6 100644 --- a/src/callbacks.py +++ b/src/callbacks.py @@ -659,7 +659,7 @@ class NestedCommandsIrcProxy(ReplyIrcProxy): else: self.prefixNick = conf.supybot.reply.withNickPrefix() - def evalArgs(self): + def evalArgs(self, withClass=None): while self.counter < len(self.args): self.repliedTo = False if isinstance(self.args[self.counter], minisix.string_types): @@ -676,8 +676,9 @@ class NestedCommandsIrcProxy(ReplyIrcProxy): # evaluating its args, it will call our reply method, which # will subsequently call this function again, and we'll # pick up where we left off via self.counter. - self.__class__(self, self.msg, - self.args[self.counter], nested=self.nested+1) + cls = withClass or self.__class__ + cls(self, self.msg, self.args[self.counter], + nested=self.nested+1) # We have to return here because the new NestedCommandsIrcProxy # might not have called our reply method instantly, since # its command might be threaded. So (obviously) we can't