+# watcher.py - high-level interfaces to the Linux inotify subsystem
+# Copyright 2006 Bryan O'Sullivan <email@example.com>
+# This library is free software; you can redistribute it and/or modify
+# it under the terms of version 2.1 of the GNU Lesser General Public
+# License, incorporated herein by reference.
'''High-level interfaces to the Linux inotify subsystem.
The inotify subsystem provides an efficient mechanism for file status
monitoring and change notification.
BasicWatcher class hides the low-level details of the inotify
+The Watcher class hides the low-level details of the inotify
interface, and provides a Pythonic wrapper around it. It generates
events that provide somewhat more information than raw inotify makes
The following fields are available:
+ mask: event mask, indicating what kind of event this is
+ cookie: rename cookie, if a rename-related event
path: path of the directory in which the event occurred
name: name of the directory entry to which the event occurred
+ (may be None)
fullpath: complete path at which the event occurred
- wd: watch descriptor that triggered this event
+ wd: watch descriptor that triggered this event'''
return 'Event(path=' + repr(self.path) + ', ' + r[r.find('(')+1:]
+ 'access': 'File was accessed',
+ 'modify': 'File was modified',
+ 'attrib': 'Attribute of a directory entry was changed',
+ 'close_write': 'File was closed after being written to',
+ 'close_nowrite': 'File was closed without being written to',
+ 'open': 'File was opened',
+ 'moved_from': 'Directory entry was renamed from this name',
+ 'moved_to': 'Directory entry was renamed to this name',
+ 'create': 'Directory entry was created',
+ 'delete': 'Directory entry was deleted',
+ 'delete_self': 'The watched directory entry was deleted',
+ 'move_self': 'The watched directory entry was renamed',
+ 'unmount': 'Directory was unmounted, and can no longer be watched',
+ 'q_overflow': 'Kernel dropped events due to queue overflow',
+ 'ignored': 'Directory entry is no longer being watched',
+ 'isdir': 'Event occurred on a directory',
+for k, v in _event_props.iteritems():
+ mask = getattr(inotify, 'IN_' + k.upper())
+ return self.mask & mask
+ setattr(Event, k, property(getter, doc=v))
'''Provide a Pythonic interface to the low-level inotify API.
- Also adds derived information to events that is not available
- through the normal inotify API, such as directory names.'''
+ Also adds derived information to each event that is not available
+ through the normal inotify API, such as directory name.'''
- '''Yield a (path, watch descriptor, vent mask) tuple for each entry.'''
+ '''Yield a (path, watch descriptor, event mask) tuple for each
+ entry being watched.'''
for path, (wd, mask) in self._paths.iteritems():
def add_all(self, path, mask, onerror=None):
+ '''Add or modify watches over path and its subdirectories.
+ Return a list of added or modified watch descriptors.
+ By default, errors are ignored. If optional arg "onerror" is
+ specified, it should be a function; it will be called with one
+ argument, an OSError instance. It can report the error to
+ continue with the walk, or raise the exception to abort the
return [w for w in self.add_iter(path, mask, onerror)]
'''Watcher class that automatically watches newly created directories.'''
+ '''Class that indicates whether a file descriptor has reached a
+ threshold of readable bytes available.
+ This class is not thread-safe.'''
self._iocbuf = array.array('i', )
+ '''Return the number of bytes readable on this file descriptor.'''
fcntl.ioctl(self.fd, termios.FIONREAD, self._iocbuf, True)
+ '''Indicate whether the number of readable bytes has met or
+ exceeded the threshold.'''
return self.readable() >= self.threshold