diff options
Diffstat (limited to 'lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/internet/inotify.py')
-rwxr-xr-x | lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/internet/inotify.py | 405 |
1 files changed, 0 insertions, 405 deletions
diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/internet/inotify.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/internet/inotify.py deleted file mode 100755 index 85305dcb..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/internet/inotify.py +++ /dev/null @@ -1,405 +0,0 @@ -# -*- test-case-name: twisted.internet.test.test_inotify -*- -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -""" -This module provides support for Twisted to linux inotify API. - -In order to use this support, simply do the following (and start a reactor -at some point):: - - from twisted.internet import inotify - from twisted.python import filepath - - def notify(ignored, filepath, mask): - \""" - For historical reasons, an opaque handle is passed as first - parameter. This object should never be used. - - @param filepath: FilePath on which the event happened. - @param mask: inotify event as hexadecimal masks - \""" - print "event %s on %s" % ( - ', '.join(inotify.humanReadableMask(mask)), filepath) - - notifier = inotify.INotify() - notifier.startReading() - notifier.watch(filepath.FilePath("/some/directory"), callbacks=[notify]) - -@since: 10.1 -""" - -import os -import struct - -from twisted.internet import fdesc -from twisted.internet.abstract import FileDescriptor -from twisted.python import log, _inotify - - -# from /usr/src/linux/include/linux/inotify.h - -IN_ACCESS = 0x00000001L # File was accessed -IN_MODIFY = 0x00000002L # File was modified -IN_ATTRIB = 0x00000004L # Metadata changed -IN_CLOSE_WRITE = 0x00000008L # Writeable file was closed -IN_CLOSE_NOWRITE = 0x00000010L # Unwriteable file closed -IN_OPEN = 0x00000020L # File was opened -IN_MOVED_FROM = 0x00000040L # File was moved from X -IN_MOVED_TO = 0x00000080L # File was moved to Y -IN_CREATE = 0x00000100L # Subfile was created -IN_DELETE = 0x00000200L # Subfile was delete -IN_DELETE_SELF = 0x00000400L # Self was deleted -IN_MOVE_SELF = 0x00000800L # Self was moved -IN_UNMOUNT = 0x00002000L # Backing fs was unmounted -IN_Q_OVERFLOW = 0x00004000L # Event queued overflowed -IN_IGNORED = 0x00008000L # File was ignored - -IN_ONLYDIR = 0x01000000 # only watch the path if it is a directory -IN_DONT_FOLLOW = 0x02000000 # don't follow a sym link -IN_MASK_ADD = 0x20000000 # add to the mask of an already existing watch -IN_ISDIR = 0x40000000 # event occurred against dir -IN_ONESHOT = 0x80000000 # only send event once - -IN_CLOSE = IN_CLOSE_WRITE | IN_CLOSE_NOWRITE # closes -IN_MOVED = IN_MOVED_FROM | IN_MOVED_TO # moves -IN_CHANGED = IN_MODIFY | IN_ATTRIB # changes - -IN_WATCH_MASK = (IN_MODIFY | IN_ATTRIB | - IN_CREATE | IN_DELETE | - IN_DELETE_SELF | IN_MOVE_SELF | - IN_UNMOUNT | IN_MOVED_FROM | IN_MOVED_TO) - - -_FLAG_TO_HUMAN = [ - (IN_ACCESS, 'access'), - (IN_MODIFY, 'modify'), - (IN_ATTRIB, 'attrib'), - (IN_CLOSE_WRITE, 'close_write'), - (IN_CLOSE_NOWRITE, 'close_nowrite'), - (IN_OPEN, 'open'), - (IN_MOVED_FROM, 'moved_from'), - (IN_MOVED_TO, 'moved_to'), - (IN_CREATE, 'create'), - (IN_DELETE, 'delete'), - (IN_DELETE_SELF, 'delete_self'), - (IN_MOVE_SELF, 'move_self'), - (IN_UNMOUNT, 'unmount'), - (IN_Q_OVERFLOW, 'queue_overflow'), - (IN_IGNORED, 'ignored'), - (IN_ONLYDIR, 'only_dir'), - (IN_DONT_FOLLOW, 'dont_follow'), - (IN_MASK_ADD, 'mask_add'), - (IN_ISDIR, 'is_dir'), - (IN_ONESHOT, 'one_shot') -] - - - -def humanReadableMask(mask): - """ - Auxiliary function that converts an hexadecimal mask into a series - of human readable flags. - """ - s = [] - for k, v in _FLAG_TO_HUMAN: - if k & mask: - s.append(v) - return s - - - -class _Watch(object): - """ - Watch object that represents a Watch point in the filesystem. The - user should let INotify to create these objects - - @ivar path: The path over which this watch point is monitoring - @ivar mask: The events monitored by this watchpoint - @ivar autoAdd: Flag that determines whether this watch point - should automatically add created subdirectories - @ivar callbacks: C{list} of callback functions that will be called - when an event occurs on this watch. - """ - def __init__(self, path, mask=IN_WATCH_MASK, autoAdd=False, - callbacks=None): - self.path = path - self.mask = mask - self.autoAdd = autoAdd - if callbacks is None: - callbacks = [] - self.callbacks = callbacks - - - def _notify(self, filepath, events): - """ - Callback function used by L{INotify} to dispatch an event. - """ - for callback in self.callbacks: - callback(self, filepath, events) - - - -class INotify(FileDescriptor, object): - """ - The INotify file descriptor, it basically does everything related - to INotify, from reading to notifying watch points. - - @ivar _buffer: a C{str} containing the data read from the inotify fd. - - @ivar _watchpoints: a C{dict} that maps from inotify watch ids to - watchpoints objects - - @ivar _watchpaths: a C{dict} that maps from watched paths to the - inotify watch ids - """ - _inotify = _inotify - - def __init__(self, reactor=None): - FileDescriptor.__init__(self, reactor=reactor) - - # Smart way to allow parametrization of libc so I can override - # it and test for the system errors. - self._fd = self._inotify.init() - - fdesc.setNonBlocking(self._fd) - fdesc._setCloseOnExec(self._fd) - - # The next 2 lines are needed to have self.loseConnection() - # to call connectionLost() on us. Since we already created the - # fd that talks to inotify we want to be notified even if we - # haven't yet started reading. - self.connected = 1 - self._writeDisconnected = True - - self._buffer = '' - self._watchpoints = {} - self._watchpaths = {} - - - def _addWatch(self, path, mask, autoAdd, callbacks): - """ - Private helper that abstracts the use of ctypes. - - Calls the internal inotify API and checks for any errors after the - call. If there's an error L{INotify._addWatch} can raise an - INotifyError. If there's no error it proceeds creating a watchpoint and - adding a watchpath for inverse lookup of the file descriptor from the - path. - """ - wd = self._inotify.add(self._fd, path.path, mask) - - iwp = _Watch(path, mask, autoAdd, callbacks) - - self._watchpoints[wd] = iwp - self._watchpaths[path] = wd - - return wd - - - def _rmWatch(self, wd): - """ - Private helper that abstracts the use of ctypes. - - Calls the internal inotify API to remove an fd from inotify then - removes the corresponding watchpoint from the internal mapping together - with the file descriptor from the watchpath. - """ - self._inotify.remove(self._fd, wd) - iwp = self._watchpoints.pop(wd) - self._watchpaths.pop(iwp.path) - - - def connectionLost(self, reason): - """ - Release the inotify file descriptor and do the necessary cleanup - """ - FileDescriptor.connectionLost(self, reason) - if self._fd >= 0: - try: - os.close(self._fd) - except OSError, e: - log.err(e, "Couldn't close INotify file descriptor.") - - - def fileno(self): - """ - Get the underlying file descriptor from this inotify observer. - Required by L{abstract.FileDescriptor} subclasses. - """ - return self._fd - - - def doRead(self): - """ - Read some data from the observed file descriptors - """ - fdesc.readFromFD(self._fd, self._doRead) - - - def _doRead(self, in_): - """ - Work on the data just read from the file descriptor. - """ - self._buffer += in_ - while len(self._buffer) >= 16: - - wd, mask, cookie, size = struct.unpack("=LLLL", self._buffer[0:16]) - - if size: - name = self._buffer[16:16 + size].rstrip('\0') - else: - name = None - - self._buffer = self._buffer[16 + size:] - - try: - iwp = self._watchpoints[wd] - except KeyError: - continue - - path = iwp.path - if name: - path = path.child(name) - iwp._notify(path, mask) - - if (iwp.autoAdd and mask & IN_ISDIR and mask & IN_CREATE): - # mask & IN_ISDIR already guarantees that the path is a - # directory. There's no way you can get here without a - # directory anyway, so no point in checking for that again. - new_wd = self.watch( - path, mask=iwp.mask, autoAdd=True, - callbacks=iwp.callbacks - ) - # This is very very very hacky and I'd rather not do this but - # we have no other alternative that is less hacky other than - # surrender. We use callLater because we don't want to have - # too many events waiting while we process these subdirs, we - # must always answer events as fast as possible or the overflow - # might come. - self.reactor.callLater(0, - self._addChildren, self._watchpoints[new_wd]) - if mask & IN_DELETE_SELF: - self._rmWatch(wd) - - - def _addChildren(self, iwp): - """ - This is a very private method, please don't even think about using it. - - Note that this is a fricking hack... it's because we cannot be fast - enough in adding a watch to a directory and so we basically end up - getting here too late if some operations have already been going on in - the subdir, we basically need to catchup. This eventually ends up - meaning that we generate double events, your app must be resistant. - """ - try: - listdir = iwp.path.children() - except OSError: - # Somebody or something (like a test) removed this directory while - # we were in the callLater(0...) waiting. It doesn't make sense to - # process it anymore - return - - # note that it's true that listdir will only see the subdirs inside - # path at the moment of the call but path is monitored already so if - # something is created we will receive an event. - for f in listdir: - # It's a directory, watch it and then add its children - if f.isdir(): - wd = self.watch( - f, mask=iwp.mask, autoAdd=True, - callbacks=iwp.callbacks - ) - iwp._notify(f, IN_ISDIR|IN_CREATE) - # now f is watched, we can add its children the callLater is to - # avoid recursion - self.reactor.callLater(0, - self._addChildren, self._watchpoints[wd]) - - # It's a file and we notify it. - if f.isfile(): - iwp._notify(f, IN_CREATE|IN_CLOSE_WRITE) - - - def watch(self, path, mask=IN_WATCH_MASK, autoAdd=False, - callbacks=None, recursive=False): - """ - Watch the 'mask' events in given path. Can raise C{INotifyError} when - there's a problem while adding a directory. - - @param path: The path needing monitoring - @type path: L{FilePath} - - @param mask: The events that should be watched - @type mask: C{int} - - @param autoAdd: if True automatically add newly created - subdirectories - @type autoAdd: C{boolean} - - @param callbacks: A list of callbacks that should be called - when an event happens in the given path. - The callback should accept 3 arguments: - (ignored, filepath, mask) - @type callbacks: C{list} of callables - - @param recursive: Also add all the subdirectories in this path - @type recursive: C{boolean} - """ - if recursive: - # This behavior is needed to be compatible with the windows - # interface for filesystem changes: - # http://msdn.microsoft.com/en-us/library/aa365465(VS.85).aspx - # ReadDirectoryChangesW can do bWatchSubtree so it doesn't - # make sense to implement this at an higher abstraction - # level when other platforms support it already - for child in path.walk(): - if child.isdir(): - self.watch(child, mask, autoAdd, callbacks, - recursive=False) - else: - wd = self._isWatched(path) - if wd: - return wd - - mask = mask | IN_DELETE_SELF # need this to remove the watch - - return self._addWatch(path, mask, autoAdd, callbacks) - - - def ignore(self, path): - """ - Remove the watch point monitoring the given path - - @param path: The path that should be ignored - @type path: L{FilePath} - """ - wd = self._isWatched(path) - if wd is None: - raise KeyError("%r is not watched" % (path,)) - else: - self._rmWatch(wd) - - - def _isWatched(self, path): - """ - Helper function that checks if the path is already monitored - and returns its watchdescriptor if so or None otherwise. - - @param path: The path that should be checked - @type path: L{FilePath} - """ - return self._watchpaths.get(path, None) - - -INotifyError = _inotify.INotifyError - - -__all__ = ["INotify", "humanReadableMask", "IN_WATCH_MASK", "IN_ACCESS", - "IN_MODIFY", "IN_ATTRIB", "IN_CLOSE_NOWRITE", "IN_CLOSE_WRITE", - "IN_OPEN", "IN_MOVED_FROM", "IN_MOVED_TO", "IN_CREATE", - "IN_DELETE", "IN_DELETE_SELF", "IN_MOVE_SELF", "IN_UNMOUNT", - "IN_Q_OVERFLOW", "IN_IGNORED", "IN_ONLYDIR", "IN_DONT_FOLLOW", - "IN_MASK_ADD", "IN_ISDIR", "IN_ONESHOT", "IN_CLOSE", - "IN_MOVED", "IN_CHANGED"] |