[feat] Script refactor; decouple timer component from script lifetime. Resolve #1715

This commit is contained in:
Griatch 2021-03-07 10:34:01 +01:00
parent cd579fb649
commit b5195a6e96
29 changed files with 1136 additions and 1266 deletions

View file

@ -608,11 +608,6 @@ def cmdhandler(
# since this may be different for every command when
# merging multuple cmdsets
if hasattr(cmd, "obj") and hasattr(cmd.obj, "scripts"):
# cmd.obj is automatically made available by the cmdhandler.
# we make sure to validate its scripts.
yield cmd.obj.scripts.validate()
if _testing:
# only return the command instance
returnValue(cmd)

View file

@ -421,7 +421,7 @@ class CmdSetHandler(object):
self.mergetype_stack.append(new_current.actual_mergetype)
self.current = new_current
def add(self, cmdset, emit_to_obj=None, permanent=False, default_cmdset=False):
def add(self, cmdset, emit_to_obj=None, persistent=True, permanent=True, default_cmdset=False, **kwargs):
"""
Add a cmdset to the handler, on top of the old ones, unless it
is set as the default one (it will then end up at the bottom of the stack)
@ -430,7 +430,9 @@ class CmdSetHandler(object):
cmdset (CmdSet or str): Can be a cmdset object or the python path
to such an object.
emit_to_obj (Object, optional): An object to receive error messages.
permanent (bool, optional): This cmdset will remain across a server reboot.
persistent (bool, optional): Let cmdset remain across server reload.
permanent (bool, optional): DEPRECATED. This has the same use as
`persistent`.
default_cmdset (Cmdset, optional): Insert this to replace the
default cmdset position (there is only one such position,
always at the bottom of the stack).
@ -447,6 +449,12 @@ class CmdSetHandler(object):
it's a 'quirk' that has to be documented.
"""
if "permanent" in kwargs:
logger.log_dep("obj.cmdset.add() kwarg 'permanent' has changed to "
"'persistent' and now defaults to True.")
permanent = persistent or permanent
if not (isinstance(cmdset, str) or utils.inherits_from(cmdset, CmdSet)):
string = _("Only CmdSets can be added to the cmdsethandler!")
raise Exception(string)

View file

@ -183,7 +183,7 @@ def purge_processor(caller):
# something went wrong. Purge cmdset except default
caller.cmdset.clear()
caller.scripts.validate() # this will purge interactive mode
# caller.scripts.validate() # this will purge interactive mode
# -------------------------------------------------------------

View file

@ -3120,7 +3120,6 @@ class CmdScript(COMMAND_DEFAULT_CLASS):
% (script.get_display_name(caller), obj.get_display_name(caller))
)
script.stop()
obj.scripts.validate()
else: # rhs exists
if not self.switches:
# adding a new script, and starting it

View file

@ -436,7 +436,6 @@ class ScriptEvMore(EvMore):
"|wintval|n",
"|wnext|n",
"|wrept|n",
"|wdb",
"|wtypeclass|n",
"|wdesc|n",
align="r",
@ -448,9 +447,10 @@ class ScriptEvMore(EvMore):
nextrep = script.time_until_next_repeat()
if nextrep is None:
nextrep = "PAUSED" if script.db._paused_time else "--"
nextrep = script.db._paused_time
nextrep = f"PAUSED {int(nextrep)}s" if nextrep else "--"
else:
nextrep = "%ss" % nextrep
nextrep = f"{nextrep}s"
maxrepeat = script.repeats
remaining = script.remaining_repeats() or 0
@ -468,7 +468,6 @@ class ScriptEvMore(EvMore):
script.interval if script.interval > 0 else "--",
nextrep,
rept,
"*" if script.persistent else "-",
script.typeclass_path.rsplit(".", 1)[-1],
crop(script.desc, width=20),
)
@ -487,7 +486,6 @@ class CmdScripts(COMMAND_DEFAULT_CLASS):
start - start a script (must supply a script path)
stop - stops an existing script
kill - kills a script - without running its cleanup hooks
validate - run a validation on the script(s)
If no switches are given, this command just views all active
scripts. The argument can be either an object, at which point it
@ -500,7 +498,7 @@ class CmdScripts(COMMAND_DEFAULT_CLASS):
key = "scripts"
aliases = ["globalscript", "listscripts"]
switch_options = ("start", "stop", "kill", "validate")
switch_options = ("start", "stop", "kill")
locks = "cmd:perm(listscripts) or perm(Admin)"
help_category = "System"
@ -558,18 +556,11 @@ class CmdScripts(COMMAND_DEFAULT_CLASS):
scripts[0].stop()
# import pdb # DEBUG
# pdb.set_trace() # DEBUG
ScriptDB.objects.validate() # just to be sure all is synced
caller.msg(string)
else:
# multiple matches.
ScriptEvMore(caller, scripts, session=self.session)
caller.msg("Multiple script matches. Please refine your search")
elif self.switches and self.switches[0] in ("validate", "valid", "val"):
# run validation on all found scripts
nr_started, nr_stopped = ScriptDB.objects.validate(scripts=scripts)
string = "Validated %s scripts. " % ScriptDB.objects.all().count()
string += "Started %s and stopped %s scripts." % (nr_started, nr_stopped)
caller.msg(string)
else:
# No stopping or validation. We just want to view things.
ScriptEvMore(caller, scripts.order_by("id"), session=self.session)

View file

@ -1163,8 +1163,8 @@ class TestBuilding(CommandTest):
self.call(building.CmdScript(), "Obj ", "dbref ")
self.call(
building.CmdScript(), "/start Obj", "0 scripts started on Obj"
) # because it's already started
building.CmdScript(), "/start Obj", "1 scripts started on Obj"
) # we allow running start again; this should still happen
self.call(building.CmdScript(), "/stop Obj", "Stopping script")
self.call(
@ -1520,7 +1520,10 @@ class TestComms(CommandTest):
class TestBatchProcess(CommandTest):
def test_batch_commands(self):
@patch("evennia.contrib.tutorial_examples.red_button.repeat")
@patch("evennia.contrib.tutorial_examples.red_button.delay")
def test_batch_commands(self, mock_delay, mock_repeat):
# cannot test batchcode here, it must run inside the server process
self.call(
batchprocess.CmdBatchCommands(),
@ -1532,6 +1535,7 @@ class TestBatchProcess(CommandTest):
building.CmdDestroy.confirm = False
self.call(building.CmdDestroy(), "button", "button was destroyed.")
building.CmdDestroy.confirm = confirm
mock_repeat.assert_called()
class CmdInterrupt(Command):