/circuits/io/notify.py

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