PageRenderTime 12ms CodeModel.GetById 2ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms

/circuits/io/notify.py

https://bitbucket.org/prologic/circuits/
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()