/circuits/io/notify.py
Python | 106 lines | 80 code | 19 blank | 7 comment | 12 complexity | c47c8df4001ba5a785315768a5af65e6 MD5 | raw file
1# Module: notify 2# Date: 2nd March 2009 3# Author: James Mills, prologic at shortcircuit dot net dot au 4 5"""File Notification Support 6 7A Component wrapping the inotify API using the pyinotify library. 8""" 9 10try: 11 from pyinotify import IN_UNMOUNT 12 from pyinotify import WatchManager, Notifier, ALL_EVENTS 13 from pyinotify import IN_ACCESS, IN_MODIFY, IN_ATTRIB, IN_CLOSE_WRITE 14 from pyinotify import IN_CREATE, IN_DELETE, IN_DELETE_SELF, IN_MOVE_SELF 15 from pyinotify import IN_CLOSE_NOWRITE, IN_OPEN, IN_MOVED_FROM, IN_MOVED_TO 16except ImportError: 17 raise Exception("No pyinotify support available. Is pyinotify installed?") 18 19from circuits.core.utils import findcmp 20from circuits.core import handler, BaseComponent 21from circuits.core.pollers import BasePoller, Poller 22 23from .events import accessed, closed, created, deleted, modified, moved, opened, ready, unmounted 24 25MASK = ALL_EVENTS 26 27EVENT_MAP = { 28 IN_MOVED_TO: moved, 29 IN_MOVE_SELF: moved, 30 IN_MOVED_FROM: moved, 31 IN_CLOSE_WRITE: closed, 32 IN_CLOSE_NOWRITE: closed, 33 IN_OPEN: opened, 34 IN_DELETE_SELF: deleted, 35 IN_DELETE: deleted, 36 IN_CREATE: created, 37 IN_ACCESS: accessed, 38 IN_MODIFY: modified, 39 IN_ATTRIB: modified, 40 IN_UNMOUNT: unmounted, 41} 42 43 44class Notify(BaseComponent): 45 46 channel = "notify" 47 48 def __init__(self, channel=channel): 49 super(Notify, self).__init__(channel=channel) 50 51 self._poller = None 52 self._wm = WatchManager() 53 self._notifier = Notifier(self._wm, self._on_process_events) 54 55 def _on_process_events(self, event): 56 dir = event.dir 57 mask = event.mask 58 path = event.path 59 name = event.name 60 pathname = event.pathname 61 62 for k, v in EVENT_MAP.items(): 63 if mask & k: 64 self.fire(v(name, path, pathname, dir)) 65 66 def add_path(self, path, mask=None, recursive=False): 67 mask = mask or MASK 68 self._wm.add_watch(path, mask, rec=recursive) 69 70 def remove_path(self, path, recursive=False): 71 wd = self._wm.get_wd(path) 72 if wd: 73 self._wm.rm_watch(wd, rec=recursive) 74 75 @handler("ready") 76 def _on_ready(self, component): 77 self._poller.addReader(self, self._notifier._fd) 78 79 @handler("registered", channel="*") 80 def _on_registered(self, component, manager): 81 if self._poller is None: 82 if isinstance(component, BasePoller): 83 self._poller = component 84 self.fire(ready(self)) 85 else: 86 if component is not self: 87 return 88 component = findcmp(self.root, BasePoller) 89 if component is not None: 90 self._poller = component 91 self.fire(ready(self)) 92 else: 93 self._poller = Poller().register(self) 94 self.fire(ready(self)) 95 96 @handler("started", channel="*", priority=1) 97 def _on_started(self, event, component): 98 if self._poller is None: 99 self._poller = Poller().register(self) 100 self.fire(ready(self)) 101 event.stop() 102 103 @handler("_read", priority=1) 104 def __on_read(self, fd): 105 self._notifier.read_events() 106 self._notifier.process_events()