From bda06acac6198ce031de6fe4923595a05f424c74 Mon Sep 17 00:00:00 2001 From: Vincent Le Goff Date: Thu, 15 Jun 2017 21:49:20 -0700 Subject: [PATCH 1/2] Add the InterruptCommand exception to cleanly interrupt commands --- evennia/commands/cmdhandler.py | 7 +++++-- evennia/commands/command.py | 7 +++++++ evennia/commands/default/tests.py | 19 +++++++++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/evennia/commands/cmdhandler.py b/evennia/commands/cmdhandler.py index a24f46d449..63c08962b8 100644 --- a/evennia/commands/cmdhandler.py +++ b/evennia/commands/cmdhandler.py @@ -43,6 +43,7 @@ from twisted.internet import reactor from twisted.internet.task import deferLater from twisted.internet.defer import inlineCallbacks, returnValue from django.conf import settings +from evennia.commands.command import InterruptCommand from evennia.comms.channelhandler import CHANNELHANDLER from evennia.utils import logger, utils from evennia.utils.utils import string_suggestions, to_unicode @@ -51,7 +52,7 @@ from django.utils.translation import ugettext as _ _IN_GAME_ERRORS = settings.IN_GAME_ERRORS -__all__ = ("cmdhandler",) +__all__ = ("cmdhandler", "InterruptCommand") _GA = object.__getattribute__ _CMDSET_MERGE_CACHE = WeakValueDictionary() @@ -601,6 +602,9 @@ def cmdhandler(called_by, raw_string, _testing=False, callertype="session", sess # return result to the deferred returnValue(ret) + except InterruptCommand: + # Do nothing, clean exit + pass except Exception: _msg_err(caller, _ERROR_UNTRAPPED) raise ErrorReported(raw_string) @@ -748,4 +752,3 @@ def cmdhandler(called_by, raw_string, _testing=False, callertype="session", sess except Exception: # This catches exceptions in cmdhandler exceptions themselves _msg_err(error_to, _ERROR_CMDHANDLER) - diff --git a/evennia/commands/command.py b/evennia/commands/command.py index 6a6025616c..c5d1515d83 100644 --- a/evennia/commands/command.py +++ b/evennia/commands/command.py @@ -451,3 +451,10 @@ class Command(with_metaclass(CommandMeta, object)): """ return self.__doc__ + + +class InterruptCommand(Exception): + + """Cleanly interrupt a command.""" + + pass diff --git a/evennia/commands/default/tests.py b/evennia/commands/default/tests.py index 39f2f8841f..e6a6f36590 100644 --- a/evennia/commands/default/tests.py +++ b/evennia/commands/default/tests.py @@ -20,6 +20,7 @@ from mock import Mock from evennia.commands.default.cmdset_character import CharacterCmdSet from evennia.utils.test_resources import EvenniaTest from evennia.commands.default import help, general, system, admin, player, building, batchprocess, comms +from evennia.commands.command import Command, InterruptCommand from evennia.utils import ansi, utils from evennia.server.sessionhandler import SESSIONS @@ -89,6 +90,8 @@ class CommandTest(EvenniaTest): else: returned_msg = "\n".join(stored_msg) returned_msg = ansi.parse_ansi(returned_msg, strip_ansi=noansi).strip() + except InterruptCommand: + pass finally: receiver.msg = old_msg @@ -326,3 +329,19 @@ class TestBatchProcess(CommandTest): self.call(batchprocess.CmdBatchCommands(), "example_batch_cmds", "Running Batchcommand processor Automatic mode for example_batch_cmds") # we make sure to delete the button again here to stop the running reactor self.call(building.CmdDestroy(), "button", "button was destroyed.") + +class CmdInterrupt(Command): + + key = "interrupt" + + def parse(self): + raise InterruptCommand + + def func(self): + self.msg("in func") + + +class TestInterruptCommand(CommandTest): + def test_interrupt_command(self): + ret = self.call(CmdInterrupt(), "") + self.assertEqual(ret, "") From 74cf15b2574c815a137f4b1c01cb9c31d8df0764 Mon Sep 17 00:00:00 2001 From: Vincent Le Goff Date: Fri, 16 Jun 2017 17:56:35 -0700 Subject: [PATCH 2/2] Add the InterruptCommand exception to the flat API --- evennia/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/evennia/__init__.py b/evennia/__init__.py index 679825bd70..b65e1edf9b 100644 --- a/evennia/__init__.py +++ b/evennia/__init__.py @@ -46,6 +46,7 @@ Command = None CmdSet = None default_cmds = None syscmdkeys = None +InterruptCommand = None # search functions search_object = None @@ -119,7 +120,7 @@ def _init(): global DefaultPlayer, DefaultObject, DefaultGuest, DefaultCharacter global DefaultRoom, DefaultExit, DefaultChannel, DefaultScript global ObjectDB, PlayerDB, ScriptDB, ChannelDB, Msg - global Command, CmdSet, default_cmds, syscmdkeys + global Command, CmdSet, default_cmds, syscmdkeys, InterruptCommand global search_object, search_script, search_player, search_channel, search_help, search_tag global create_object, create_script, create_player, create_channel, create_message, create_help_entry global settings,lockfuncs, logger, utils, gametime, ansi, spawn, managers @@ -142,7 +143,7 @@ def _init(): from .comms.models import Msg # commands - from .commands.command import Command + from .commands.command import Command, InterruptCommand from .commands.cmdset import CmdSet # search functions