From 603baa85814833d9cfc3921b005115bffecf3fe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9munaire?= Date: Thu, 16 Aug 2012 04:32:47 +0200 Subject: [PATCH] Simplify the listen function creation and management --- bot.py | 43 +++++++++++++++++++++++ event.py | 88 ++++++++++++++++++++++++++++++++++++------------ modules/velib.py | 3 +- 3 files changed, 110 insertions(+), 24 deletions(-) diff --git a/bot.py b/bot.py index a57b341..5eb8d85 100644 --- a/bot.py +++ b/bot.py @@ -16,6 +16,9 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +from datetime import datetime +import threading + import event import hooks from server import Server @@ -33,6 +36,46 @@ class Bot: self.hooks = hooks.MessagesHook() self.events = list() + self.event_timer = None + + + def add_event(self, evt): + # Add the event in place + t = evt.current + i = 0 + for i in range(0, len(self.events)): + if self.events[i].current > t: + break + self.events.insert(i, evt) + if i == 0: + self.update_timer() + + def update_timer(self): + # Reset the timer if this is the first item + if self.event_timer is not None: + self.event_timer.cancel() + if len(self.events) > 0: + #print ("Update timer, next in", self.events[0].time_left.seconds, + # "seconds") + if datetime.now() >= self.events[0].current: + self.end_timer() + else: + self.event_timer = threading.Timer( + self.events[0].time_left.seconds + 1, self.end_timer) + self.event_timer.start() + #else: + # print ("Update timer: no timer left") + + + def end_timer(self): + #print ("end timer") + while len(self.events)>0 and datetime.now() >= self.events[0].current: + #print ("end timer: while") + evt = self.events.pop(0) + evt.launch_check() + if evt.next is not None: + self.add_event(evt) + self.update_timer() def addServer(self, node, nick, owner, realname): diff --git a/event.py b/event.py index ccba1d1..f1137d4 100644 --- a/event.py +++ b/event.py @@ -16,11 +16,12 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -import threading +from datetime import datetime +from datetime import timedelta class ModuleEvent: - def __init__(self, func, func_data, check, cmp_data, intervalle=60, - call=None, call_data=None, times=1): + def __init__(self, func=None, func_data=None, check=None, cmp_data=None, + intervalle=60, call=None, call_data=None, times=1): # What have we to check? self.func = func self.func_data = func_data @@ -29,10 +30,16 @@ class ModuleEvent: self.check = check if cmp_data is not None: self.cmp_data = cmp_data - else: - self.cmp_data = self.func(self.func_data) + elif self.func is not None: + if self.func_data is None: + self.cmp_data = self.func() + elif isinstance(self.func_data, dict): + self.cmp_data = self.func(**self.func_data) + else: + self.cmp_data = self.func(self.func_data) - self.intervalle = intervalle + self.intervalle = timedelta(seconds=intervalle) + self.end = None # What should we call when self.call = call @@ -45,21 +52,58 @@ class ModuleEvent: self.times = times - def launch_check(self): - d = self.func(self.func_data) - #print ("do test with", d, self.cmp_data) - if self.check(d, self.cmp_data): - self.call(self.call_data) - self.times -= 1 - self.run() - - def run(self): + @property + def next(self): + """Return the date of the next check""" if self.times != 0: - #print ("run timer") - self.timer = threading.Timer(self.intervalle, self.launch_check) - self.timer.start() - #else: - #print ("no more times") + if self.end is None: + self.end = datetime.now() + self.intervalle + elif self.end < datetime.now(): + self.end += self.intervalle + return self.end + return None - def stop(self): - self.timer.cancel() + @property + def current(self): + """Return the date of the near check""" + if self.times != 0: + if self.end is None: + self.end = datetime.now() + self.intervalle + return self.end + return None + + @property + def time_left(self): + """Return the time left before/after the near check""" + if self.current is not None: + return self.current - datetime.now() + return 99999 + + def launch_check(self): + if self.func is None: + d = self.func_data + elif self.func_data is None: + d = self.func() + elif isinstance(self.func_data, dict): + d = self.func(**self.func_data) + else: + d = self.func(self.func_data) + #print ("do test with", d, self.cmp_data) + + if self.check is None: + r = True + elif self.cmp_data is None: + r = self.check(d) + elif isinstance(self.cmp_data, dict): + r = self.check(d, **self.cmp_data) + else: + r = self.check(d, self.cmp_data) + + if r: + self.times -= 1 + if self.call_data is None: + self.call() + elif isinstance(self.call_data, dict): + self.call(**self.call_data) + else: + self.call(self.call_data) diff --git a/modules/velib.py b/modules/velib.py index ca9915f..51e3540 100644 --- a/modules/velib.py +++ b/modules/velib.py @@ -16,8 +16,7 @@ def load(context): evt = ModuleEvent(station_available, "42706", (lambda a, b: a != b), None, 60, station_status) - context.events.append(evt) - evt.run() + context.add_event(evt) def help_tiny (): """Line inserted in the response to the command !help"""