From 6a6236e704ce67e174479a766331a76944dced17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20T=C3=B3th?= Date: Wed, 7 Mar 2018 10:12:58 +0100 Subject: [PATCH] Refactor callback subscription stuff to a mixin --- lib/tfw/components/history_monitor.py | 13 +++++-------- lib/tfw/components/mixins/callback_mixin.py | 17 +++++++++++++++++ lib/tfw/fsm_base.py | 16 +++++----------- lib/tfw/networking/server/tfw_server.py | 2 +- src/demo/event_handler_main.py | 2 +- 5 files changed, 29 insertions(+), 21 deletions(-) create mode 100644 lib/tfw/components/mixins/callback_mixin.py diff --git a/lib/tfw/components/history_monitor.py b/lib/tfw/components/history_monitor.py index f07a57b..9d8abf6 100644 --- a/lib/tfw/components/history_monitor.py +++ b/lib/tfw/components/history_monitor.py @@ -2,6 +2,8 @@ from watchdog.observers import Observer from watchdog.events import PatternMatchingEventHandler from os.path import dirname +from tfw.components.mixins.callback_mixin import CallbackMixin + class CallbackEventHandler(PatternMatchingEventHandler): def __init__(self, files, *callbacks): @@ -13,12 +15,12 @@ class CallbackEventHandler(PatternMatchingEventHandler): callback() -class HistoryMonitor: +class HistoryMonitor(CallbackMixin): def __init__(self, histfile): + CallbackMixin.__init__(self) self.histfile = histfile self._history = [] self._last_length = len(self._history) - self._callbacks = [] self.observer = Observer() self.observer.schedule(CallbackEventHandler([self.histfile], self._fetch_history, @@ -29,10 +31,6 @@ class HistoryMonitor: def history(self): return self._history - @property - def callbacks(self): - return self._callbacks - def _fetch_history(self): self._last_length = len(self._history) with open(self.histfile, 'r') as ifile: @@ -40,8 +38,7 @@ class HistoryMonitor: def _invoke_callbacks(self): if self._last_length < len(self._history): - for callback in self.callbacks: - callback(self.history) + self._execute_callbacks(self.history) def watch(self): self.observer.start() diff --git a/lib/tfw/components/mixins/callback_mixin.py b/lib/tfw/components/mixins/callback_mixin.py new file mode 100644 index 0000000..c7a97b0 --- /dev/null +++ b/lib/tfw/components/mixins/callback_mixin.py @@ -0,0 +1,17 @@ +from functools import partial + + +class CallbackMixin: + def __init__(self): + self._callbacks = [] + + def subscribe_callback(self, callback, *args, **kwargs): + fun = partial(callback, *args, **kwargs) + self._callbacks.append(fun) + + def unsubscribe_callback(self, callback): + self._callbacks.remove(callback) + + def _execute_callbacks(self, *args, **kwargs): + for callback in self._callbacks: + callback(*args, **kwargs) diff --git a/lib/tfw/fsm_base.py b/lib/tfw/fsm_base.py index 04494e6..b46a563 100644 --- a/lib/tfw/fsm_base.py +++ b/lib/tfw/fsm_base.py @@ -1,13 +1,14 @@ from typing import List - from transitions import Machine +from tfw.components.mixins.callback_mixin import CallbackMixin -class FSMBase: + +class FSMBase(CallbackMixin): states, transitions = [], [] def __init__(self, initial: str = None, accepted_states: List[str] = None): - self.callbacks = [] + CallbackMixin.__init__(self) self.accepted_states = accepted_states or [self.states[-1]] self.machine = Machine(model=self, states=self.states, @@ -18,14 +19,7 @@ class FSMBase: after_state_change='execute_callbacks') def execute_callbacks(self, event_data): - for callback in self.callbacks: - callback(event_data.kwargs) - - def subscribe(self, callback): - self.callbacks.append(callback) - - def unsubscribe(self, callback): - self.callbacks.remove(callback) + self._execute_callbacks(event_data.kwargs) def is_solved(self): return self.state in self.accepted_states diff --git a/lib/tfw/networking/server/tfw_server.py b/lib/tfw/networking/server/tfw_server.py index 8b7d1f3..b076f9f 100644 --- a/lib/tfw/networking/server/tfw_server.py +++ b/lib/tfw/networking/server/tfw_server.py @@ -14,7 +14,7 @@ class TFWServer: self._fsm = fsm_type() self._fsm_updater = FSMUpdater(self._fsm) self._fsm_manager = FSMManager(self._fsm) - self._fsm.subscribe(self._fsm_updater.update) + self._fsm.subscribe_callback(self._fsm_updater.update) self.application = Application( [(r'/ws', ZMQWebSocketProxy, {'make_response': self.make_response, diff --git a/src/demo/event_handler_main.py b/src/demo/event_handler_main.py index 8500d09..9d5976c 100644 --- a/src/demo/event_handler_main.py +++ b/src/demo/event_handler_main.py @@ -11,7 +11,7 @@ log = logging.getLogger(__name__) if __name__ == '__main__': ide = SourceCodeEventHandler('webide', tfwenv.WEBIDE_WD) terminado = TerminadoEventHandler('shell') - terminado.historymonitor.callbacks.append(lambda hist: log.debug('User executed command: "{}"'.format(hist[-1]))) + terminado.historymonitor.subscribe_callback(lambda hist: log.debug('User executed command: "{}"'.format(hist[-1]))) processmanager = ProcessManagingEventHandler('processmanager', ide.monitor) eventhandlers = {ide, terminado, processmanager}