baseimage-tutorial-framework/lib/tfw/components/directory_monitor.py
2018-03-20 11:31:29 +01:00

132 lines
3.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
from os.path import exists, isdir
from tfw.networking.event_handlers.server_connector import ServerUplinkConnector
from tfw.components.decorators import RateLimiter
from tfw.event_handler_base import TriggerlessEventHandler
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.observer.schedule(self.eventhandler, directory, recursive=True)
self.pause, self.resume = self.eventhandler.pause, self.eventhandler.resume
def watch(self):
self.observer.start()
def stop(self):
self.observer.stop()
self.observer.join()
@property
def ignore(self):
return self.eventhandler.ignore
@ignore.setter
def ignore(self, value):
self.eventhandler.ignore = value if value >= 0 else 0
@property
def pauser(self):
return DirectoryMonitor.Pauser(self)
class Pauser:
def __init__(self, directory_monitor):
self.directorymonitor = directory_monitor
def __enter__(self):
self.directorymonitor.pause()
def __exit__(self, exc_type, exc_val, exc_tb):
self.directorymonitor.resume()
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('DirManagingEH failed to switch directory!')
def cleanup(self):
self.monitor.stop()