From 482658529b5a809bc2464e5f0032938761c3d5a3 Mon Sep 17 00:00:00 2001 From: Valentin Lorentz Date: Sat, 2 May 2020 20:02:06 +0200 Subject: [PATCH] Scheduler: Add --delay option, to add an offset before the first run. Closes GH-397. --- plugins/Scheduler/plugin.py | 26 +++++++++++++------------- plugins/Scheduler/test.py | 11 +++++++++++ 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/plugins/Scheduler/plugin.py b/plugins/Scheduler/plugin.py index af33b499c..74483d3fb 100644 --- a/plugins/Scheduler/plugin.py +++ b/plugins/Scheduler/plugin.py @@ -188,17 +188,11 @@ class Scheduler(callbacks.Plugin): irc.error(_('Invalid event id.')) remove = wrap(remove, ['lowered']) - def _repeat(self, irc, msg, name, seconds, command, first_run=None, next_run_in=None): + def _repeat(self, irc, msg, name, seconds, command, first_run, next_run_in): f = self._makeCommandFunction(irc, msg, command, remove=False) f_wrapper = schedule.schedule.makePeriodicWrapper(f, seconds, name) - if next_run_in is None: - assert first_run is None - # run immediately - id = f_wrapper() - first_run = time.time() - else: - assert first_run is not None - id = schedule.addEvent(f_wrapper, time.time() + next_run_in, name) + assert first_run is not None + id = schedule.addEvent(f_wrapper, time.time() + next_run_in, name) assert id == name self.events[name] = {'command':command, 'msg':msg, @@ -208,23 +202,29 @@ class Scheduler(callbacks.Plugin): } @internationalizeDocstring - def repeat(self, irc, msg, args, name, seconds, command): - """ + def repeat(self, irc, msg, args, optlist, name, seconds, command): + """[--delay ] Schedules the command to run every seconds, starting now (i.e., the command runs now, and every seconds thereafter). is a name by which the command can be unscheduled. + If --delay is given, starts in seconds instead of now. """ + opts = dict(optlist) name = name.lower() if name in self.events: irc.error(_('There is already an event with that name, please ' 'choose another name.'), Raise=True) - self._repeat(irc, msg, name, seconds, command) + next_run_in = opts.get('delay', 0) + first_run = time.time() + next_run_in + self._repeat(irc, msg, name, seconds, command, first_run, next_run_in) # We don't reply because the command runs immediately. # But should we? What if the command doesn't have visible output? # irc.replySuccess() - repeat = wrap(repeat, ['nonInt', 'positiveInt', 'text']) + repeat = wrap(repeat, [ + getopts({'delay': 'positiveInt'}), + 'nonInt', 'positiveInt', 'text']) @internationalizeDocstring def list(self, irc, msg, args): diff --git a/plugins/Scheduler/test.py b/plugins/Scheduler/test.py index 660c373f5..fd92d1bea 100644 --- a/plugins/Scheduler/test.py +++ b/plugins/Scheduler/test.py @@ -87,6 +87,17 @@ class SchedulerTestCase(ChannelPluginTestCase): timeFastForward(5) self.assertNoResponse(' ', timeout=1) + def testRepeatDelay(self): + self.assertNoResponse( + 'scheduler repeat --delay 5 repeater 20 echo testRepeat', + timeout=1) + timeFastForward(5) + self.assertResponse(' ', 'testRepeat', timeout=1) + timeFastForward(17) + self.assertNoResponse(' ', timeout=1) + timeFastForward(5) + self.assertResponse(' ', 'testRepeat', timeout=1) + def testRepeatWorksWithNestedCommands(self): self.assertRegexp('scheduler repeat foo 5 "echo foo [echo nested]"', 'foo nested')