diff --git a/evennia/scripts/taskhandler.py b/evennia/scripts/taskhandler.py index 6c648b3360..eceb61a1cf 100644 --- a/evennia/scripts/taskhandler.py +++ b/evennia/scripts/taskhandler.py @@ -256,7 +256,6 @@ class TaskHandler(object): else: return False - def cancel(self, task_id): """ Stop a task from automatically executing. @@ -298,7 +297,7 @@ class TaskHandler(object): Returns: True (bool): if the removal completed successfully or if the a task with the id does not exist. - None, if there was a raised exception + None: if there was a raised exception """ d = None @@ -317,22 +316,41 @@ class TaskHandler(object): return True def do_task(self, task_id): - """Execute the task (call its callback). + """ + Execute the task (call its callback). + If calling before timedelay cancel the deferral affliated to this task. + Remove the task from the dictionary of current tasks on a successful + callback. Args: task_id (int): a valid task ID. + Returns: + False (bool): if the: + task no longer exists, + has no affliated instance of deferral + The return of the callback passed on task creation. + This makes it possible for the callback to also return False + None: if there was a raised exception + Note: - This will also remove it from the list of current tasks. + On a successful call the task will be removed from the dictionary + of current tasks. """ - date, callback, args, kwargs, persistent, d = self.tasks.pop(task_id) - - if task_id in self.to_save: - del self.to_save[task_id] - - self.save() - callback(*args, **kwargs) + callback_return = False + if task_id in self.tasks: + date, callback, args, kwargs, persistent, d = self.tasks.get(task_id) + else: # the task does not exist + return False + if d: # it is remotely possible for a task to not have a deferral + if not d.called: # the task has not been called yet + d.cancel() # cancel the automated callback + else: # this task has no deferral, and should not be called + return False + callback_return = callback(*args, **kwargs) + self.remove(task_id) + return callback_return def get_deferred(self, task_id): """ diff --git a/evennia/utils/tests/test_utils.py b/evennia/utils/tests/test_utils.py index c5bf20d032..8de5ef1900 100644 --- a/evennia/utils/tests/test_utils.py +++ b/evennia/utils/tests/test_utils.py @@ -314,6 +314,7 @@ def dummy_func(obj): obj = obj[0] # make changes to object obj.ndb.dummy_var = 'dummy_func ran' + return True class TestDelay(EvenniaTest): @@ -335,12 +336,30 @@ class TestDelay(EvenniaTest): _TASK_HANDLER.clock.advance(timedelay) # make time pass self.assertEqual(self.char1.ndb.dummy_var, 'dummy_func ran') self.char1.ndb.dummy_var = False + # test a persistent deferral, that completes on a manual call + task_id = utils.delay(timedelay, dummy_func, self.char1.dbref, persistent=True) + self.assertTrue(_TASK_HANDLER.active(task_id)) + result = _TASK_HANDLER.do_task(task_id) + self.assertTrue(result) + self.assertFalse(_TASK_HANDLER.exists(task_id)) + _TASK_HANDLER.clock.advance(timedelay) # make time pass, important keep + self.assertEqual(self.char1.ndb.dummy_var, 'dummy_func ran') + self.char1.ndb.dummy_var = False # test a non persisten deferral, that completes after delay time. utils.delay(timedelay, dummy_func, self.char1.dbref) self.assertTrue(_TASK_HANDLER.active(task_id)) _TASK_HANDLER.clock.advance(timedelay) # make time pass self.assertEqual(self.char1.ndb.dummy_var, 'dummy_func ran') self.char1.ndb.dummy_var = False + # test a non-persistent deferral, that completes on a manual call + task_id = utils.delay(timedelay, dummy_func, self.char1.dbref) + self.assertTrue(_TASK_HANDLER.active(task_id)) + result = _TASK_HANDLER.do_task(task_id) + self.assertTrue(result) + self.assertFalse(_TASK_HANDLER.exists(task_id)) + _TASK_HANDLER.clock.advance(timedelay) # make time pass, important keep + self.assertEqual(self.char1.ndb.dummy_var, 'dummy_func ran') + self.char1.ndb.dummy_var = False # test a non persisten deferral, with a short timedelay utils.delay(.1, dummy_func, self.char1.dbref) self.assertTrue(_TASK_HANDLER.active(task_id)) @@ -367,7 +386,7 @@ class TestDelay(EvenniaTest): self.assertEqual(self.char1.ndb.dummy_var, False) self.assertFalse(_TASK_HANDLER.exists(task_id)) self.char1.ndb.dummy_var = False - # test removing a canceled active task + # test removing a canceled task task_id = utils.delay(timedelay, dummy_func, self.char1.dbref) self.assertTrue(_TASK_HANDLER.active(task_id)) deferal_inst = _TASK_HANDLER.get_deferred(task_id)