diff --git a/lib/tfw/components/directory_monitor.py b/lib/tfw/components/directory_monitor.py index 1493133..64d5c23 100644 --- a/lib/tfw/components/directory_monitor.py +++ b/lib/tfw/components/directory_monitor.py @@ -1,5 +1,5 @@ from watchdog.observers import Observer -from watchdog.events import FileSystemEventHandler +from watchdog.events import FileSystemEventHandler as FileSystemWatchdogEventHandler from tfw.networking.event_handlers.server_connector import ServerUplinkConnector from tfw.components.decorators import RateLimiter @@ -8,34 +8,10 @@ from tfw.config.logs import logging log = logging.getLogger(__name__) -class WebideReloadEventHandler(FileSystemEventHandler): - def __init__(self): - super().__init__() - self.uplink = ServerUplinkConnector() - self._paused = False - self.ignore = 0 - - def pause(self): - self._paused = True - - def resume(self): - self._paused = False - - @RateLimiter(rate_per_second=5) - def on_modified(self, event): - if self._paused: return - if self.ignore > 0: - self.ignore = self.ignore - 1 - return - log.debug(event) - key = 'webide' - self.uplink.send(key, {'data': {'command': 'reload'}}) - - class DirectoryMonitor: def __init__(self, directory): self.observer = Observer() - self.eventhandler = WebideReloadEventHandler() + self.eventhandler = WebideReloadWatchdogEventHandler() self.observer.schedule(self.eventhandler, directory, recursive=True) self.pause, self.resume = self.eventhandler.pause, self.eventhandler.resume @@ -52,7 +28,7 @@ class DirectoryMonitor: @ignore.setter def ignore(self, value): - self.ignore = value if value >= 0 else 0 + self.eventhandler.ignore = value if value >= 0 else 0 @property def pauser(self): @@ -65,3 +41,27 @@ class DirectoryMonitor: self.directorymonitor.pause() def __exit__(self, exc_type, exc_val, exc_tb): self.directorymonitor.resume() + + +class WebideReloadWatchdogEventHandler(FileSystemWatchdogEventHandler): + def __init__(self): + super().__init__() + self.uplink = ServerUplinkConnector() + self._paused = False + self.ignore = 0 + + def pause(self): + self._paused = True + + def resume(self): + self._paused = False + + @RateLimiter(rate_per_second=2) + def on_modified(self, event): + if self._paused: return + if self.ignore > 0: + self.ignore = self.ignore - 1 + return + log.debug(event) + key = 'webide' + self.uplink.send(key, {'data': {'command': 'reload'}}) diff --git a/lib/tfw/components/directory_monitoring_event_handler.py b/lib/tfw/components/directory_monitoring_event_handler.py new file mode 100644 index 0000000..afceaaf --- /dev/null +++ b/lib/tfw/components/directory_monitoring_event_handler.py @@ -0,0 +1,68 @@ +from os.path import isdir, exists + +from tfw.components.directory_monitor import DirectoryMonitor +from tfw.event_handler_base import TriggerlessEventHandler +from tfw.config.logs import logging +log = logging.getLogger(__name__) + + +class DirectoryMonitoringEventHandler(TriggerlessEventHandler): + def __init__(self, key, directory): + super().__init__(key) + self._directory = directory + self._monitor = None + self.reload_monitor() + self.commands = {'pause': self.pause, + 'resume': self.resume, + 'ignore': self.ignore, + 'selectdir': self.selectdir} + + @property + def directory(self): + return self._directory + + @directory.setter + def directory(self, directory): + if not exists(directory) or not isdir(directory): raise EnvironmentError('No such directory!') + self._directory = directory + + @property + def monitor(self): + return self._monitor + + def reload_monitor(self): + if self._monitor: + try: self._monitor.stop() + except KeyError: logging.debug('Working directory was removed – ignoring...') + self._monitor = DirectoryMonitor(self._directory) + self._monitor.watch() # This runs on a separate thread + + def handle_event(self, key, message): + try: + message['data'] = self.commands[message['data']['command']](message['data']) + return message + except KeyError: + log.error('IGNORING MESSAGE: Invalid message received: {}'.format(message)) + + def pause(self, data): + self.monitor.pause() + return data + + def resume(self, data): + self.monitor.resume() + return data + + def ignore(self, data): + self.monitor.ignore += data['ignore'] + return data + + def selectdir(self, data): + try: + self.directory = data['directory'] + self.reload_monitor() + return data + except EnvironmentError: + log.error('Failed to switch directory!') + + def cleanup(self): + self.monitor.stop() diff --git a/lib/tfw/components/source_code_event_handler.py b/lib/tfw/components/source_code_event_handler.py index 760b28b..8986bf2 100644 --- a/lib/tfw/components/source_code_event_handler.py +++ b/lib/tfw/components/source_code_event_handler.py @@ -102,7 +102,7 @@ class SourceCodeEventHandler(TriggerlessEventHandler): return data def write(self, data): - self.monitor.eventhandler.ignore = 1 + self.monitor.ignore = self.monitor.ignore + 1 try: self.filemanager.file_contents = data['content'] except Exception: log.exception('Error writing file!') del data['content']