pyinotify/0000700000175000017500000000000011402071101012103 5ustar ookoiookoipyinotify/setup.py0000755000175000017500000000260311402071037013643 0ustar ookoiookoi#!/usr/bin/env python # check Python's version import sys if sys.version < '2.4': sys.stderr.write('This module requires at least Python 2.4\n') sys.exit(1) # import statements from distutils.core import setup, Extension from distutils.util import get_platform # debug DISTUTILS_DEBUG = False # get platform platform = get_platform() # check linux platform if not platform.startswith('linux'): sys.stderr.write("inotify is not available under %s\n" % platform) sys.exit(1) classif = [ 'Environment :: Console', 'Intended Audience :: Developers', 'License :: OSI Approved :: MIT License', 'Natural Language :: English', 'Operating System :: POSIX :: Linux', 'Programming Language :: Python', 'Topic :: Software Development :: Libraries', 'Topic :: System :: Monitoring' ] if sys.version_info[0] >= 3: package_dir = {'': 'python3'} else: package_dir = {'': 'python2'} setup( name='pyinotify', version='0.9.0', description='Linux filesystem events monitoring', author='Sebastien Martini', author_email='sebastien.martini@gmail.com', license='MIT License', platforms='Linux', classifiers=classif, url='http://trac.dbzteam.org/pyinotify', download_url='http://seb.dbzteam.org/pub/pyinotify/releases/pyinotify-0.9.0.tar.gz', py_modules=['pyinotify'], package_dir=package_dir, packages=[''], ) pyinotify/NEWS_old0000644000175000017500000002323111402071040013455 0ustar ookoiookoiChanges in version 0.8.0: ------------------------ * Incompatible changes with version 0.7.x - Dropped support for python 2.3 (supports only CPython >= 2.4) - Changed attribute names of class Event: * 'is_dir' becomes 'dir' * 'event_name' becomes 'maskname' - Altered namespace: * Everything previously accessible under inotify.* is now accessible under pyinotify. - When meaningful, an event (instance of Event) brings a new attribute 'pathname' - Modified debugging messages: * The VERBOSE variable is removed, and is replaced by the logging module * Set the reporting level like this: log.setLevel(level) * print_err(msg) replaced by log.error(msg) - EventsCodes: * _get_event_name(mask) replaced by get_masks(mask) * EventsCodes.IN_* replaced by IN_* (avalaible at the pyinotify's scope) - Notifier: * Avoid use of ThreadedNotifier, everything can be done with Notifier and it provides more functionalities * Use Notifier.loop() method instead of using an infinite while loop Changes in version 0.6.2: ------------------------ * New features - Pathname pattern expansion: Something like python -m pyinotify /tmp/[0-9]*.gif now works. See http://www.python.org/doc/lib/module-glob.html for more details. Changes in version 0.6.0: ------------------------ * Incompatible changes List of incompatible changes in pyinotify.py: ------------------------------------------------------------------- | v0.5 | Now | |-------------------------------------------------------------------| | i1 = SimpleINotify() | wm = WatchManager() | | i2 = ThreadedINotify() | n1 = Notifier(wm) | | | n2 = ThreadedNotifier(wm) | |-------------------------------------------------------------------| | i2.start() | n2.start() | |-------------------------------------------------------------------| | i1.add_watch(...) | wm.add_watch(...) | | i2.rm_watch(...) | wm.rm_watch(...) | |-------------------------------------------------------------------| | i1.close() | n1.stop() | |-------------------------------------------------------------------| | DEBUG = True | VERBOSE = True | |-------------------------------------------------------------------| | event.isdir | event.is_dir | |-------------------------------------------------------------------| | i1.event_check() | n1.check_events() | |-------------------------------------------------------------------| | raise ProcessEventException(err) | raise ProcessEventError(err) | | raise INotifyException(err) | raise NotifierError(err) | |------------------------------------|------------------------------| | def process_default(s,a,b): | def process_default(s,event):| | pass | pass | ------------------------------------------------------------------- * New features - supported flags: IN_ONLYDIR, IN_DONT_FOLLOW, IN_MASK_ADD, IN_MOVE_SELF - auto_add: if a watch is added with this flag set to true, every new subdirectory will be automatically watched too. - possibility to pass one instance of your processing class to Notifier or ThreadedNotifier and this object will be called by default for each watch. Note, you always can give an instance to add_watch(), update_watch(). * Fixed - The pathname is appropriately updated in this case: wm.add_watch('/a/') wm.add_watch('/a/b/') echo "bar" > /a/foo.txt mv /a/foo.txt /a/b/foo.txt The necessary condition is to have watches both on the source dir and on the dst dir. - Ignored (deleted) watches are removed from watch manager. * Pending bug - Consider this case: wm.add_watch('/a/foo.txt') # where neither /a nor /a/b are watched mv /a/foo.txt /a/b/foo.txt In this case we have received IN_MOVE_SELF but we are unable to infer the new pathname. The event IN_MOVE_SELF doesn't provide this indication. Actually, the safest way to use pyinotify is to watch a top directory (say /tmp) one we don't expect be moved, and the watched items located in this directory should only be moved inside this directory or inside another watched top directory (in the same device). Example: wm.add_watch('/tmp', rec=True) mv /tmp/foo/ /tmp/bar/ [safe] mv /tmp/bar/ ~/tmp/ [unsafe] mv /tmp /tmp-new [unsafe] Changes in version 0.5.0: ------------------------ * Few namespace modifications (incompatible changes) - pyinotfiy.inotify.* becomes inotify.* this namespace is a simple wrap of inotify's features (3 systems calls, and 3 variables). - pyinotify.* unchanged. This namespace handle higher developments made on top of inotify. - python -m pyinotify now works (no need to wait python 2.4.5 :) ) * New features - You can read and update the followings variables (accessible through the namespace inotify): - max_queued_events - max_user_instances - max_user_watches Changes in version 0.4.0: ------------------------ Few things have been modified (again) to add more consistence and reliability. Reliability: it is now easy to immediately and precisely know if an operation failed or not, and on which path or wd. That, without interrupting (without raising exceptions) the monitoring. It is more consistent because once you have added a watch on a path you keep the returned wd and use it to further update or remove this watch, this is the natural way. Howewer, in case where you have lost the wd and only have the path you still might retrieve the wd with the method get_wd(path). * Incompatible changes - add_watch returns a dictionary {path: watch_descriptor, ...} where: - path is the path given as argument or a subdirectory (if rec is set to True) - watch_descriptor is the corresponding wd, which is a positive integer if the watch has been successfully added or is a negative integer if it failed. - update_watch only accepts a wd or a list of wd. Moreover, it now returns a dictionary {wd: success, ...} where: - wd is the watch directory being updated (given as argument or retrieved by rec=True). - success is boolean value. success is set to True is the update succeed, False otherwise. - rm_watch only accepts a wd or a list of wd. Moreover, it now returns a dictionary {wd: success, ...} see 'update_watch' just above. Changes in version 0.3.3: ------------------------ * bug fix and cosmetic changes. Changes in version 0.3.1: ------------------------ * Incompatible changes - Event.length removed. Changes in version 0.3.0: ------------------------ This is a development version, there are many changes from 0.2.x releases, this release must be considered as unstable. Most of the changes affects the SimpleINotify class. * Incompatible changes - No more raise an INotify Exception in case where an error occurred in the methods add_watch, update_watch, rm_watch. - Ignore update to an nonexistent watch. - Different behavior for the recursive treatment of the update_watch method. Recursively update only existing and valid watches, doesn't follow symlinks. - The method rm_watch returns a list of watch descriptor (those who were removed). * New features - two new methods: get_wd and get_path. The former takes a path and returns the associated watch descriptor, the latter takes a wd and returns a path. (returning None if the request couldn't be satisfied) - add_watch accepts a list of path as well as a single path. - update_watch and remove_watch accept both string path and int wd as argument. Note: that the preferred argument for update_watch is the path whereas the preferred one for rm_watch is the wd. - The methods rm_watch and update_watch can recursively be applied on theirs arguments. The symlinks aren't followed. Read also the next section. - rm_watch returns the list of watch descriptors of watches successfully removed. * Performances - Always prefer string path for update_watch, and int wd for rm_watch. - Always prefer to save the result of one operation e.g. add_watch for further update or remove watches with this list instead the use of the 'rec' option which is very expansive. * Exceptions vs errors vs nothing The previous versions raised exceptions on explicit errors, the drawback was to drop important informations. For example, given the list ['a-valid-path', 'non-valid-path', 'a-valid-path2'], the first item was successfully added whereas an exception was raised on the second, thus the first wd hadn't been returned to the caller, and the last item hadn't been processed. The new approach is to quietly ignore errors, process all items and to return all successfully executed operations. The benefit is to never hang up the execution of one operation, the called method will never unexpectedly fail, if all operations failed, the result is an empty list. The drawback is to not directly and explicitly report errors. This task is left to the caller, which is able to compare the input parameters to the received list. Obviously this is a subjective choice but i think this is the least worst. Anyway, feel free to send me a comment to say if in your use case this choice works or if it is really really annoying. pyinotify/python3/0000755000175000017500000000000011402071501013525 5ustar ookoiookoipyinotify/python3/Makefile0000644000175000017500000000037211402071040015165 0ustar ookoiookoiEPYDOC=epydoc DSTDOC=docstrings doc: clean-doc $(EPYDOC) --html --graph=all -v -o $(DSTDOC) pyinotify.py clean-doc: rm -rf $(DSTDOC) clean: clean-doc find . \( -name '*~' -or \ -name '*.pyc' -or \ -name '*.pyo' \) \ -print -exec rm {} \; pyinotify/python3/pyinotify.py0000755000175000017500000023214311402071040016137 0ustar ookoiookoi#!/usr/bin/env python # pyinotify.py - python interface to inotify # Copyright (c) 2010 Sebastien Martini # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. """ pyinotify @author: Sebastien Martini @license: MIT License @contact: seb@dbzteam.org """ class PyinotifyError(Exception): """Indicates exceptions raised by a Pyinotify class.""" pass class UnsupportedPythonVersionError(PyinotifyError): """ Raised on unsupported Python versions. """ def __init__(self, version): """ @param version: Current Python version @type version: string """ PyinotifyError.__init__(self, ('Python %s is unsupported, requires ' 'at least Python 3.0') % version) class UnsupportedLibcVersionError(PyinotifyError): """ Raised on unsupported libc versions. """ def __init__(self, version): """ @param version: Current Libc version @type version: string """ PyinotifyError.__init__(self, ('Libc %s is not supported, requires ' 'at least Libc 2.4') % version) # Check Python version import sys if sys.version < '3.0': raise UnsupportedPythonVersionError(sys.version) # Import directives import threading import os import select import struct import fcntl import errno import termios import array import logging import atexit from collections import deque from datetime import datetime, timedelta import time import fnmatch import re import ctypes import ctypes.util import asyncore import glob try: from functools import reduce except ImportError: pass # Will fail on Python 2.4 which has reduce() builtin anyway. __author__ = "seb@dbzteam.org (Sebastien Martini)" __version__ = "0.9.0" # Compatibity mode: set to True to improve compatibility with # Pyinotify 0.7.1. Do not set this variable yourself, call the # function compatibility_mode() instead. COMPATIBILITY_MODE = False # Load libc LIBC = ctypes.CDLL(ctypes.util.find_library('c'), use_errno=True) def STRERRNO(): code = ctypes.get_errno() return '%s (%s)' % (os.strerror(code), errno.errorcode[code]) # The libc version > 2.4 check. # XXX: Maybe it is better to check if the libc has the needed functions inside? # Because there are inotify patches for libc 2.3.6. LIBC.gnu_get_libc_version.restype = ctypes.c_char_p LIBC_VERSION = LIBC.gnu_get_libc_version() if not isinstance(LIBC_VERSION, str): LIBC_VERSION = LIBC_VERSION.decode() if (int(LIBC_VERSION.split('.')[0]) < 2 or (int(LIBC_VERSION.split('.')[0]) == 2 and int(LIBC_VERSION.split('.')[1]) < 4)): raise UnsupportedLibcVersionError(LIBC_VERSION) class PyinotifyLogger(logging.Logger): """ Pyinotify logger used for logging unicode strings. """ def makeRecord(self, name, level, fn, lno, msg, args, exc_info, func=None, extra=None): rv = UnicodeLogRecord(name, level, fn, lno, msg, args, exc_info, func) if extra is not None: for key in extra: if (key in ["message", "asctime"]) or (key in rv.__dict__): raise KeyError("Attempt to overwrite %r in LogRecord" % key) rv.__dict__[key] = extra[key] return rv # Logging def logger_init(): """Initialize logger instance.""" log = logging.getLogger("pyinotify") console_handler = logging.StreamHandler() console_handler.setFormatter( logging.Formatter("[Pyinotify %(levelname)s] %(message)s")) log.addHandler(console_handler) log.setLevel(20) return log log = logger_init() # inotify's variables class SysCtlINotify: """ Access (read, write) inotify's variables through sysctl. Usually it requires administrator rights to update them. Examples: - Read max_queued_events attribute: myvar = max_queued_events.value - Update max_queued_events attribute: max_queued_events.value = 42 """ inotify_attrs = {'max_user_instances': 1, 'max_user_watches': 2, 'max_queued_events': 3} def __init__(self, attrname): sino = ctypes.c_int * 3 self._attrname = attrname self._attr = sino(5, 20, SysCtlINotify.inotify_attrs[attrname]) def get_val(self): """ Gets attribute's value. @return: stored value. @rtype: int """ oldv = ctypes.c_int(0) size = ctypes.c_int(ctypes.sizeof(oldv)) LIBC.sysctl(self._attr, 3, ctypes.c_voidp(ctypes.addressof(oldv)), ctypes.addressof(size), None, 0) return oldv.value def set_val(self, nval): """ Sets new attribute's value. @param nval: replaces current value by nval. @type nval: int """ oldv = ctypes.c_int(0) sizeo = ctypes.c_int(ctypes.sizeof(oldv)) newv = ctypes.c_int(nval) sizen = ctypes.c_int(ctypes.sizeof(newv)) LIBC.sysctl(self._attr, 3, ctypes.c_voidp(ctypes.addressof(oldv)), ctypes.addressof(sizeo), ctypes.c_voidp(ctypes.addressof(newv)), ctypes.addressof(sizen)) value = property(get_val, set_val) def __repr__(self): return '<%s=%d>' % (self._attrname, self.get_val()) # Singleton instances # # read: myvar = max_queued_events.value # update: max_queued_events.value = 42 # for attrname in ('max_queued_events', 'max_user_instances', 'max_user_watches'): globals()[attrname] = SysCtlINotify(attrname) class EventsCodes: """ Set of codes corresponding to each kind of events. Some of these flags are used to communicate with inotify, whereas the others are sent to userspace by inotify notifying some events. @cvar IN_ACCESS: File was accessed. @type IN_ACCESS: int @cvar IN_MODIFY: File was modified. @type IN_MODIFY: int @cvar IN_ATTRIB: Metadata changed. @type IN_ATTRIB: int @cvar IN_CLOSE_WRITE: Writtable file was closed. @type IN_CLOSE_WRITE: int @cvar IN_CLOSE_NOWRITE: Unwrittable file closed. @type IN_CLOSE_NOWRITE: int @cvar IN_OPEN: File was opened. @type IN_OPEN: int @cvar IN_MOVED_FROM: File was moved from X. @type IN_MOVED_FROM: int @cvar IN_MOVED_TO: File was moved to Y. @type IN_MOVED_TO: int @cvar IN_CREATE: Subfile was created. @type IN_CREATE: int @cvar IN_DELETE: Subfile was deleted. @type IN_DELETE: int @cvar IN_DELETE_SELF: Self (watched item itself) was deleted. @type IN_DELETE_SELF: int @cvar IN_MOVE_SELF: Self (watched item itself) was moved. @type IN_MOVE_SELF: int @cvar IN_UNMOUNT: Backing fs was unmounted. @type IN_UNMOUNT: int @cvar IN_Q_OVERFLOW: Event queued overflowed. @type IN_Q_OVERFLOW: int @cvar IN_IGNORED: File was ignored. @type IN_IGNORED: int @cvar IN_ONLYDIR: only watch the path if it is a directory (new in kernel 2.6.15). @type IN_ONLYDIR: int @cvar IN_DONT_FOLLOW: don't follow a symlink (new in kernel 2.6.15). IN_ONLYDIR we can make sure that we don't watch the target of symlinks. @type IN_DONT_FOLLOW: int @cvar IN_MASK_ADD: add to the mask of an already existing watch (new in kernel 2.6.14). @type IN_MASK_ADD: int @cvar IN_ISDIR: Event occurred against dir. @type IN_ISDIR: int @cvar IN_ONESHOT: Only send event once. @type IN_ONESHOT: int @cvar ALL_EVENTS: Alias for considering all of the events. @type ALL_EVENTS: int """ # The idea here is 'configuration-as-code' - this way, we get our nice class # constants, but we also get nice human-friendly text mappings to do lookups # against as well, for free: FLAG_COLLECTIONS = {'OP_FLAGS': { 'IN_ACCESS' : 0x00000001, # File was accessed 'IN_MODIFY' : 0x00000002, # File was modified 'IN_ATTRIB' : 0x00000004, # Metadata changed 'IN_CLOSE_WRITE' : 0x00000008, # Writable file was closed 'IN_CLOSE_NOWRITE' : 0x00000010, # Unwritable file closed 'IN_OPEN' : 0x00000020, # File was opened 'IN_MOVED_FROM' : 0x00000040, # File was moved from X 'IN_MOVED_TO' : 0x00000080, # File was moved to Y 'IN_CREATE' : 0x00000100, # Subfile was created 'IN_DELETE' : 0x00000200, # Subfile was deleted 'IN_DELETE_SELF' : 0x00000400, # Self (watched item itself) # was deleted 'IN_MOVE_SELF' : 0x00000800, # Self (watched item itself) was moved }, 'EVENT_FLAGS': { 'IN_UNMOUNT' : 0x00002000, # Backing fs was unmounted 'IN_Q_OVERFLOW' : 0x00004000, # Event queued overflowed 'IN_IGNORED' : 0x00008000, # File was ignored }, 'SPECIAL_FLAGS': { 'IN_ONLYDIR' : 0x01000000, # only watch the path if it is a # directory 'IN_DONT_FOLLOW' : 0x02000000, # don't follow a symlink '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 }, } def maskname(mask): """ Returns the event name associated to mask. IN_ISDIR is appended to the result when appropriate. Note: only one event is returned, because only one event can be raised at a given time. @param mask: mask. @type mask: int @return: event name. @rtype: str """ ms = mask name = '%s' if mask & IN_ISDIR: ms = mask - IN_ISDIR name = '%s|IN_ISDIR' return name % EventsCodes.ALL_VALUES[ms] maskname = staticmethod(maskname) # So let's now turn the configuration into code EventsCodes.ALL_FLAGS = {} EventsCodes.ALL_VALUES = {} for flagc, valc in EventsCodes.FLAG_COLLECTIONS.items(): # Make the collections' members directly accessible through the # class dictionary setattr(EventsCodes, flagc, valc) # Collect all the flags under a common umbrella EventsCodes.ALL_FLAGS.update(valc) # Make the individual masks accessible as 'constants' at globals() scope # and masknames accessible by values. for name, val in valc.items(): globals()[name] = val EventsCodes.ALL_VALUES[val] = name # all 'normal' events ALL_EVENTS = reduce(lambda x, y: x | y, EventsCodes.OP_FLAGS.values()) EventsCodes.ALL_FLAGS['ALL_EVENTS'] = ALL_EVENTS EventsCodes.ALL_VALUES[ALL_EVENTS] = 'ALL_EVENTS' class _Event: """ Event structure, represent events raised by the system. This is the base class and should be subclassed. """ def __init__(self, dict_): """ Attach attributes (contained in dict_) to self. @param dict_: Set of attributes. @type dict_: dictionary """ for tpl in dict_.items(): setattr(self, *tpl) def __repr__(self): """ @return: Generic event string representation. @rtype: str """ s = '' for attr, value in sorted(self.__dict__.items(), key=lambda x: x[0]): if attr.startswith('_'): continue if attr == 'mask': value = hex(getattr(self, attr)) elif isinstance(value, str) and not value: value = "''" s += ' %s%s%s' % (Color.field_name(attr), Color.punctuation('='), Color.field_value(value)) s = '%s%s%s %s' % (Color.punctuation('<'), Color.class_name(self.__class__.__name__), s, Color.punctuation('>')) return s class _RawEvent(_Event): """ Raw event, it contains only the informations provided by the system. It doesn't infer anything. """ def __init__(self, wd, mask, cookie, name): """ @param wd: Watch Descriptor. @type wd: int @param mask: Bitmask of events. @type mask: int @param cookie: Cookie. @type cookie: int @param name: Basename of the file or directory against which the event was raised in case where the watched directory is the parent directory. None if the event was raised on the watched item itself. @type name: string or None """ # name: remove trailing '\0' _Event.__init__(self, {'wd': wd, 'mask': mask, 'cookie': cookie, 'name': name.rstrip('\0')}) log.debug(repr(self)) # Use this variable to cache the result of str(self) self._str = None def __str__(self): if self._str is None: self._str = '%s %s %s %s' % (str(self.wd), str(self.mask), str(self.cookie), self.name) return self._str class Event(_Event): """ This class contains all the useful informations about the observed event. However, the presence of each field is not guaranteed and depends on the type of event. In effect, some fields are irrelevant for some kind of event (for example 'cookie' is meaningless for IN_CREATE whereas it is mandatory for IN_MOVE_TO). The possible fields are: - wd (int): Watch Descriptor. - mask (int): Mask. - maskname (str): Readable event name. - path (str): path of the file or directory being watched. - name (str): Basename of the file or directory against which the event was raised in case where the watched directory is the parent directory. None if the event was raised on the watched item itself. This field is always provided even if the string is ''. - pathname (str): Concatenation of 'path' and 'name'. - src_pathname (str): Only present for IN_MOVED_TO events and only in the case where IN_MOVED_FROM events are watched too. Holds the source pathname from where pathname was moved from. - cookie (int): Cookie. - dir (bool): True if the event was raised against a directory. """ def __init__(self, raw): """ Concretely, this is the raw event plus inferred infos. """ _Event.__init__(self, raw) self.maskname = EventsCodes.maskname(self.mask) if COMPATIBILITY_MODE: self.event_name = self.maskname try: if self.name: self.pathname = os.path.abspath(os.path.join(self.path, self.name)) else: self.pathname = os.path.abspath(self.path) except AttributeError as err: # Usually it is not an error some events are perfectly valids # despite the lack of these attributes. log.debug(err) class ProcessEventError(PyinotifyError): """ ProcessEventError Exception. Raised on ProcessEvent error. """ def __init__(self, err): """ @param err: Exception error description. @type err: string """ PyinotifyError.__init__(self, err) class _ProcessEvent: """ Abstract processing event class. """ def __call__(self, event): """ To behave like a functor the object must be callable. This method is a dispatch method. Its lookup order is: 1. process_MASKNAME method 2. process_FAMILY_NAME method 3. otherwise calls process_default @param event: Event to be processed. @type event: Event object @return: By convention when used from the ProcessEvent class: - Returning False or None (default value) means keep on executing next chained functors (see chain.py example). - Returning True instead means do not execute next processing functions. @rtype: bool @raise ProcessEventError: Event object undispatchable, unknown event. """ stripped_mask = event.mask - (event.mask & IN_ISDIR) maskname = EventsCodes.ALL_VALUES.get(stripped_mask) if maskname is None: raise ProcessEventError("Unknown mask 0x%08x" % stripped_mask) # 1- look for process_MASKNAME meth = getattr(self, 'process_' + maskname, None) if meth is not None: return meth(event) # 2- look for process_FAMILY_NAME meth = getattr(self, 'process_IN_' + maskname.split('_')[1], None) if meth is not None: return meth(event) # 3- default call method process_default return self.process_default(event) def __repr__(self): return '<%s>' % self.__class__.__name__ class _SysProcessEvent(_ProcessEvent): """ There is three kind of processing according to each event: 1. special handling (deletion from internal container, bug, ...). 2. default treatment: which is applied to the majority of events. 3. IN_ISDIR is never sent alone, he is piggybacked with a standard event, he is not processed as the others events, instead, its value is captured and appropriately aggregated to dst event. """ def __init__(self, wm, notifier): """ @param wm: Watch Manager. @type wm: WatchManager instance @param notifier: Notifier. @type notifier: Notifier instance """ self._watch_manager = wm # watch manager self._notifier = notifier # notifier self._mv_cookie = {} # {cookie(int): (src_path(str), date), ...} self._mv = {} # {src_path(str): (dst_path(str), date), ...} def cleanup(self): """ Cleanup (delete) old (>1mn) records contained in self._mv_cookie and self._mv. """ date_cur_ = datetime.now() for seq in (self._mv_cookie, self._mv): for k in list(seq.keys()): if (date_cur_ - seq[k][1]) > timedelta(minutes=1): log.debug('Cleanup: deleting entry %s', seq[k][0]) del seq[k] def process_IN_CREATE(self, raw_event): """ If the event affects a directory and the auto_add flag of the targetted watch is set to True, a new watch is added on this new directory, with the same attribute values than those of this watch. """ if raw_event.mask & IN_ISDIR: watch_ = self._watch_manager.get_watch(raw_event.wd) created_dir = os.path.join(watch_.path, raw_event.name) if watch_.auto_add and not watch_.exclude_filter(created_dir): addw = self._watch_manager.add_watch # The newly monitored directory inherits attributes from its # parent directory. addw_ret = addw(created_dir, watch_.mask, proc_fun=watch_.proc_fun, rec=False, auto_add=watch_.auto_add, exclude_filter=watch_.exclude_filter) # Trick to handle mkdir -p /t1/t2/t3 where t1 is watched and # t2 and t3 are created. # Since the directory is new, then everything inside it # must also be new. created_dir_wd = addw_ret.get(created_dir) if (created_dir_wd is not None) and created_dir_wd > 0: for name in os.listdir(created_dir): inner = os.path.join(created_dir, name) if (os.path.isdir(inner) and self._watch_manager.get_wd(inner) is None): # Generate (simulate) creation event for sub # directories. rawevent = _RawEvent(created_dir_wd, IN_CREATE | IN_ISDIR, 0, name) self._notifier.append_event(rawevent) return self.process_default(raw_event) def process_IN_MOVED_FROM(self, raw_event): """ Map the cookie with the source path (+ date for cleaning). """ watch_ = self._watch_manager.get_watch(raw_event.wd) path_ = watch_.path src_path = os.path.normpath(os.path.join(path_, raw_event.name)) self._mv_cookie[raw_event.cookie] = (src_path, datetime.now()) return self.process_default(raw_event, {'cookie': raw_event.cookie}) def process_IN_MOVED_TO(self, raw_event): """ Map the source path with the destination path (+ date for cleaning). """ watch_ = self._watch_manager.get_watch(raw_event.wd) path_ = watch_.path dst_path = os.path.normpath(os.path.join(path_, raw_event.name)) mv_ = self._mv_cookie.get(raw_event.cookie) to_append = {'cookie': raw_event.cookie} if mv_ is not None: self._mv[mv_[0]] = (dst_path, datetime.now()) # Let's assume that IN_MOVED_FROM event is always queued before # that its associated (they share a common cookie) IN_MOVED_TO # event is queued itself. It is then possible in that scenario # to provide as additional information to the IN_MOVED_TO event # the original pathname of the moved file/directory. to_append['src_pathname'] = mv_[0] elif (raw_event.mask & IN_ISDIR and watch_.auto_add and not watch_.exclude_filter(dst_path)): # We got a diretory that's "moved in" from an unknown source and # auto_add is enabled. Manually add watches to the inner subtrees. # The newly monitored directory inherits attributes from its # parent directory. self._watch_manager.add_watch(dst_path, watch_.mask, proc_fun=watch_.proc_fun, rec=True, auto_add=True, exclude_filter=watch_.exclude_filter) return self.process_default(raw_event, to_append) def process_IN_MOVE_SELF(self, raw_event): """ STATUS: the following bug has been fixed in recent kernels (FIXME: which version ?). Now it raises IN_DELETE_SELF instead. Old kernels were bugged, this event raised when the watched item were moved, so we had to update its path, but under some circumstances it was impossible: if its parent directory and its destination directory wasn't watched. The kernel (see include/linux/fsnotify.h) doesn't bring us enough informations like the destination path of moved items. """ watch_ = self._watch_manager.get_watch(raw_event.wd) src_path = watch_.path mv_ = self._mv.get(src_path) if mv_: dest_path = mv_[0] watch_.path = dest_path # add the separator to the source path to avoid overlapping # path issue when testing with startswith() src_path += os.path.sep src_path_len = len(src_path) # The next loop renames all watches with src_path as base path. # It seems that IN_MOVE_SELF does not provide IN_ISDIR information # therefore the next loop is iterated even if raw_event is a file. for w in self._watch_manager.watches.values(): if w.path.startswith(src_path): # Note that dest_path is a normalized path. w.path = os.path.join(dest_path, w.path[src_path_len:]) else: log.error("The pathname '%s' of this watch %s has probably changed " "and couldn't be updated, so it cannot be trusted " "anymore. To fix this error move directories/files only " "between watched parents directories, in this case e.g. " "put a watch on '%s'.", watch_.path, watch_, os.path.normpath(os.path.join(watch_.path, os.path.pardir))) if not watch_.path.endswith('-unknown-path'): watch_.path += '-unknown-path' return self.process_default(raw_event) def process_IN_Q_OVERFLOW(self, raw_event): """ Only signal an overflow, most of the common flags are irrelevant for this event (path, wd, name). """ return Event({'mask': raw_event.mask}) def process_IN_IGNORED(self, raw_event): """ The watch descriptor raised by this event is now ignored (forever), it can be safely deleted from the watch manager dictionary. After this event we can be sure that neither the event queue nor the system will raise an event associated to this wd again. """ event_ = self.process_default(raw_event) self._watch_manager.del_watch(raw_event.wd) return event_ def process_default(self, raw_event, to_append=None): """ Commons handling for the followings events: IN_ACCESS, IN_MODIFY, IN_ATTRIB, IN_CLOSE_WRITE, IN_CLOSE_NOWRITE, IN_OPEN, IN_DELETE, IN_DELETE_SELF, IN_UNMOUNT. """ watch_ = self._watch_manager.get_watch(raw_event.wd) if raw_event.mask & (IN_DELETE_SELF | IN_MOVE_SELF): # Unfornulately this information is not provided by the kernel dir_ = watch_.dir else: dir_ = bool(raw_event.mask & IN_ISDIR) dict_ = {'wd': raw_event.wd, 'mask': raw_event.mask, 'path': watch_.path, 'name': raw_event.name, 'dir': dir_} if COMPATIBILITY_MODE: dict_['is_dir'] = dir_ if to_append is not None: dict_.update(to_append) return Event(dict_) class ProcessEvent(_ProcessEvent): """ Process events objects, can be specialized via subclassing, thus its behavior can be overriden: Note: you should not override __init__ in your subclass instead define a my_init() method, this method will be called automatically from the constructor of this class with its optionals parameters. 1. Provide specialized individual methods, e.g. process_IN_DELETE for processing a precise type of event (e.g. IN_DELETE in this case). 2. Or/and provide methods for processing events by 'family', e.g. process_IN_CLOSE method will process both IN_CLOSE_WRITE and IN_CLOSE_NOWRITE events (if process_IN_CLOSE_WRITE and process_IN_CLOSE_NOWRITE aren't defined though). 3. Or/and override process_default for catching and processing all the remaining types of events. """ pevent = None def __init__(self, pevent=None, **kargs): """ Enable chaining of ProcessEvent instances. @param pevent: Optional callable object, will be called on event processing (before self). @type pevent: callable @param kargs: This constructor is implemented as a template method delegating its optionals keyworded arguments to the method my_init(). @type kargs: dict """ self.pevent = pevent self.my_init(**kargs) def my_init(self, **kargs): """ This method is called from ProcessEvent.__init__(). This method is empty here and must be redefined to be useful. In effect, if you need to specifically initialize your subclass' instance then you just have to override this method in your subclass. Then all the keyworded arguments passed to ProcessEvent.__init__() will be transmitted as parameters to this method. Beware you MUST pass keyword arguments though. @param kargs: optional delegated arguments from __init__(). @type kargs: dict """ pass def __call__(self, event): stop_chaining = False if self.pevent is not None: # By default methods return None so we set as guideline # that methods asking for stop chaining must explicitely # return non None or non False values, otherwise the default # behavior will be to accept chain call to the corresponding # local method. stop_chaining = self.pevent(event) if not stop_chaining: return _ProcessEvent.__call__(self, event) def nested_pevent(self): return self.pevent def process_IN_Q_OVERFLOW(self, event): """ By default this method only reports warning messages, you can overredide it by subclassing ProcessEvent and implement your own process_IN_Q_OVERFLOW method. The actions you can take on receiving this event is either to update the variable max_queued_events in order to handle more simultaneous events or to modify your code in order to accomplish a better filtering diminishing the number of raised events. Because this method is defined, IN_Q_OVERFLOW will never get transmitted as arguments to process_default calls. @param event: IN_Q_OVERFLOW event. @type event: dict """ log.warning('Event queue overflowed.') def process_default(self, event): """ Default processing event method. By default does nothing. Subclass ProcessEvent and redefine this method in order to modify its behavior. @param event: Event to be processed. Can be of any type of events but IN_Q_OVERFLOW events (see method process_IN_Q_OVERFLOW). @type event: Event instance """ pass class PrintAllEvents(ProcessEvent): """ Dummy class used to print events strings representations. For instance this class is used from command line to print all received events to stdout. """ def my_init(self, out=None): """ @param out: Where events will be written. @type out: Object providing a valid file object interface. """ if out is None: out = sys.stdout self._out = out def process_default(self, event): """ Writes event string representation to file object provided to my_init(). @param event: Event to be processed. Can be of any type of events but IN_Q_OVERFLOW events (see method process_IN_Q_OVERFLOW). @type event: Event instance """ self._out.write(repr(event)) self._out.write('\n') class ChainIfTrue(ProcessEvent): """ Makes conditional chaining depending on the result of the nested processing instance. """ def my_init(self, func): """ Method automatically called from base class constructor. """ self._func = func def process_default(self, event): return not self._func(event) class Stats(ProcessEvent): """ Compute and display trivial statistics about processed events. """ def my_init(self): """ Method automatically called from base class constructor. """ self._start_time = time.time() self._stats = {} self._stats_lock = threading.Lock() def process_default(self, event): """ Processes |event|. """ self._stats_lock.acquire() try: events = event.maskname.split('|') for event_name in events: count = self._stats.get(event_name, 0) self._stats[event_name] = count + 1 finally: self._stats_lock.release() def _stats_copy(self): self._stats_lock.acquire() try: return self._stats.copy() finally: self._stats_lock.release() def __repr__(self): stats = self._stats_copy() elapsed = int(time.time() - self._start_time) elapsed_str = '' if elapsed < 60: elapsed_str = str(elapsed) + 'sec' elif 60 <= elapsed < 3600: elapsed_str = '%dmn%dsec' % (elapsed / 60, elapsed % 60) elif 3600 <= elapsed < 86400: elapsed_str = '%dh%dmn' % (elapsed / 3600, (elapsed % 3600) / 60) elif elapsed >= 86400: elapsed_str = '%dd%dh' % (elapsed / 86400, (elapsed % 86400) / 3600) stats['ElapsedTime'] = elapsed_str l = [] for ev, value in sorted(stats.items(), key=lambda x: x[0]): l.append(' %s=%s' % (Color.field_name(ev), Color.field_value(value))) s = '<%s%s >' % (Color.class_name(self.__class__.__name__), ''.join(l)) return s def dump(self, filename): """ Dumps statistics to file |filename|. @param filename: pathname. @type filename: string """ with open(filename, 'w') as file_obj: file_obj.write(str(self)) def __str__(self, scale=45): stats = self._stats_copy() if not stats: return '' m = max(stats.values()) unity = scale / m fmt = '%%-26s%%-%ds%%s' % (len(Color.field_value('@' * scale)) + 1) def func(x): return fmt % (Color.field_name(x[0]), Color.field_value('@' * int(x[1] * unity)), Color.simple('%d' % x[1], 'yellow')) s = '\n'.join(map(func, sorted(stats.items(), key=lambda x: x[0]))) return s class NotifierError(PyinotifyError): """ Notifier Exception. Raised on Notifier error. """ def __init__(self, err): """ @param err: Exception string's description. @type err: string """ PyinotifyError.__init__(self, err) class Notifier: """ Read notifications, process events. """ def __init__(self, watch_manager, default_proc_fun=None, read_freq=0, threshold=0, timeout=None): """ Initialization. read_freq, threshold and timeout parameters are used when looping. @param watch_manager: Watch Manager. @type watch_manager: WatchManager instance @param default_proc_fun: Default processing method. If None, a new instance of PrintAllEvents will be assigned. @type default_proc_fun: instance of ProcessEvent @param read_freq: if read_freq == 0, events are read asap, if read_freq is > 0, this thread sleeps max(0, read_freq - timeout) seconds. But if timeout is None it may be different because poll is blocking waiting for something to read. @type read_freq: int @param threshold: File descriptor will be read only if the accumulated size to read becomes >= threshold. If != 0, you likely want to use it in combination with an appropriate value for read_freq because without that you would keep looping without really reading anything and that until the amount of events to read is >= threshold. At least with read_freq set you might sleep. @type threshold: int @param timeout: http://docs.python.org/lib/poll-objects.html#poll-objects @type timeout: int """ # Watch Manager instance self._watch_manager = watch_manager # File descriptor self._fd = self._watch_manager.get_fd() # Poll object and registration self._pollobj = select.poll() self._pollobj.register(self._fd, select.POLLIN) # This pipe is correctely initialized and used by ThreadedNotifier self._pipe = (-1, -1) # Event queue self._eventq = deque() # System processing functor, common to all events self._sys_proc_fun = _SysProcessEvent(self._watch_manager, self) # Default processing method self._default_proc_fun = default_proc_fun if default_proc_fun is None: self._default_proc_fun = PrintAllEvents() # Loop parameters self._read_freq = read_freq self._threshold = threshold self._timeout = timeout # Coalesce events option self._coalesce = False # set of str(raw_event), only used when coalesce option is True self._eventset = set() def append_event(self, event): """ Append a raw event to the event queue. @param event: An event. @type event: _RawEvent instance. """ self._eventq.append(event) def proc_fun(self): return self._default_proc_fun def coalesce_events(self, coalesce=True): """ Coalescing events. Events are usually processed by batchs, their size depend on various factors. Thus, before processing them, events received from inotify are aggregated in a fifo queue. If this coalescing option is enabled events are filtered based on their unicity, only unique events are enqueued, doublons are discarded. An event is unique when the combination of its fields (wd, mask, cookie, name) is unique among events of a same batch. After a batch of events is processed any events is accepted again. By default this option is disabled, you have to explictly call this function to turn it on. @param coalesce: Optional new coalescing value. True by default. @type coalesce: Bool """ self._coalesce = coalesce if not coalesce: self._eventset.clear() def check_events(self, timeout=None): """ Check for new events available to read, blocks up to timeout milliseconds. @param timeout: If specified it overrides the corresponding instance attribute _timeout. @type timeout: int @return: New events to read. @rtype: bool """ while True: try: # blocks up to 'timeout' milliseconds if timeout is None: timeout = self._timeout ret = self._pollobj.poll(timeout) except select.error as err: if err.errno == errno.EINTR: continue # interrupted, retry else: raise else: break if not ret or (self._pipe[0] == ret[0][0]): return False # only one fd is polled return ret[0][1] & select.POLLIN def read_events(self): """ Read events from device, build _RawEvents, and enqueue them. """ buf_ = array.array('i', [0]) # get event queue size if fcntl.ioctl(self._fd, termios.FIONREAD, buf_, 1) == -1: return queue_size = buf_[0] if queue_size < self._threshold: log.debug('(fd: %d) %d bytes available to read but threshold is ' 'fixed to %d bytes', self._fd, queue_size, self._threshold) return try: # Read content from file r = os.read(self._fd, queue_size) except Exception as msg: raise NotifierError(msg) log.debug('Event queue size: %d', queue_size) rsum = 0 # counter while rsum < queue_size: s_size = 16 # Retrieve wd, mask, cookie and fname_len wd, mask, cookie, fname_len = struct.unpack('iIII', r[rsum:rsum+s_size]) # Retrieve name bname, = struct.unpack('%ds' % fname_len, r[rsum + s_size:rsum + s_size + fname_len]) # FIXME: should we explictly call sys.getdefaultencoding() here ?? uname = bname.decode() rawevent = _RawEvent(wd, mask, cookie, uname) if self._coalesce: # Only enqueue new (unique) events. raweventstr = str(rawevent) if raweventstr not in self._eventset: self._eventset.add(raweventstr) self._eventq.append(rawevent) else: self._eventq.append(rawevent) rsum += s_size + fname_len def process_events(self): """ Routine for processing events from queue by calling their associated proccessing method (an instance of ProcessEvent). It also does internal processings, to keep the system updated. """ while self._eventq: raw_event = self._eventq.popleft() # pop next event watch_ = self._watch_manager.get_watch(raw_event.wd) if watch_ is None: # Not really sure how we ended up here, nor how we should # handle these types of events and if it is appropriate to # completly skip them (like we are doing here). log.warning("Unable to retrieve Watch object associated to %s", repr(raw_event)) continue revent = self._sys_proc_fun(raw_event) # system processings if watch_ and watch_.proc_fun: watch_.proc_fun(revent) # user processings else: self._default_proc_fun(revent) self._sys_proc_fun.cleanup() # remove olds MOVED_* events records if self._coalesce: self._eventset.clear() def __daemonize(self, pid_file=None, force_kill=False, stdin=os.devnull, stdout=os.devnull, stderr=os.devnull): """ pid_file: file to which the pid will be written. force_kill: if True kill the process associated to pid_file. stdin, stdout, stderr: files associated to common streams. """ if pid_file is None: dirname = '/var/run/' basename = os.path.basename(sys.argv[0]) or 'pyinotify' pid_file = os.path.join(dirname, basename + '.pid') if os.path.exists(pid_file): with open(pid_file, 'r') as fo: try: pid = int(fo.read()) except ValueError: pid = None if pid is not None: try: os.kill(pid, 0) except OSError as err: if err.errno == errno.ESRCH: log.debug(err) else: log.error(err) else: if not force_kill: s = 'There is already a pid file %s with pid %d' raise NotifierError(s % (pid_file, pid)) else: os.kill(pid, 9) def fork_daemon(): # Adapted from Chad J. Schroeder's recipe # @see http://code.activestate.com/recipes/278731/ pid = os.fork() if (pid == 0): # parent 2 os.setsid() pid = os.fork() if (pid == 0): # child os.chdir('/') os.umask(0) else: # parent 2 os._exit(0) else: # parent 1 os._exit(0) fd_inp = open(stdin, 'r') os.dup2(fd_inp.fileno(), 0) fd_out = open(stdout, 'w') os.dup2(fd_out.fileno(), 1) fd_err = open(stderr, 'w') os.dup2(fd_err.fileno(), 2) # Detach task fork_daemon() # Write pid with open(pid_file, 'w') as file_obj: file_obj.write(str(os.getpid()) + '\n') atexit.register(lambda : os.unlink(pid_file)) def _sleep(self, ref_time): # Only consider sleeping if read_freq is > 0 if self._read_freq > 0: cur_time = time.time() sleep_amount = self._read_freq - (cur_time - ref_time) if sleep_amount > 0: log.debug('Now sleeping %d seconds', sleep_amount) time.sleep(sleep_amount) def loop(self, callback=None, daemonize=False, **args): """ Events are read only one time every min(read_freq, timeout) seconds at best and only if the size to read is >= threshold. After this method returns it must not be called again for the same instance. @param callback: Functor called after each event processing iteration. Expects to receive the notifier object (self) as first parameter. If this function returns True the loop is immediately terminated otherwise the loop method keeps looping. @type callback: callable object or function @param daemonize: This thread is daemonized if set to True. @type daemonize: boolean @param args: Optional and relevant only if daemonize is True. Remaining keyworded arguments are directly passed to daemonize see __daemonize() method. @type args: various """ if daemonize: self.__daemonize(**args) # Read and process events forever while 1: try: self.process_events() if (callback is not None) and (callback(self) is True): break ref_time = time.time() # check_events is blocking if self.check_events(): self._sleep(ref_time) self.read_events() except KeyboardInterrupt: # Stop monitoring if sigint is caught (Control-C). log.debug('Pyinotify stops monitoring.') break # Close internals self.stop() def stop(self): """ Close inotify's instance (close its file descriptor). It destroys all existing watches, pending events,... This method is automatically called at the end of loop(). """ self._pollobj.unregister(self._fd) os.close(self._fd) class ThreadedNotifier(threading.Thread, Notifier): """ This notifier inherits from threading.Thread for instanciating a separate thread, and also inherits from Notifier, because it is a threaded notifier. Note that every functionality provided by this class is also provided through Notifier class. Moreover Notifier should be considered first because it is not threaded and could be easily daemonized. """ def __init__(self, watch_manager, default_proc_fun=None, read_freq=0, threshold=0, timeout=None): """ Initialization, initialize base classes. read_freq, threshold and timeout parameters are used when looping. @param watch_manager: Watch Manager. @type watch_manager: WatchManager instance @param default_proc_fun: Default processing method. See base class. @type default_proc_fun: instance of ProcessEvent @param read_freq: if read_freq == 0, events are read asap, if read_freq is > 0, this thread sleeps max(0, read_freq - timeout) seconds. @type read_freq: int @param threshold: File descriptor will be read only if the accumulated size to read becomes >= threshold. If != 0, you likely want to use it in combination with an appropriate value set for read_freq because without that you would keep looping without really reading anything and that until the amount of events to read is >= threshold. At least with read_freq you might sleep. @type threshold: int @param timeout: see http://docs.python.org/lib/poll-objects.html#poll-objects @type timeout: int """ # Init threading base class threading.Thread.__init__(self) # Stop condition self._stop_event = threading.Event() # Init Notifier base class Notifier.__init__(self, watch_manager, default_proc_fun, read_freq, threshold, timeout) # Create a new pipe used for thread termination self._pipe = os.pipe() self._pollobj.register(self._pipe[0], select.POLLIN) def stop(self): """ Stop notifier's loop. Stop notification. Join the thread. """ self._stop_event.set() os.write(self._pipe[1], b'stop') threading.Thread.join(self) Notifier.stop(self) self._pollobj.unregister(self._pipe[0]) os.close(self._pipe[0]) os.close(self._pipe[1]) def loop(self): """ Thread's main loop. Don't meant to be called by user directly. Call inherited start() method instead. Events are read only once time every min(read_freq, timeout) seconds at best and only if the size of events to read is >= threshold. """ # When the loop must be terminated .stop() is called, 'stop' # is written to pipe fd so poll() returns and .check_events() # returns False which make evaluate the While's stop condition # ._stop_event.isSet() wich put an end to the thread's execution. while not self._stop_event.isSet(): self.process_events() ref_time = time.time() if self.check_events(): self._sleep(ref_time) self.read_events() def run(self): """ Start thread's loop: read and process events until the method stop() is called. Never call this method directly, instead call the start() method inherited from threading.Thread, which then will call run() in its turn. """ self.loop() class AsyncNotifier(asyncore.file_dispatcher, Notifier): """ This notifier inherits from asyncore.file_dispatcher in order to be able to use pyinotify along with the asyncore framework. """ def __init__(self, watch_manager, default_proc_fun=None, read_freq=0, threshold=0, timeout=None, channel_map=None): """ Initializes the async notifier. The only additional parameter is 'channel_map' which is the optional asyncore private map. See Notifier class for the meaning of the others parameters. """ Notifier.__init__(self, watch_manager, default_proc_fun, read_freq, threshold, timeout) asyncore.file_dispatcher.__init__(self, self._fd, channel_map) def handle_read(self): """ When asyncore tells us we can read from the fd, we proceed processing events. This method can be overridden for handling a notification differently. """ self.read_events() self.process_events() class Watch: """ Represent a watch, i.e. a file or directory being watched. """ def __init__(self, wd, path, mask, proc_fun, auto_add, exclude_filter): """ Initializations. @param wd: Watch descriptor. @type wd: int @param path: Path of the file or directory being watched. @type path: str @param mask: Mask. @type mask: int @param proc_fun: Processing callable object. @type proc_fun: @param auto_add: Automatically add watches on new directories. @type auto_add: bool @param exclude_filter: Boolean function, used to exclude new directories from being automatically watched. See WatchManager.__init__ @type exclude_filter: callable object """ self.wd = wd self.path = path self.mask = mask self.proc_fun = proc_fun self.auto_add = auto_add self.exclude_filter = exclude_filter self.dir = os.path.isdir(self.path) def __repr__(self): """ @return: String representation. @rtype: str """ s = ' '.join(['%s%s%s' % (Color.field_name(attr), Color.punctuation('='), Color.field_value(getattr(self, attr))) \ for attr in self.__dict__ if not attr.startswith('_')]) s = '%s%s %s %s' % (Color.punctuation('<'), Color.class_name(self.__class__.__name__), s, Color.punctuation('>')) return s class ExcludeFilter: """ ExcludeFilter is an exclusion filter. """ def __init__(self, arg_lst): """ Examples: ef1 = ExcludeFilter(["^/etc/rc.*", "^/etc/hostname"]) ef2 = ExcludeFilter("/my/path/exclude.lst") Where exclude.lst contains: ^/etc/rc.* ^/etc/hostname @param arg_lst: is either a list of patterns or a filename from which patterns will be loaded. @type arg_lst: list of str or str """ if isinstance(arg_lst, str): lst = self._load_patterns_from_file(arg_lst) elif isinstance(arg_lst, list): lst = arg_lst else: raise TypeError self._lregex = [] for regex in lst: self._lregex.append(re.compile(regex, re.UNICODE)) def _load_patterns_from_file(self, filename): lst = [] with open(filename, 'r') as file_obj: for line in file_obj.readlines(): # Trim leading an trailing whitespaces pattern = line.strip() if not pattern or pattern.startswith('#'): continue lst.append(pattern) return lst def _match(self, regex, path): return regex.match(path) is not None def __call__(self, path): """ @param path: Path to match against provided regexps. @type path: str @return: Return True if path has been matched and should be excluded, False otherwise. @rtype: bool """ for regex in self._lregex: if self._match(regex, path): return True return False class WatchManagerError(Exception): """ WatchManager Exception. Raised on error encountered on watches operations. """ def __init__(self, msg, wmd): """ @param msg: Exception string's description. @type msg: string @param wmd: This dictionary contains the wd assigned to paths of the same call for which watches were successfully added. @type wmd: dict """ self.wmd = wmd Exception.__init__(self, msg) class WatchManager: """ Provide operations for watching files and directories. Its internal dictionary is used to reference watched items. When used inside threaded code, one must instanciate as many WatchManager instances as there are ThreadedNotifier instances. """ def __init__(self, exclude_filter=lambda path: False): """ Initialization: init inotify, init watch manager dictionary. Raise OSError if initialization fails. @param exclude_filter: boolean function, returns True if current path must be excluded from being watched. Convenient for providing a common exclusion filter for every call to add_watch. @type exclude_filter: callable object """ self._exclude_filter = exclude_filter self._wmd = {} # watch dict key: watch descriptor, value: watch self._fd = LIBC.inotify_init() # inotify's init, file descriptor if self._fd < 0: err = 'Cannot initialize new instance of inotify Errno=%s' raise OSError(err % STRERRNO()) def get_fd(self): """ Return assigned inotify's file descriptor. @return: File descriptor. @rtype: int """ return self._fd def get_watch(self, wd): """ Get watch from provided watch descriptor wd. @param wd: Watch descriptor. @type wd: int """ return self._wmd.get(wd) def del_watch(self, wd): """ Remove watch entry associated to watch descriptor wd. @param wd: Watch descriptor. @type wd: int """ try: del self._wmd[wd] except KeyError as err: log.error(str(err)) @property def watches(self): """ Get a reference on the internal watch manager dictionary. @return: Internal watch manager dictionary. @rtype: dict """ return self._wmd def __format_path(self, path): """ Format path to its internal (stored in watch manager) representation. """ # path must be a unicode string (str) and is just normalized. return os.path.normpath(path) def __add_watch(self, path, mask, proc_fun, auto_add, exclude_filter): """ Add a watch on path, build a Watch object and insert it in the watch manager dictionary. Return the wd value. """ path = self.__format_path(path) # path to a bytes string. This conversion seems to be required because # ctypes.create_string_buffer seems to manipulate bytes # strings representations internally. # Moreover it seems that LIBC.inotify_add_watch does not work very # well when it receives an ctypes.create_unicode_buffer instance as # argument. However wd are _always_ indexed with their original # unicode paths in wmd. byte_path = path.encode(sys.getfilesystemencoding()) wd_ = LIBC.inotify_add_watch(self._fd, ctypes.create_string_buffer(byte_path), mask) if wd_ < 0: return wd_ watch_ = Watch(wd=wd_, path=path, mask=mask, proc_fun=proc_fun, auto_add=auto_add, exclude_filter=exclude_filter) self._wmd[wd_] = watch_ log.debug('New %s', watch_) return wd_ def __glob(self, path, do_glob): if do_glob: return glob.iglob(path) else: return [path] def add_watch(self, path, mask, proc_fun=None, rec=False, auto_add=False, do_glob=False, quiet=True, exclude_filter=None): """ Add watch(s) on the provided |path|(s) with associated |mask| flag value and optionally with a processing |proc_fun| function and recursive flag |rec| set to True. All |path| components _must_ be str (i.e. unicode) objects. If |path| is already watched it is ignored, but if it is called with option rec=True a watch is put on each one of its not-watched subdirectory. @param path: Path to watch, the path can either be a file or a directory. Also accepts a sequence (list) of paths. @type path: string or list of strings @param mask: Bitmask of events. @type mask: int @param proc_fun: Processing object. @type proc_fun: function or ProcessEvent instance or instance of one of its subclasses or callable object. @param rec: Recursively add watches from path on all its subdirectories, set to False by default (doesn't follows symlinks in any case). @type rec: bool @param auto_add: Automatically add watches on newly created directories in watched parent |path| directory. @type auto_add: bool @param do_glob: Do globbing on pathname (see standard globbing module for more informations). @type do_glob: bool @param quiet: if False raises a WatchManagerError exception on error. See example not_quiet.py. @type quiet: bool @param exclude_filter: predicate (boolean function), which returns True if the current path must be excluded from being watched. This argument has precedence over exclude_filter passed to the class' constructor. @type exclude_filter: callable object @return: dict of paths associated to watch descriptors. A wd value is positive if the watch was added sucessfully, otherwise the value is negative. If the path was invalid or was already watched it is not included into this returned dictionary. @rtype: dict of {str: int} """ ret_ = {} # return {path: wd, ...} if exclude_filter is None: exclude_filter = self._exclude_filter # normalize args as list elements for npath in self.__format_param(path): # Require that path be a unicode string if not isinstance(npath, str): ret_[path] = -3 continue # unix pathname pattern expansion for apath in self.__glob(npath, do_glob): # recursively list subdirs according to rec param for rpath in self.__walk_rec(apath, rec): if self.get_wd(rpath) is not None: # We decide to ignore paths already inserted into # the watch manager. Need to be removed with rm_watch() # first. Or simply call update_watch() to update it. continue if not exclude_filter(rpath): wd = ret_[rpath] = self.__add_watch(rpath, mask, proc_fun, auto_add, exclude_filter) if wd < 0: err = 'add_watch: cannot watch %s WD=%d Errno=%s' err = err % (rpath, wd, STRERRNO()) if quiet: log.error(err) else: raise WatchManagerError(err, ret_) else: # Let's say -2 means 'explicitely excluded # from watching'. ret_[rpath] = -2 return ret_ def __get_sub_rec(self, lpath): """ Get every wd from self._wmd if its path is under the path of one (at least) of those in lpath. Doesn't follow symlinks. @param lpath: list of watch descriptor @type lpath: list of int @return: list of watch descriptor @rtype: list of int """ for d in lpath: root = self.get_path(d) if root is not None: # always keep root yield d else: # if invalid continue # nothing else to expect if not os.path.isdir(root): continue # normalization root = os.path.normpath(root) # recursion lend = len(root) for iwd in self._wmd.items(): cur = iwd[1].path pref = os.path.commonprefix([root, cur]) if root == os.sep or (len(pref) == lend and \ len(cur) > lend and \ cur[lend] == os.sep): yield iwd[1].wd def update_watch(self, wd, mask=None, proc_fun=None, rec=False, auto_add=False, quiet=True): """ Update existing watch descriptors |wd|. The |mask| value, the processing object |proc_fun|, the recursive param |rec| and the |auto_add| and |quiet| flags can all be updated. @param wd: Watch Descriptor to update. Also accepts a list of watch descriptors. @type wd: int or list of int @param mask: Optional new bitmask of events. @type mask: int @param proc_fun: Optional new processing function. @type proc_fun: function or ProcessEvent instance or instance of one of its subclasses or callable object. @param rec: Optionally adds watches recursively on all subdirectories contained into |wd| directory. @type rec: bool @param auto_add: Automatically adds watches on newly created directories in the watch's path corresponding to |wd|. @type auto_add: bool @param quiet: If False raises a WatchManagerError exception on error. See example not_quiet.py @type quiet: bool @return: dict of watch descriptors associated to booleans values. True if the corresponding wd has been successfully updated, False otherwise. @rtype: dict of {int: bool} """ lwd = self.__format_param(wd) if rec: lwd = self.__get_sub_rec(lwd) ret_ = {} # return {wd: bool, ...} for awd in lwd: apath = self.get_path(awd) if not apath or awd < 0: err = 'update_watch: invalid WD=%d' % awd if quiet: log.error(err) continue raise WatchManagerError(err, ret_) if mask: addw = LIBC.inotify_add_watch # apath is always stored as unicode string so encode it to # bytes. byte_path = apath.encode(sys.getfilesystemencoding()) wd_ = addw(self._fd, ctypes.create_string_buffer(byte_path), mask) if wd_ < 0: ret_[awd] = False err = 'update_watch: cannot update %s WD=%d Errno=%s' err = err % (apath, wd_, STRERRNO()) if quiet: log.error(err) continue raise WatchManagerError(err, ret_) assert(awd == wd_) if proc_fun or auto_add: watch_ = self._wmd[awd] if proc_fun: watch_.proc_fun = proc_fun if auto_add: watch_.auto_add = auto_add ret_[awd] = True log.debug('Updated watch - %s', self._wmd[awd]) return ret_ def __format_param(self, param): """ @param param: Parameter. @type param: string or int @return: wrap param. @rtype: list of type(param) """ if isinstance(param, list): for p_ in param: yield p_ else: yield param def get_wd(self, path): """ Returns the watch descriptor associated to path. This method presents a prohibitive cost, always prefer to keep the WD returned by add_watch(). If the path is unknown it returns None. @param path: Path. @type path: str @return: WD or None. @rtype: int or None """ path = self.__format_path(path) for iwd in self._wmd.items(): if iwd[1].path == path: return iwd[0] def get_path(self, wd): """ Returns the path associated to WD, if WD is unknown it returns None. @param wd: Watch descriptor. @type wd: int @return: Path or None. @rtype: string or None """ watch_ = self._wmd.get(wd) if watch_ is not None: return watch_.path def __walk_rec(self, top, rec): """ Yields each subdirectories of top, doesn't follow symlinks. If rec is false, only yield top. @param top: root directory. @type top: string @param rec: recursive flag. @type rec: bool @return: path of one subdirectory. @rtype: string """ if not rec or os.path.islink(top) or not os.path.isdir(top): yield top else: for root, dirs, files in os.walk(top): yield root def rm_watch(self, wd, rec=False, quiet=True): """ Removes watch(s). @param wd: Watch Descriptor of the file or directory to unwatch. Also accepts a list of WDs. @type wd: int or list of int. @param rec: Recursively removes watches on every already watched subdirectories and subfiles. @type rec: bool @param quiet: If False raises a WatchManagerError exception on error. See example not_quiet.py @type quiet: bool @return: dict of watch descriptors associated to booleans values. True if the corresponding wd has been successfully removed, False otherwise. @rtype: dict of {int: bool} """ lwd = self.__format_param(wd) if rec: lwd = self.__get_sub_rec(lwd) ret_ = {} # return {wd: bool, ...} for awd in lwd: # remove watch wd_ = LIBC.inotify_rm_watch(self._fd, awd) if wd_ < 0: ret_[awd] = False err = 'rm_watch: cannot remove WD=%d Errno=%s' % (awd, STRERRNO()) if quiet: log.error(err) continue raise WatchManagerError(err, ret_) ret_[awd] = True log.debug('Watch WD=%d (%s) removed', awd, self.get_path(awd)) return ret_ def watch_transient_file(self, filename, mask, proc_class): """ Watch a transient file, which will be created and deleted frequently over time (e.g. pid file). @attention: Currently under the call to this function it is not possible to correctly watch the events triggered into the same base directory than the directory where is located this watched transient file. For instance it would be wrong to make these two successive calls: wm.watch_transient_file('/var/run/foo.pid', ...) and wm.add_watch('/var/run/', ...) @param filename: Filename. @type filename: string @param mask: Bitmask of events, should contain IN_CREATE and IN_DELETE. @type mask: int @param proc_class: ProcessEvent (or of one of its subclass), beware of accepting a ProcessEvent's instance as argument into __init__, see transient_file.py example for more details. @type proc_class: ProcessEvent's instance or of one of its subclasses. @return: Same as add_watch(). @rtype: Same as add_watch(). """ dirname = os.path.dirname(filename) if dirname == '': return {} # Maintains coherence with add_watch() basename = os.path.basename(filename) # Assuming we are watching at least for IN_CREATE and IN_DELETE mask |= IN_CREATE | IN_DELETE def cmp_name(event): if getattr(event, 'name') is None: return False return basename == event.name return self.add_watch(dirname, mask, proc_fun=proc_class(ChainIfTrue(func=cmp_name)), rec=False, auto_add=False, do_glob=False, exclude_filter=lambda path: False) class Color: """ Internal class. Provide fancy colors used by string representations. """ normal = "\033[0m" black = "\033[30m" red = "\033[31m" green = "\033[32m" yellow = "\033[33m" blue = "\033[34m" purple = "\033[35m" cyan = "\033[36m" bold = "\033[1m" uline = "\033[4m" blink = "\033[5m" invert = "\033[7m" @staticmethod def punctuation(s): """Punctuation color.""" return Color.normal + s + Color.normal @staticmethod def field_value(s): """Field value color.""" if not isinstance(s, str): s = str(s) return Color.purple + s + Color.normal @staticmethod def field_name(s): """Field name color.""" return Color.blue + s + Color.normal @staticmethod def class_name(s): """Class name color.""" return Color.red + Color.bold + s + Color.normal @staticmethod def simple(s, color): if not isinstance(s, str): s = str(s) try: color_attr = getattr(Color, color) except AttributeError: return s return color_attr + s + Color.normal def compatibility_mode(): """ Use this function to turn on the compatibility mode. The compatibility mode is used to improve compatibility with Pyinotify 0.7.1 (or older) programs. The compatibility mode provides additional variables 'is_dir', 'event_name', 'EventsCodes.IN_*' and 'EventsCodes.ALL_EVENTS' as Pyinotify 0.7.1 provided. Do not call this function from new programs!! Especially if there are developped for Pyinotify >= 0.8.x. """ setattr(EventsCodes, 'ALL_EVENTS', ALL_EVENTS) for evname in globals(): if evname.startswith('IN_'): setattr(EventsCodes, evname, globals()[evname]) global COMPATIBILITY_MODE COMPATIBILITY_MODE = True def command_line(): """ By default the watched path is '/tmp' and all types of events are monitored. Events monitoring serves forever, type c^c to stop it. """ from optparse import OptionParser usage = "usage: %prog [options] [path1] [path2] [pathn]" parser = OptionParser(usage=usage) parser.add_option("-v", "--verbose", action="store_true", dest="verbose", help="Verbose mode") parser.add_option("-r", "--recursive", action="store_true", dest="recursive", help="Add watches recursively on paths") parser.add_option("-a", "--auto_add", action="store_true", dest="auto_add", help="Automatically add watches on new directories") parser.add_option("-e", "--events-list", metavar="EVENT[,...]", dest="events_list", help=("A comma-separated list of events to watch for - " "see the documentation for valid options (defaults" " to everything)")) parser.add_option("-s", "--stats", action="store_true", dest="stats", help="Display dummy statistics") (options, args) = parser.parse_args() if options.verbose: log.setLevel(10) if len(args) < 1: path = '/tmp' # default watched path else: path = args # watch manager instance wm = WatchManager() # notifier instance and init if options.stats: notifier = Notifier(wm, default_proc_fun=Stats(), read_freq=5) else: notifier = Notifier(wm, default_proc_fun=PrintAllEvents()) # What mask to apply mask = 0 if options.events_list: events_list = options.events_list.split(',') for ev in events_list: evcode = EventsCodes.ALL_FLAGS.get(ev, 0) if evcode: mask |= evcode else: parser.error("The event '%s' specified with option -e" " is not valid" % ev) else: mask = ALL_EVENTS # stats cb_fun = None if options.stats: def cb(s): print('%s\n%s\n' % (repr(s.proc_fun()), s.proc_fun())) cb_fun = cb log.debug('Start monitoring %s, (press c^c to halt pyinotify)' % path) wm.add_watch(path, mask, rec=options.recursive, auto_add=options.auto_add) # Loop forever (until sigint signal get caught) notifier.loop(callback=cb_fun) if __name__ == '__main__': command_line() pyinotify/python3/docstrings/0000755000175000017500000000000011402071465015715 5ustar ookoiookoipyinotify/python3/docstrings/uml_class_diagram_for_pyinotif_4.gif0000644000175000017500000002020411402071464025061 0ustar ookoiookoiGIF87a|LBDĤBDĆ,"d^\jdԦbd|T., dJD<2,Ėvtܶ|^TĞlܪvlTJD&$$RT,*$lVLD:4j\ԢԮĞ64 \F<̦rdԜ|fdԌ~tTB<ĤJL| nddRT~|<.,L:4Ď4&$t^T|D2,̖vl쾼|bd̞24,Z\4*$tZT̞:< Ԧz|t܌TF< ,&$ԪnldNDܾ|bT䲤zl\JD&$$lZ\|rl  ~t̬ND rlL><~|܌ ,"$Ԧ<24$lVTD:lI:h3x |RЬE@-[XkX>w~mܫ}#W\UuGq $Zp|)'Kւ >sC-ԡ_d_&`xDKl0ʸ!UR_ Hd'j-jA tHdni_k][dil)`myBlG%ekY斃&gyi`hDU iHPm':f!,(^{B`'몭 _om):[h]Wn[u([WXt1@)JJmm,k06mz,J mY-']f@Pqx,k,nH 0*B'/++ @mܱ ,[|p 7!1>e&Q EJAD&-7I%(iFP+y\!d^-C|G'tA-5Vct[sF k'dQ#2ywh_礗n][KTǮG%L/o<``7ӈH4B+kpZ6ӵDqm5zϞ;SBƢ^^ԍcD@:iU \zƤU}_=dֶG׺xҳ6r4_ X> 5 [ÙH/Vebcfp\3cHڅfALSI~> --u?0@0 U3xPɰ)@}"G~q WKs6hCF5tc Elp S*6' h _*z٥Ůc0c3K Fcayضa fV+E6 mJӼEm27ֲ % f(// `4KЏ}tgnռͭQjVֹoA`e,&Ra> 4>7}iV-^M2̎ gh쒆EaX Aox;F}o𬻠iOz +S6riw- ,uײ)D}BRxVq,2SPMlQtznq%S#-rs1vyFdf2s5F}>g8G>:G{kmcotM5>C@$v~dSttQg_ 4u-8gGu.N9P3T8VhmgYo8wYքgW9y8{7JօZCxb~aixrKQC!M#jaysYkyL؆v1z$bMv$'zX${qQlDmNn(]'/{XVdB}BTCwnG-h~f\~%on!Q)oъ!hhsRP$0 /gg(ƀeWd7-VSˈJ4oqsxu9P4'%>'r,((0@35hS긎1}ItTu:BȁQ{Hx Duǒ0?8-yI6<2Vv!YUvE9e:tIN)?VKUoQK[L0kW\ǥ$hz{e]M9Ȧ])ƊHt}x~}~!.Dn5Ռg'~ &>lAqaW3R1v<7#S*rvc<7+F )GGFY)Ld$)OFF;ɓOU Nٝ1Y99~QBY:BNtVT9JLSI9QSRd[W9'ɱ_Y4Ɵ)f$V'{ Zvl .^T rHIJc/vИ' Y37SvQrgМt[|tdY/)醆FztH#Guՙ l;-rzkZF}p|* Dwj8f-* 9SʥVkwiv]KE~!ʎ!\6kkrIUi(ɦ㥙[ZBফHɘ}ιʘFQoiأՑpۈaHp-h!6b%gڑ8caqAӉd;wJxj [+wgJf&wY}ѨSjw^?ѩc5;*t!\D䖱zq걵 (]$J"}y^ӗkHv:E$mڀ_{ϊݲ.Bo$"o9Uȍ"u*ݪ##23ɯI8qqrX#K)sBtv$m<8\bj=#)ui@*k; ۝˓~gб]u$z(Uٲ/1[UY[~AytQ{OQNORoqѵ˽onעuV;Djۍߺp!.{k7vl!л =7gzy+Vl'<) +̒-|*+- K:3˷99;ܼp񼣋f6ux#4W[:j?{A Ď+R%5x1Rh\Lۯ[LB[Т/]{`Ş Z9_^חxpѶmt|~[{m{}&33S`+mx7ocQ5{z@ |Ĩ*tiָܸӺMV° М/9/IB<\l=A@ \|L<]>bP] 0]5QO 1Op T&TCp Pp0}(P 1# 0J@B)@0GX0L'@< M]1Qm\IQGdJPU` je 0t]5 x]Q0yׂ==؃]؆׈y، ׎eْՔ]V}٘ԚCٞӠ1=ڤlڪڬڮڰۯs-۶}۸}7pA !uP:k9CfݷŭpܤSv9HV9 ح8݂XU<@ aCg潕ѳe4m}ܝzJIRz! ,L=@dmn!aѤN/N%nݗ'S(-N`$jZ| -q!^܍}g+cfCe{b[ENkM~*;N܍-n4/8>80^cV>-ε3ݢi ɇ6y %3%Ս^N0D,q3s.<3nh.mOOqJZ5S )*˝Q778\CkynܓcԣٍF01 z뺾uV./Ai-nˎ.۸ގ;>^.N>p12a,7m.&KBP x {?=f_ANFK\św g04yk@@a iP Sp{ ]fP Hhp޷(E[BZI0 } E468F}n*-nR^pab8l^`wZA@rL) ,[%EpEpSAS:0ʇs&n~o",>+_ϒ.ޝ@tO/>sR^S@@ qJB >Q"C6-^ĘQF7*H%IޘRJ-]t(0męSN SDOEERx$UԈ~DU]T)Pt|EV-DC@)j\^ZX}UUB*8EPTfzX䔘4PeΝOe(0TM+Rj֟ 8o#W^mul}o%~\9˝Sm\zӭ~]{۽]C,^շwo~|ǟ_~kx?R !dA0B 'B< lG$OD _F4 4(!ŃR1E;20"=1@4[RK,HMp3:4VYMEs ZC4$8# -.`5 "W`bդ3vDEoU+lX$=>\-esVnO6E)"D(MvEݷhKZlޅEq LW]XAUPzϐbYܖ[O43UP d;LyeT 5J5&[w ($ZšEqH@zIzId:/~v2kFF{uRކ;n离n;oa;p'|nݴGf<r/OzǼs!)?rGGtD'=p_Yw;vo{vQW}tw/x/'~=㏏޼->1D>GA D+1 X%pM4+.Àr 3S<@0 \ S" T'%- N @XapN@) BR06&DOFh(UDX54xM8A#f>M)N/Uo`sF12ge 5:gt#+1 cG>я#$^HBҐ{,wHF6ґ HJVPd+bINvғ&AIN:b1tR~ e,c Lz'$%S MD&-3LPޡte4Ljβ۹%5 _TC&ч 4fhZpE9[ x38YOf*Ӗg `o C+QPy6Ԙ?r1bʀ,E3J΃&t5̀@0h(,x_6ԡ-0PbҥMsIƀ5? iƠy12T-S˥6uHZ4O]ԔƼ*U9֖YV@h+.QL&@h. \ kZ)ԑuԃ1vnR{kC'0!l 6[Y⒱Zul5UZ֪qMmke;[ӑkmu۷.,__¸Enr\6׹υnt >(ҒnvA6o9o+܆׼.yc{^6)o{׾/|{_2@q;`6.u]7n};akz>_ /,݊MEQS8հr82(j0ͺZKqITȪ 2 96aԥcNvl%IKx9whÒ%ld^ E/"=AcX&!*Q{hE/QBC j1 c^$ɘ~neg rtW8tc=VF/֬Llb8u57iU2ٴ%+2maMJ"Ŏ_`;EQ;j}E&XWAo`%:XLRۂ m [fҘr/6W ʢYg,[1EA̸lXTbܸ |0g6a0 JJj1@q\#'9{Moܼ+7΃e>s9duscЅ>tGGzҕt;pyinotify/python3/docstrings/pyinotify.UnsupportedPythonVersionError-class.html0000644000175000017500000002640511402071465030060 0ustar ookoiookoi pyinotify.UnsupportedPythonVersionError
Module pyinotify :: Class UnsupportedPythonVersionError
[hide private]
[frames] | no frames]

Class UnsupportedPythonVersionError

source code


Raised on unsupported Python versions.

Instance Methods [hide private]
 
__init__(self, version)
x.__init__(...) initializes x; see x.__class__.__doc__ for signature
source code

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__, __unicode__

Inherited from object: __format__, __hash__, __reduce_ex__, __sizeof__, __subclasshook__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

Method Details [hide private]

__init__(self, version)
(Constructor)

source code 

x.__init__(...) initializes x; see x.__class__.__doc__ for signature

Parameters:
  • version (string) - Current Python version
Overrides: object.__init__

pyinotify/python3/docstrings/pyinotify.EventsCodes-class.html0000644000175000017500000004276311402071464024174 0ustar ookoiookoi pyinotify.EventsCodes
Module pyinotify :: Class EventsCodes
[hide private]
[frames] | no frames]

Class EventsCodes

source code

Set of codes corresponding to each kind of events. Some of these flags are used to communicate with inotify, whereas the others are sent to userspace by inotify notifying some events.

Static Methods [hide private]
str
maskname(mask)
Returns the event name associated to mask.
source code
Class Variables [hide private]
  FLAG_COLLECTIONS = {'OP_FLAGS': {'IN_ACCESS': 0x00000001, 'IN_...
  ALL_FLAGS = {}
  ALL_VALUES = {}
int ALL_EVENTS
Alias for considering all of the events.
int IN_ACCESS
File was accessed.
int IN_ATTRIB
Metadata changed.
int IN_CLOSE_NOWRITE
Unwrittable file closed.
int IN_CLOSE_WRITE
Writtable file was closed.
int IN_CREATE
Subfile was created.
int IN_DELETE
Subfile was deleted.
int IN_DELETE_SELF
Self (watched item itself) was deleted.
int IN_DONT_FOLLOW
don't follow a symlink (new in kernel 2.6.15).
int IN_IGNORED
File was ignored.
int IN_ISDIR
Event occurred against dir.
int IN_MASK_ADD
add to the mask of an already existing watch (new in kernel 2.6.14).
int IN_MODIFY
File was modified.
int IN_MOVED_FROM
File was moved from X.
int IN_MOVED_TO
File was moved to Y.
int IN_MOVE_SELF
Self (watched item itself) was moved.
int IN_ONESHOT
Only send event once.
int IN_ONLYDIR
only watch the path if it is a directory (new in kernel 2.6.15).
int IN_OPEN
File was opened.
int IN_Q_OVERFLOW
Event queued overflowed.
int IN_UNMOUNT
Backing fs was unmounted.
Method Details [hide private]

maskname(mask)
Static Method

source code 

Returns the event name associated to mask. IN_ISDIR is appended to the result when appropriate. Note: only one event is returned, because only one event can be raised at a given time.

Parameters:
  • mask (int) - mask.
Returns: str
event name.

Class Variable Details [hide private]

FLAG_COLLECTIONS

Value:
{'OP_FLAGS': {'IN_ACCESS': 0x00000001, 'IN_MODIFY': 0x00000002, 'IN_AT\
TRIB': 0x00000004, 'IN_CLOSE_WRITE': 0x00000008, 'IN_CLOSE_NOWRITE': 0\
x00000010, 'IN_OPEN': 0x00000020, 'IN_MOVED_FROM': 0x00000040, 'IN_MOV\
ED_TO': 0x00000080, 'IN_CREATE': 0x00000100, 'IN_DELETE': 0x00000200, \
'IN_DELETE_SELF': 0x00000400, 'IN_MOVE_SELF': 0x00000800,}, 'EVENT_FLA\
GS': {'IN_UNMOUNT': 0x00002000, 'IN_Q_OVERFLOW': 0x00004000, 'IN_IGNOR\
ED': 0x00008000,}, 'SPECIAL_FLAGS': {'IN_ONLYDIR': 0x01000000, 'IN_DON\
T_FOLLOW': 0x02000000, 'IN_MASK_ADD': 0x20000000, 'IN_ISDIR': 0x400000\
...

IN_DONT_FOLLOW

don't follow a symlink (new in kernel 2.6.15). IN_ONLYDIR we can make sure that we don't watch the target of symlinks.
Type:
int

pyinotify/python3/docstrings/pyinotify.AsyncNotifier-class.html0000644000175000017500000004543411402071464024525 0ustar ookoiookoi pyinotify.AsyncNotifier
Module pyinotify :: Class AsyncNotifier
[hide private]
[frames] | no frames]

Class AsyncNotifier

source code


This notifier inherits from asyncore.file_dispatcher in order to be able to use pyinotify along with the asyncore framework.

Instance Methods [hide private]
 
__init__(self, watch_manager, default_proc_fun=None, read_freq=0, threshold=0, timeout=None, channel_map=None)
Initializes the async notifier.
source code
 
handle_read(self)
When asyncore tells us we can read from the fd, we proceed processing events.
source code

Inherited from asyncore.file_dispatcher: set_file

Inherited from asyncore.dispatcher: __getattr__, __repr__, accept, add_channel, bind, close, connect, create_socket, del_channel, handle_accept, handle_close, handle_connect, handle_connect_event, handle_error, handle_expt, handle_expt_event, handle_read_event, handle_write, handle_write_event, listen, log, log_info, readable, recv, send, set_reuse_addr, set_socket, writable

Inherited from Notifier: append_event, check_events, coalesce_events, loop, proc_fun, process_events, read_events, stop

Inherited from Notifier (private): _sleep

Class Variables [hide private]

Inherited from asyncore.dispatcher: accepting, addr, closing, connected, debug, ignore_log_types

Method Details [hide private]

__init__(self, watch_manager, default_proc_fun=None, read_freq=0, threshold=0, timeout=None, channel_map=None)
(Constructor)

source code 

Initializes the async notifier. The only additional parameter is 'channel_map' which is the optional asyncore private map. See Notifier class for the meaning of the others parameters.

Parameters:
  • watch_manager - Watch Manager.
  • default_proc_fun - Default processing method. If None, a new instance of PrintAllEvents will be assigned.
  • read_freq - if read_freq == 0, events are read asap, if read_freq is > 0, this thread sleeps max(0, read_freq - timeout) seconds. But if timeout is None it may be different because poll is blocking waiting for something to read.
  • threshold - File descriptor will be read only if the accumulated size to read becomes >= threshold. If != 0, you likely want to use it in combination with an appropriate value for read_freq because without that you would keep looping without really reading anything and that until the amount of events to read is >= threshold. At least with read_freq set you might sleep.
  • timeout - http://docs.python.org/lib/poll-objects.html#poll-objects
Overrides: Notifier.__init__

handle_read(self)

source code 

When asyncore tells us we can read from the fd, we proceed processing events. This method can be overridden for handling a notification differently.

Overrides: asyncore.dispatcher.handle_read

pyinotify/python3/docstrings/pyinotify.Notifier-class.html0000644000175000017500000006105311402071464023522 0ustar ookoiookoi pyinotify.Notifier
Module pyinotify :: Class Notifier
[hide private]
[frames] | no frames]

Class Notifier

source code

Read notifications, process events.

Instance Methods [hide private]
 
__init__(self, watch_manager, default_proc_fun=None, read_freq=0, threshold=0, timeout=None)
Initialization.
source code
 
append_event(self, event)
Append a raw event to the event queue.
source code
 
proc_fun(self) source code
 
coalesce_events(self, coalesce=True)
Coalescing events.
source code
bool
check_events(self, timeout=None)
Check for new events available to read, blocks up to timeout milliseconds.
source code
 
read_events(self)
Read events from device, build _RawEvents, and enqueue them.
source code
 
process_events(self)
Routine for processing events from queue by calling their associated proccessing method (an instance of ProcessEvent).
source code
 
__daemonize(self, pid_file=None, force_kill=False, stdin=os.devnull, stdout=os.devnull, stderr=os.devnull)
pid_file: file to which the pid will be written.
source code
 
_sleep(self, ref_time) source code
 
loop(self, callback=None, daemonize=False, **args)
Events are read only one time every min(read_freq, timeout) seconds at best and only if the size to read is >= threshold.
source code
 
stop(self)
Close inotify's instance (close its file descriptor).
source code
Method Details [hide private]

__init__(self, watch_manager, default_proc_fun=None, read_freq=0, threshold=0, timeout=None)
(Constructor)

source code 

Initialization. read_freq, threshold and timeout parameters are used when looping.

Parameters:
  • watch_manager (WatchManager instance) - Watch Manager.
  • default_proc_fun (instance of ProcessEvent) - Default processing method. If None, a new instance of PrintAllEvents will be assigned.
  • read_freq (int) - if read_freq == 0, events are read asap, if read_freq is > 0, this thread sleeps max(0, read_freq - timeout) seconds. But if timeout is None it may be different because poll is blocking waiting for something to read.
  • threshold (int) - File descriptor will be read only if the accumulated size to read becomes >= threshold. If != 0, you likely want to use it in combination with an appropriate value for read_freq because without that you would keep looping without really reading anything and that until the amount of events to read is >= threshold. At least with read_freq set you might sleep.
  • timeout (int) - http://docs.python.org/lib/poll-objects.html#poll-objects

append_event(self, event)

source code 

Append a raw event to the event queue.

Parameters:
  • event (_RawEvent instance.) - An event.

coalesce_events(self, coalesce=True)

source code 

Coalescing events. Events are usually processed by batchs, their size depend on various factors. Thus, before processing them, events received from inotify are aggregated in a fifo queue. If this coalescing option is enabled events are filtered based on their unicity, only unique events are enqueued, doublons are discarded. An event is unique when the combination of its fields (wd, mask, cookie, name) is unique among events of a same batch. After a batch of events is processed any events is accepted again. By default this option is disabled, you have to explictly call this function to turn it on.

Parameters:
  • coalesce (Bool) - Optional new coalescing value. True by default.

check_events(self, timeout=None)

source code 

Check for new events available to read, blocks up to timeout milliseconds.

Parameters:
  • timeout (int) - If specified it overrides the corresponding instance attribute _timeout.
Returns: bool
New events to read.

process_events(self)

source code 

Routine for processing events from queue by calling their associated proccessing method (an instance of ProcessEvent). It also does internal processings, to keep the system updated.

__daemonize(self, pid_file=None, force_kill=False, stdin=os.devnull, stdout=os.devnull, stderr=os.devnull)

source code 

pid_file: file to which the pid will be written. force_kill: if True kill the process associated to pid_file. stdin, stdout, stderr: files associated to common streams.

loop(self, callback=None, daemonize=False, **args)

source code 

Events are read only one time every min(read_freq, timeout) seconds at best and only if the size to read is >= threshold. After this method returns it must not be called again for the same instance.

Parameters:
  • callback (callable object or function) - Functor called after each event processing iteration. Expects to receive the notifier object (self) as first parameter. If this function returns True the loop is immediately terminated otherwise the loop method keeps looping.
  • daemonize (boolean) - This thread is daemonized if set to True.
  • args (various) - Optional and relevant only if daemonize is True. Remaining keyworded arguments are directly passed to daemonize see __daemonize() method.

stop(self)

source code 

Close inotify's instance (close its file descriptor). It destroys all existing watches, pending events,... This method is automatically called at the end of loop().


pyinotify/python3/docstrings/uml_class_diagram_for_pyinotif_8.gif0000644000175000017500000001647411402071465025104 0ustar ookoiookoiGIF87a|LBDĤBDTĂ,"d^\̢jdbd,|T.,ܲ dJDvt<2,|^TĖTJDԪvl"D:4Ětܺ|fd64 \F<4*$dRTVTlfdԦrdrd~t̞TB<侼  <.,^\rlz|~tt^T$j\z|\NL*,lVLĆ,"$lZ\̦ 24\64ļvt䶴̖ 4rtZ\L><Ԧ̞̌NLԮ<24D:< \FD4*,Ԧ~|̞TBD$vt\JLTFDdNL|b\ztt^\jdlVT,G H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳ JѣH*]ʴӧPzիXjʵׯ`ÊK#SY˶۷pb ݻCc-uZ~W7h;fPkq@=IFNlrdi97,.J!.kQaOkT9RZ":2bH:h# i|5P̬5􀃷-[XkϞVw~mܫ}#W\UuG!K(ZLC|)&I̱ւ >;Ёsq0q_bh_t`xDͰI0ʸ!UR_ Hd'j-jE tHD bni_#kd要il@miBl@%ekY斃&Gyi`hD iHPm':f%*^{@>`'몭 _om):[h]Wn` [u([Xt1'(JJm%C+kuA/Qmz,J mY-']f*<2;P qh.k, 0*B&/+k*Cmܱ ,[|p 7!1>e&QPDVVA׆DK,H%XI2GP+T yDd^-C|G'tA-5Vct[sF k'dQ#2ywh_礗n][JTǮG",/o]`7ӈH4B+kpZ6ӵDqm5zϞ;SBƢ^^ԍcD@:iU \zƤU}_dֶG׺xҳ6r4_ X> 5 [ÙT/Vebcf 3cHڅfmLSI~ --u?/ A0 U1hPɰ)@}"G~ ?Kis6hCF5t Elp S*6' h _*z٥Ůc0c3K Fcayض4!fV+56 m@ӼEm27ֲ ߥ f|(//h`Z4KЏ}tgnռͭQjVֹom`,&Ra> t>7}iV-^M2̎ Gh X Aox;F}o𬻘iOz +S6riw- ,uײH}BRxVq,29PMlQtznq%S#-rs1vyFdf2s5F}>g8G>:G{kVmcotM5>CT;yv~dSttQg0 4u-8gGu.N9P3T8VhmgYo8wYքgW9y8{7JօZCxb~aixrKQC!M#jaysYkyL؆v1z$bMv$'zX${qQlDmNn(]'/{XVdB}BTCwnG-h~f\~%on!Q)oъ!hhsRP$0 /gg(ƀeWd7-VS˘J4oqsxu9P4'%>'r,((0@35hS긎1}ItTu:Bȁ!{Hx Duǒ0?8-yI6<2Vv!YUvE9e:tIN)?VKUoQK[L0kW\ǥ$hz{e]M9Ȧ])ƊHt}x~}~!.Dn5Ռg'~ &>lAqaW3R1v<7#S*rvc<7+F )GGFY)Ld$)OFF;ɓOU Nٝ1Y99~QBY:BNtVT9JLSI9QSRd[W9'ɱ_Y4Ɵ)f$V'{ Zvl2.^T rHIJc/vИ' Y37SvQrGМt[|tdY/)醆FztH#Guՙ l;-rzkZF}p|* Dwj8f-* 9SʥVkwiv]KE~!ʎ!\6kkrIUi(ɦ㥙[ZBফHɘ}ιʘFQoiأՑpۈaHp-h!6b%Gڑ8caqAӉd;wJxj [+wgJf&wY}ѨSjw^?ѩc5;*t!\D䖱zq걵 (]$J"}y^ӗkHv:E$mڀ_{ϊݲ.Bo$"o9Uȍ"u*ݪ##23ɯI8qqrX#K)sBtv$m<8\bj=#)ui@*k; ۝˓~Gб]u$z(Uٲ/1[UY[~AytQ{OQNORoqѵ˽onעuV;Djۍߺp!.{k7vl!л =7gzy+Vl'<) +̒-|*+- K:3˷99;ܼp񼣋f6ux#4[:j?{A Ď+R%5x1Rh\Lۯ[LB[Т/]{`Ş Z9_^חxpѶmt|~[{m{}&33S`+mx7ocQ5{z@ |Ĩ*tiָܸӺMV° М/94I><\lNA: \|<@<]>_Z]5  10 BP&P0 p0} 1#0B%W0D@ 0LV@ @\ M]1Qm\IQGdPj eA 0t]5 x]0yׂ==؃]؆׈y، ׎eْՔ]V}٘ԚCٞӠ1=ڤgڪڬڮڰۯs-۶}۸},pA oP:k9CfݷŭpܤSv9HV9 ح8݂XU<@ aCg潕ѳe4m}ܝzJIRz! ,L=@dmn!aѤN/N%nݗ'S(-N`$jZ| -q!^܍}G+cfCe{b[ENkM~*;N܍-n4/8>80^cV>-ε3ݢi ɇ6y %3%Ս^N0D,q3s.<3nh.mOOqJZ5S )*˝Q778\CkynܓcԣٍF01z뺾uV./Ai-nˎ.۸ގ;>^.ވpQmq"=?>AhtR8 Rai.U3h,-Vmz\m<>&/(hG뫾8=?kŌ/1?b KM<>9?;:.ȼ"c_(q6I, .WHnT0QLNV/X# {Fɂx'ۓor poQMMwQA&aՓo d !k M +`aĩ?޷UyG.p>m1yPla C0ϟ% M 9p{ ]fj H f`G$aC[d>TZK }" r41@ <( B|QD-^Ęq"7  $ #X,5x4@SA0 eS@M5w>TPw 90̂-,9&ԣ-z g6Yv X)*M HΑ,t=j9.hJ Xj[V]L@(0rDU];6D# x첍 >EG{>"Ĵk \yü t}0aǭv>ow/2Β,Cu__o92o=$dA0B '/(0C 1@1DG1 1EW@_,O8$Fo1QтMt2H!ꁃ8cH%d2" <EbL8J/8D3M yB"8PQ3N9/2S8dN=āJ&#=3'(eJ(~M8QK*K?F%K@EI`QYeTgQThF[s]{_%ָaEceVegViZlv[fYp%v\rqEuSօ;ν(07_}_8`|ފEbᅂ'5 b*] 6x"~=x [xBe'dN8Pb1y[Ygx@c4 #=q$& e'k~ Yą\[` 8^j ^ W;c'l~!Xn湤V\($a`A; `[IՎ\u]|bRWxѰjE;").$ ZQv9ϸG&z]CxG}{o|x=^8VjR rlob!W8)x sA Z;YnFp4Zl5< v)(| L!bQLt͎x$FъWxuы,CFÌgDcոF6эo1VwĢeG3Zd2;pτf49MjVӚf691vӛg89NrӜDg:;pyinotify/python3/docstrings/identifier-index.html0000644000175000017500000011746011402071464022042 0ustar ookoiookoi Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

A

B

C

D

E

F

G

H

I

L

M

N

P

R

S

T

U

V

W

Y

_



pyinotify/python3/docstrings/uml_class_diagram_for_pyinotif_9.gif0000644000175000017500000004057411402071465025103 0ustar ookoiookoiGIF87a #|LBDČjdĂT$"$d^\Ģ|nd4dJD<2,ܲ |^TnlT>4TF<~|Ĭrt,dND|bTvtԴԪD><4*$  亼|vlĞ:<̦<24TJLԦD:z鷚K~eלeQLv̰]ͻϥ[U&Ϳ/س\^}#:PZW%:ʯޙ=[y!u9K_םfiqW]i4BH4hJ)NRڅ7d!th! Cj .H`w 2 9\p!L$yHI@G0Vbt78d9Ωv%!j.fjkR"qJwxNwbnx9)h2Bj&Ay磑Eq唛ij韀9JRha-N!b'*RG ~+y(gpGJIKNawH ~'.Z'j^,1d&/vlhhv06lھFLֿ&qxhf1Ʈm|H"2q$V%4lͦW@-DmH'L7,V(lգ M9ٍ4|']9O=;-Wn9P?9f9o.I~nkHUۚZjlq<[i"r ZqħԺtXokF\p{j:l Zw./F_+i򱿶!m{)v,y€| 4E~} t@3"&ׂ:@p@pgkpР,Z Q=o73jы%!PVbX#`4i O(EuO]Җ4s =@ T CS◚pwNnjo%DN9CBC=Њ֞vDuN~ $5b&NIO] L}ҌAS(w xfnKN2IWPHBD &8yE\W-XZ!Y+K\䣊qi 氖` w3O+O.d 8Cuf3 aL6b>JQ3d3P0VT=HG澏2#MiL=T+ei\RTiM=wSN;[O}9Ϗ*kj%nwPk癡qFm`49%t`%* 13+_άj=o`  p:BF0Py{CQxa9ˇ3CntN'MNWRKtiPLԣZM2T:m9f\jZuvk\;KjnVkzvW=h[-4g]vM64qJsWUo\[}B[tjf8} ~8P Wz7d ݚ0pkp="å\NN^v w)8j`(FS "jHlڨm|=Aw2S'>5)cer3-&e',cs& zIH+T\UǚY1%|L 1W$ĥ.hXomWs=|t.a<<=x,=swx4|SA?W+G6.9Z zҝ(]zR{{KNA%]#? LdOƘϾ 3{q b0.~^-1b0 %9A (ч$p@w8@p1P 1P a0 X8{(@w) G}@ :X0EPD`n E6PRM(X PXUHO_a8UXfXhNln:rtX!xxz؇~x7xxr~؈q`8(۷؉xIjvb|Cxj/ShsVыX!行LraNoFHad!%2D$$ Bwhg!e!\&AX vs$SLYD%)c'h.^xݘG `}v2MH{ԑKǍIi(K@)(,6*(/ c9Qw8D*Ғ2BV)Pfw8X%֒-Tgߑu'-^"ySQ)x/ᖯ!XUƗj l | 0}I9 1 Øs1Yqiy:xI9Y5up9ٚ3ٙ7yIiJ%Yqa9 [E,iYZWaYCHqtSC)ٜ) ّYAyz q?ӡ+ZTaifʟT9(z;zؙ.Zy.:٢402>z8$j9D;ʢ=/jNKzM:#ZGzXZ\ڥ 5X%gS?XNkj?̸Ye b7_Z[U[tB"F>c[#$\w 6y߉]]ѱGiaOs)9_)רwju'tdGCutGGVWzmd  d1ItK`Dfu+9\BePKbuge 7*MֺM-e9g)3:)Aʛaz yPԺQzZ(# |*8+ٰ k9{49) k& 7)5x&/p  >K ZolQ57#VJ2f-'`4UphnٖJ LnHatp'?@A?psV(ۯ*-Nv%o Do2ָm gJXNUXX+tFuXx2`s@bqZlC(DqCw\Cw[!tE[D[[[T*vr S@"m붋;'骞^u(\ڷn]*r[5^ߵᵩ/g/@xR D4WUpy6R_ m)G`GWaDU}"`f`HxuDs&Gqu[.J]R+W#VbMlK@PtW,QppcRJn'mMdoWĴZxw]Bd'RL^nNpA)e[ U1{;ܶ=eޒfgTyIɊ'.rOdffApG;˺ p v,?l cz΁z)ԩz0G[2<_uwgϡ{cL#Ko#ͻ|\'K,ν;tK/Ɩ̲^lC:/aOնmԔ} M%Pkʭ|;@5Z1X "єY+F&]o4чqhY[ϛ79;+ 7A"LTF< ZԿ;*RݐTm ^ũf_NMρdt LA(Ls FtBsr"oK(jӄȓClmuD'A8|؆-*bcLsהV+!vx"wNFwxt@b!3nk L ;p ( !*../[э?ҷ0)=otY9%s*.K1;OXQy eIX #ۈew* ^T rR(3źD qF\맪Q8aZϸP )0d/ qME:" b\rSmG*Sէg):^̝-tH:'VG=¤ ! x(_O]50^!a%^5^b s? An,0*5n/ ʹojH+A2]q䟻ad%GEB>x <PkN @ C!0Q*tp@K6H"F)rCHE4)p>UTU^ŚUV]~VXS$a2 1QPa؁Q D`%+Kj[ *JY 4,A%r޽}-+UXRKjUJAt0f͜ {-qi`~iYōG\rXϦ0(D!xJ%T,@ •8Q{_Ȥ=$G'( }G o ^XYB V0/[Bp1DG$DV@[$3B <`\qEi;".QCWӺ•% '<2IqF'իI21M5dQ1ꖸ.;r { O@s >{̤T{sx㏧sgM⑇>zozC|^z8V#8]U_7B ӁN` PvUЂVor)P сPB0XC e)` e'Ȅ&6D*r@D-fB <`QPc(Da3E #IIILtn 5 J0%/Ljr'fP8ՠ2dF6Kf:47f 5LUI5P\ve.󰎋eݫWV 2\X(i;cM E,_زƱL>5 2.*]u&Z( Y_[{ }eyi~%zju]_mjvݬP)sRV޴WP||)$|wo =]c{83˿~؝NV?O:V@Ӻc )92%3:T).Ӝ-+ z9 3d7k7Sy3+31C{(CS-4lD E,G3"I;62:5!T'6Z7 5=!3#T#>Z$_C55]s6^ä_ `l] k[Cl5i5[>%P*m+C3lZ 079s7Ca7:|727{rz7v2&xJ&8SăAFlD{븕 I(\$3)b(^$;9cS)EW#*>1R:Aqt Guj:)uL%@[kL?bAj]1 +a9;Na␷[;W p3ZcȺ*HS=}Z-) -!Iӊm<Ѽ-k<--< ..}D؛ڛڃ; Ӕǣ? K>{qJ˅ȏ<$ŵ?4dLDL*;t̠"<|Kl)ʬLǼL'dW@@@ Laͅ@Ӭ ,\lMzMaAaZ!º%Wؚ漍S8a$ B&'AD#$t=jBiB/H˴."CIN&Kêa#p/ؖ5L',\?D9:L a^Cdk;^RDM'G8 ' G& (Do|tDm7n{!EQ7YD5`◇Z\)9-'- :(+F*%*ݸabT9a1S%]Nƅ؁Me6-ЀK+pG.Mv,3QT|$Q5MZǸZt#PaBWx+P'# : GGMHs;LdDSFE0d%)9ؚ,8EE0Ix<<{VBՅ =ðg-ݤU:D \جKop4T/ףYuWWqݡKKXL~W̅uvEM |X?XX?XRX% YْUYqؓ% ѼV+͝-vu4 Fùz`~L+P]8aMȼ;_HS]m\HV+W;wȹ,ȇՈ"l_VBVeeXjU *Ik)ITɋ,+h'po0ek/]~ p p  ]pqW ?qvUq l1Bfu6Yfifw- OgffmIZ- n)`mqxyV!)?A ܸFOiY[6pΈ[%Lh1OhsCִs2tۭP5TAݠCQjܘf^հYi]*Dg l= {B^^yOZַL^^V,7K4ݜXk?Ep pM S߲k%/fVk3EnliFlN+SZWl > T;`H~G G~9&*2|GHR5;NTCȈMԈdmm`ambyx;;KeϪ-:a%6p㶼ī֙dn,5~-3ꎭ/n y*' nJl^{A>Q>⛛<yߊ/? {eoq;|w|W#5ӗ O}Y}>}}٧S@R2 pPXemPE6UmWaIEU5dW{upMmXrG,\OGl&[6/Ⱇ&;ջjNɷN7}Yn-_G4EAN}6Qo=LNDPBRdE-E0ۉع9$4 1W(o{w¨f;ag)Q{AR&-K_ Ȅ%-zᙎ́hWHs$$M$,P(W=:xMYش'N/S⨪hm!E01RbNũ4ƄmH=Ɏx#wAk<IEΐ|dI>ʑd %IMF̒$l4QΓ<^IUbď|eLTY̔\dI]ƖLt]Ƽ(2f>Ȕ&6)RLkS6Ko~s-əFGD+YNByI# ZPTBPD)zG^b(9s}_~gzAć+.- y+KjR)ѥ,MߴvyTcj'[RsL&ՠ#SXU8Mu=.LY91s@|laGx2=[Vҿ.X R3i)X.x,0U5NB88v Uh7 Y;Fz fR>qX淓Э0˪門:U2dU@Kxkxt76`^ Uq0t'ӑW IϬ|zBG}߶J'OKk /A ;Wt3 bDtPX!\001 dbΨ:;rϲ/b.J=~ v5.LY.1L.n& 2 E+%٢}LA#l1cuHeE#bJ#=o9=1OW5H}.AԨfYӺֶ5s]׾L`>6WK~6-iS֦6b0ks6gf; ʭnJ@ 1ĺmĠ胼hLP{Ap{F"5&s3 S"4A;3 @ r1pDHPpoHwH@DL IĠ6 :h0NAңF`zիsKA.ů#~8c/˽֢>,O* "/(+Bb# K^/r73s<`?=SkEyc/Ӿ=s=/?>3@[!Sֿ>s>/;,}gTU`?/'@_]ȁ &y @A- fn z_F_ ڟ@) N V_ Ơ `  DA# N(B(GB! !A .a,aq*!))h!@! ] ơ*y@.BZa,xM-d|-.!&@"8ڄ8$Bơ9(026cD*bC>d@D %_5AGRDZ &IaAA$KB>A!;' JLLd2N_M"NVb hbQ%P~bBF$T`JJFUjBzDI @Vr% %j%¥\~%A 'tFtN'u]Ăvn'wvw~'xx'yy'zz'{{'|Ƨ|'}֧}g@*Jq`"K'+ K(6>h *hK0(V^J(KP(v~g8'hiJ(gu(ƨ(fuf}樎(()g~ &~.)FqAh- )m*b-Ο b)a).dߛ|BI`ߜi&|#)@RR I 1.~_l>* #j*D|")zࡊA(•erBB*lOr^^"5iJB(\BB\ !&4%>"nB%́'(!:! *BdL_k/Ba*Mk^b:+r++$.$k+f-k>kk+b)ZaɎinÊk.&ȂҪ+bBTj츖>;BB"ϚF˖"=ZZ!BfaRd.x&bY,"b.y"("$B'`Bm(-@MR"@.-ŤFl2% ҭ- .blȫnivmDzέ$"bǢ.h.p&f-&//fN_ |"Fn.Rve"&*o.Vf#2o2$zy-ZN6 <"(4%\c6ZBTB+ha_"XFj3GF6,XA[db5006.HJ*iv  %0̰0 S4~$;#4Ÿ.(<"HZ1κDΪWZ s0N*b30bj0C"1$q Ij,ZRղ,Z*cDjr&%()+$Cd"7>*?$"\%2Ж.j)r(# g)/&'(,+C$[/rO3;6B@1'w%@_7 213q-a63^/OBA '`(4"bj$?k:V31nrl"BL>;31=3CES,-4Dl1Dֲ0{$N=+bH:I7e4q*(@05kV/ A`@SEttM24-QbO-S#!Gq(oAbS:e2*š5(5-l$PPڟ.<(|(B.[7% +D~uX26Zb.e[G4T4MP_O>BRba?3g%ef_c"\\24e*"B*u\Abvi~j߯NgoϵPNiVgWC$@(ZAG%^c#B{w^n*,2[Nl)`%,@N`_wv6$wF771sz[2aO6}7¾e\"8v+"ץDŶ ǬЬy1?N7xHEAUwzex|wF.XέaT׸7eythK&(_b_wߕ_c!+fmy )+4yBeui¹h&y9ib`⠿ *TV&n=:o. 6zpo:;ēv:B~I::Ǻ:I\,:纮::;;'/;7?;GO+](do;w;;;;;ǻ;;W绾;;<<'7? pyinotify

Module pyinotify


Classes

AsyncNotifier
ChainIfTrue
Color
Event
EventsCodes
ExcludeFilter
Notifier
NotifierError
PrintAllEvents
ProcessEvent
ProcessEventError
PyinotifyError
PyinotifyLogger
Stats
SysCtlINotify
ThreadedNotifier
UnsupportedLibcVersionError
UnsupportedPythonVersionError
Watch
WatchManager
WatchManagerError

Functions

STRERRNO
command_line
compatibility_mode
logger_init

Variables

ALL_EVENTS
COMPATIBILITY_MODE
LIBC
LIBC_VERSION
__author__
log

[hide private] pyinotify/python3/docstrings/uml_class_diagram_for_pyinotif_2.gif0000644000175000017500000001666111402071464025073 0ustar ookoiookoiGIF87a0LBDĤFDĢ$"$|lVLf\nlvtĺ <2,dJDlfdԦĖfdTJDvl$D:4,tĆnl T><4&$ܲԮ\F4TF< |lZ\j\dNDԪrd\JDzl$|̒  *,4*$|f\쾼̼lRLVT̢̞,&$z|rtĬRTlVT~t<24tbdԦĚ$D:<:<^\ܮ䶴Ğ̒ԪD64\NLܶ侼|fd rd̦ \FDt^\|b\dRTL:Kh\`htk;z ,*t5 !4$MeCMv8E0SD_ F YzeN=`-DYxF]4ڈ#u~32!uazU]wHfOBEa*Wf|-TndMB9](.".ڕD}v'}p&)kmyY]ه4AH~EC 1][2t)'r)uޢ5 Wo@@GA[45*+XTtk,9G29j+.`v㦫n`嚻Xc+ܺ{oտ,UzT$ 7G,hKƨRs,2eT#W&0rl_,<7A ,DW4SL7=G'suOSSWu<jf $w0BfTjE䦭65kJJLw I!q1n H݅t| H uO1X)\&x`~7*PH$3RzeXu|@~SI7xbeV"JR^8~k]hv)uT0BG ĮT߫ķT~jFk&i*f%K<*֑0 *L/^_w.a\a@B-52`XzW B;!\EC}M]cJqEQ)buE,DE/)3H6n H:qM1cM> i LdrdB0,@$#d$ pC  !A "!E@!c# Hȥ@`bUH&Y1 Blhh8lj^z(:iZ2( )x`=Oxʳ5'@yρFP5B2p}"*ѫQG(Ful: HGJҒ(MJWҕ֠5hLgJӚtӞTh?~ӢONMEE/= TBSH&ZWuե5_) X³Yݪ[ץ&7o3`);K(+.:_i+G YB=T}v+dgYr*]Uv\e_;GƃSVT&8/GP# `[i[jdF0|n>L. u ]87#-DS8Duj'/۝p@I^MmvRT(!3&::y:YjXVrx+`Ze&egZ' 8α|@~+e ȔE|&;y J*[Xβ.S H'J2hNsS:q'QLgy"s{g^Tݳ9Ntd"slt` 6q{a,;c%MjI[h+Z (=Ug\Fޟ~[ )F3RiMP!n2M.K}'+CVҦvC,2ZUЍXf9AUP/,ouq + ./+D CKIx׺yA.W|lȔL8Lr.(?de]-:Ycm~tzQUK渺Ě=:ZжΚ W_Ȃjis˶og; $PE2a(>ռwpWV/|54Pb9_8r4b;=z4VWuـ$7Vq=v0s/pWa%d+,LIW} N.2Gi"F T ;wA%5~<<< kkv\\#t1$"$5AHj7%F{)˳#s7G]Uz$f%^.vaT-Hl<N.6AN80&ʖ]gyr&v8oAXmVpmFƆV7lo 012_E uf e=kX?6agVv$*Qa99vn vVpx`2։G:[BY= FbtC|w%AbroגAocFcaHy+2FbKb3~|q,,%DVU..w:֎"lg1U.ftF"v`f#~?X8EtDqP DxkDP&xFYtgg}}$ o!ih# g.Yl0)296 Nu"CU]5y7I`GfǓv"z'+Yi-.g|Ӌ;(]uAy92WAȧ|gy%z#zXgnS} ZUy~W}c]Ȗv[}9i8X$f[ƙ%=5XvY== =El26`xI_tAt~mqr8(qu &b)Bhaha ؉nmay+,荲ID,f$)-foh/4.19V.(2虞HDŐ萕DP3ipס $q&z/)F1u(uvFY6^*.b6CvIi17Tɓ73Wxt8yXi9QjoJiiqiOJzq&vI&JeE ut(@禉Y;Ҧ"@n@٤x\ &ȅ{ktk?k5`:@im]-Gl19&vș=]Rφ$ڇLK@tXsȫHXĹƩm`h*T8@T0DH3yѝwjʢFpGbHhQ (h&8+by$ YUY(.JU z{aDHd.I* p% "h!{Ė*;k,ETRuh|05{3@Л|ADJTU~8 *W˒ F>1@yuUD%n7W*V@S" F<@{Hz({N`XOBim u[P tظ#躵$p&k3Tbx`[S`|~at[s1]v*OvAbsX`KБJ2 rzԁ"{!aY3XSZ`W{,Wk[0A ujw7$XV@1Bzuoi t[q7r:o~Ej1-G[>Wva?YS@ K ~){ kl} ;|ʁ'[tAz,$o~A oK{-NAIGN`\KYjűY_uº> _|Y_j}\yB AL`\РUlţwOܠ4+30ɺmVil&@?`i靳LBC`pAbF"0CXPIº}-a!u1ZJ|!؉ջ &HbQˏN _'@6 0_\|$ºC<;Fpyt%Âoo֟t1ZZd +./ N- 17RJ(smdZ#z֊Ƶ|,tn 'FDpG؎ؐm$G]ٖ}٘F٠ڢ=ڤHTڨڪڃHI5dI}5ItG3JtJ 4J-#KdKdKtL144L4M.dMrQ(4NdN&NNM+Ur߰1~\  I~>EQ>AW">$^&~(*"~t,2>4^03}rjTCi8]0D^F~HJ%P @BC>H>RA\^R-`^f@P UnF>p Mp~x &CyF. @0vSn]fA荾$Pu耐s>k pP `鋾M!E @ nrpr cn@WCN  , 쯮nS P纞_ pD^~>PcP ~1~^eN %@d>c ,; |K.DP. /SNe~($j~ ~ uNs0P-*_0,K m S ! Ym0c-lLOI/K_j(lrn.p?x`^rz|-qp?_33>_T?_/O+~_(O&$!ȟʿ?>د!޿/?P: _p IE>Ѩ@ S2la-^Ę#>g<~RH%MD2e]l]Zƌ&AGvڐJEEeAm["u!A6ڴ 61g93X邕+W9(m4MXbKa g)[jV*ɋK+ 4yeFMD ]ih<[ j6/2%bōw,wL&X)HmƭM;.LYD1b_iW.dDǏ4M1[D<Ȱοh<$ʮ@DKϠ0'Ò3<=*)ZD eq 9*k@̰G60 AP4!(KX$e7iM%% ǖTѡ L 8{$NH5#D.) Mк p6JJ /mR,33LsMK/#Izð<<֘R /E5L/"cIzdz3KTw-jU2cEJSp;ds=WgQuYiVg]jT]h%\ qe]MW]mݥރu]tuv_z=  >,8 .5t _y_:ƂFcKc *8݌v^h&iSm#PG/z Zki, : QZBX8* M $amtł츶 +ժfo/Lb{q)OiKQDvl*CE5պh<5<,&$z|̢ĤFD,lfd\64䲤̒fdtlRLrt侼ĊĢ:<̪D64̢̚Ԫ\NL*,fd|ĚܮVTrdNL^\><~|܌ Ԧ<24$lVTD:sC-p_e_*`xDJ`00ʸ!UR_ Hd'j-jA tGFe ni_k]d&il%m}BlG%ekY斃&Yi`hDe iHPm':f,,^|A`'몭 _om):[h]Wn[u([WXt1)JJma,k07mz,J mY-']f0 Qt|,k,bD 0*B'/++ @mܱ ,[|p 7!1>e&Q JA'D&-GI%(mFP+Y\!d^-C|G'tA-5Vct[sF k'dQ#2ywh_礗n][KTǮG%\/o|x`7ӈH4B+kpZ6ӵDqm5zϞ;SBƢ^^ԍcD@:iU \zƤU}_EdֶG׺xҳ6r4_ X> 5 [ÙH/Vebcfh3cHڅfRSI~3 --U?0@0 U3|Pɰ)@}"G~ ^Ks6hCF5tc %lp S*6' h _*z٥Ůc0c3K &cayضa (fV+ۗE6 mLӼEm27ֲ % f(// h`4KЏ}tgnռͭQjVֹoR`,&Rb>K 4>7}iV-^M2̎ ׅh X Aox;F}o 񬻠iOz +S6riw- ,uײ6D}BRxVq,2SPMlQtznq%S#-rs1vyFdV2s5F}>g8G>:G{kmcotM5>C@$v~dSttQgaP 4u-8gGu.N9P3T8VhmgYo8wYքgW9y8{7JօZCxb~aixrKQC!M#jaysYkyL؆v1z$bMv$'zX${qQlDmNn(]'/{XVdB}BTCwnG-h~f\~%on!Q)oъ!hhsRP$0 /gg(ƀeWd7-VS˨J4oqsXu9P4'%>'R,((0@35hS긎1}ItTu:BȁA|Hx Duǒ0?8-yI6<2Vv!YUvE9e:tIN)?VKUoQK[L0kW\ǥ$hz{e]M9Ȧ])ƊHt}x~}~!.Dn5Ռg'~ &>lAqaW3R1v<7#S*rvc<7+F )GGFY)Ld$)OFF;ɓOU Nٝ1Y99~QBY:BNtVT9JLSI9QSRd[W9'ɱ_Y4Ɵ)f$V'{ Zvl .^T rHIJc/vИ' Y37SvQrМt[|tdY/)醆FztH#Guՙ l;-rzkZF}p|* Dwj8f-* 9SʥVkwiv]KE~!ʎ!\6kkrIUi(ɦ㥙[ZBফHɘ}ιʘFQoiأՑpۈaHp-h!6b%ڑ8caqAӉd;wJxj [+wgJf&wY}ѨSjw^?ѩc5;*t!\D䖱zq걵 (]$J"}y^ӗkHv:E$mڀ_{ϊݲ.Bo$"o9Uȍ"u*ݺ##23ɯI8qqrX#K)sBtv$m<8\bj=#)ui@*k; ۝˓~б]u$Z(Uٲ/1[UY[~AytQ{OQNORoqѵ˽onעuV;Djۍߺp!.{k7vl!л =7gzy+Vl'<) +̒-|*+- K:3˷99;ܼp񼣋f6ux#4W[:j?{A Ď+R%5x1Rh\Lۯ[LB[Т/]{`Ş Z9_^חxpѶmt\~[{m{}&33S`+mx7ocQ5{z@ |Ĩ*tiָܸӺMV° М/9/IA<\l<A? \|L<]>cP_ 0]5aO 1O T&TB Pp0}'P 1# 0I`B(`0FX0L&@;@ M]1Qm\IQGdIPUp je 0t]5 x]Q0yׂ==؃]؆׈y، ׎eْՔ]V}٘ԚCٞӠ1=ڤlڪڬڮڰۯs-۶}۸}6pA !\P:k9CfݷŭpܤSv9HV9 ح8݂XU<@ aCg潕ѳe4m}ܝzJIRz! ,L=@dmn!aѤN/N%nݗ'S(-N`$jZ| -q!^܍}+cfCe{b[ENkM~*;N܍-n4/8>80^cV>-ε3ݢi ɇ6y %3%Ս^N0D,q3s.<3nh.mOOqJZ5S )*˝Q778\CkynܓcԣٍF01Ѝz뺾uV ./Ai-nˎ.۸ގ;>^.N>p12a,7m.&KA@ z {?=faALFK\śW 05yk@0a iP Sp{ ]f` Ghp޷(E[AZH0 } D468F}n*-nR^pQb8l^`wZR@rL) ,[%DpDPSAS:0ʇs&n~o",>+_ϒ.ޝ@tO/>uR^S@@ JB >Q"C6-^ĘQF7"*H%IژRJ-]t(0męSN QDOEE Rv$UԈDU]TPv|EV-CB)j\^ZX}]UB*8EQTjzX䔙4PeΝQY(0!+UM+Rj֠ 8o#Y^ml}o%~\9˝Sm\zӭ~]{۽]C,^շwo~|ǟ_~ox?R  dA0B 'B,l BG$OD_F44(!ŃR1;20"=1@4>QH%O1G[lOXXr(Y*lɇvR [:B&XC(0)DHM*3QFaBSD-K/3Z0 ";=,C;ԡO>[RK,HpB:4VYMEs ZC4$( -.`U "W`bդBvDEoUE+lX$?>\-esVnQ66"D(MvEݷhKZlޅEq TW]XAUPz bYܖ[O,3UP ;LyeT 5J5&[w ($ZšEH@zIzId:0v2kFF{}Sކ;n离n;oa;p'|nݴGf<r/OzǼs!)?rGGtD'=p_Yw;vo{vQW}tw/x/'~=㏏޼-B>1D>GA D1 `%pM43.<r #T8@0 \ T" T($-  PXapL) R06&DOFh$UDX54xM8A#f>M)N/Uo`sF12ge 5:gt#+α cG>яd$^HBҐ4sHF6ґ HJVҒ "]|~d(E9JRҔ<)UIG2<%&5IR{,uKZp/W)K`l!Lfe/L @K ~%@M]a .hZ|Rws$&l'- >Р&*Ʌ7c&Tr-c`b '}@-"r1 N!%' \ SZn  +e/d΄$R;ѐ&UNE*X@* `qU(M,Ve"t]$d5+-Mlbs*`9Ut&E MWu |E%A8X,ke/PQNqT WrV}m, [Fu&a 8d%$rqPꖷ~fA6D-lUz=T\Lxd08 .L< oQi.ik2v1 7w^`v 1 8 ^ nE;NV .+1\w£MnٹWWW8RfUbfB5dqe-aƒL..MO>u+,1}Mث%V-SAE=hRxL%|YZS➪ij]NTµ0/qj{$v)92ԛ;3]lSwRe.! 1JYc2@uj]Pt{z|%1yukY[_ͪ6 Nia2%n)kYЖ,iCaorK[d-_).Wlm_җ#,z ^Wdz.o\-&:';K76|cW9'}ӠsАXX4=M'<,&$z|jlĤFDĊ|vt䲤̖*,̒rtfdlRL<.,Ģ̪D64ԪtbdlZ\亼䬊|ܮVTNL~|>< |fd^\̤Ԧ<24TJL|b\D:<$ \FDnl~|̞TBD\JLtZ\L:<,"$vtjdTFDdNLzt4*,,K5K H*\ȰÇ#JHŋ3LǏ CIdF&S\ɲ˗ QœI͛7eɳϟ uJQB*]ʴ¤NJ*իXׯٳhӪ]˶۷pʝ{؋b6,߿ LÈ+~ް+b#˘3_FKH͠CּvhI;1/kS`U !s=: ʍ_1̴-cbq9pȏ'5ơ J^9L,ÈςkI@HP9Y$Ͽ] X0Bz\vf6u YavqJ.}5 5T&*h \l%Hz&h0B[~6K*1ȩۍ{FI[| HD`GQاD؊@ `bQ2z"L&E+jtģ(H+tq< 򍂹fA"J`e/04DRԦ$`76 *>Bz)V*Q L ADjRY)ގ{ 0cEB1h~Wx̪ju? <8Y΂ Q7H!%-jY 餹%.ry\A+ȥ52+×Xd e1_!5aC *VVTlZR5h:SͥM3e"vJ˞R80vaHAu^op?-(U jP!T8 C&R(EwfQ`4*'xqhd>ꔐz z$UXR&Ϟ tt8Mx4@ B ׉REOnj̊jX Rj>"j1aU)8.JN0+55|$^ȥ"v0RtOԐT }F1l`1+ZfLB22$ȵ2(~O4V#OiScX"#Ǜ]̗#O2LӺKW5MjL 1 ߔӺ?: +*v ͑gt.ť` ҎwqR{T5cQaR9-'0'lBrX7{ ;|$b(NE\R'+8:,A%P(7Bl PTBJ{JlÒy)dGD) aKX9'_' M|aI` Ai/ X P9äV6R/5a? @KN ~0 $J ȄG +4-eQZ&"PU/duu\:տ^bdddٟ6@ljl 6-m{ܐAFέ#~wu}x;B}NO;\N'N[7: GN(OW0gNxCp6@ЇNHOqP y0}Ι^T`X7Z)p`;qs\hOڇދYT+bXUG:c)}@7E,Ot|\׻.D!Amh.|>%:O`#ކ lx+ >}ې|^lhBw~Іc9;y/E($H wh.s>e~PW ` >wevp` pw[' w7ЀHu`|WEyF~&Ig @w mPsPx?p}A  <t uC 8I9=8tR` m` RKMHuwǂ,OydG9s  ssC | ·Cgy u Bthx8wcs: s݇$jXy*8Qh ns t:@ NsDFsrtPzH@7>Wg@mALJ$gGMwo>s#hst0@> R` ?>G>(H@w08HuCPX)sg&8 `/ks }t7s} | y|`*s ɐ(m ^X19m ȏ'v0YS5:yx4d8 @Y@)$guE L9ňTZhg@0dYfyhjlٖnpr9tYvyxiea9Yyٖ{ٗ \דÈy^4Fy(dCٚYY YH򗉹ٛٛ9~ yșʹ9ؙҹvɚyعw9Й{IiJguY'yX詇g tywu~Y?d?}ZtwIt%tאd*t|Jtb}"Yw7uz|g|a8D }w xtYy(G}|G|2j{!)x ((S @ȁȌ\*tg@ m@pPv@Zu!8Hhwd m0"JfW& WIA8Q؅_Yy PuPW 3Exh>Gg+XWzt\ڧYׇX#iZtFYPnP}WȒ} ج Uʙ:vΪG RȊ A o,Ɏ||ګv7yz#z%j8u8䨪EGYy oHwK kyZ -I' ))|ȪzK* ȱ' hnjj ] C[I+h_vsvYk~PP}D{TJm u:`+9lTr{LIix۷:ʷ~;$*jhxɞɇk k}/ࠕkn+Twyᘾ|8|{] | -} -ڢ|KʫRʺ:}w 7wm`KϷ;LX?' zP*Ps ھ:+:y #[Zzux ̫+|\ يA P*PWbXІm($<|ਇ[xXgm}: bs ҹXiϷ(Y `ĭHuj*Ah(<>|@kӉ(tG+vNKWW੻ʤjs;: \TgRY DM 'ksup8 נbˏ'J, ls8>W͋8 Ϩ˞ +P{{|+ͷ|}Tg zyZ& m yIkm:'tNz},E˛{rʀzRG y_0ȬS@甦9{c{(כwimJt-*yͽujUͿʊQH^Xsmzh 7X=x_p *t> LͅցحZwʩt|Y}jyl\IJŝ{|",tm0D {ި ui扫^HJ u:ȃ$;К{. Ö׮'¨Hn[myPpDG?W^kyw̶XZϢMt2sZ߫u?g(wjJtt'n\ϼky؍( $mYpW;tа@G|D֫ ˰E>玹L ؗi,?ٳm,!9t{PA9(ja ڊ RwŬۜo̲FL`,| )E>g(/=~bǴ:m߁τ+X[ ˏu>v0ʘЎʲ~~흜Ku\>w ^k  υ>׈Dh!gy.m@Ƽ<@̔yܞb(ͪރp@w Ptpu@?K|@a?w΋z>Π}.wz !䴎Z?0>Lߩs޸Я{ =|A[0ƚ Mm|gA-J x>ݗ?>/|==+ ӫ7Ӻ7;:tcM}ϣKԦNyG- KO-Q8t_wV},|/z| ډm,%ߋ՟GAguimo;=ثm@jʦ?{}=cIT7ͅ}ۥ]F6lcRA RFm"h@Sv^y cņ$!_nUx1F%RDEWu P'M3BMB(mC[ \Z ̊*eVZJ7nuҹEFF E2%KcVĊ()ۈ5$V k`NZ^M<0'1kxċ .v<TJG n*LPsB ٨Jk/n];M~WL.p՜F6AKPk[0JFj$:*A$ZP;HA@+E)H Q!UސꑨҲ:x%EVHX#25̃<$B/%0CŔS)^C@ : 1Fҥh*RĎz RH*#&baM z63=+sΊ^!\ebC>ZE3l7+HXbeLEZL(t w\$ejh7]M2Xe^F$g i vc]ֶx}k%}=d_9fgnUb>fRId۟F:i۰XzgGjڼ.;5[ )(1IQz<ӦnNjۮm` 5 Va#?,r 7d+ )H `*0d*gmLQ?Rlb(R  BdB77Cԟ~w feUa:vR6:hZΰ>`i,3i33:R"<A`v$y&yu)B,I|x{%,(z11LcíL{f:4m0 XL4KP:FJS1rh)ҡu#H;-< $C=} ~Jt(A H R04T;-(j_ d4F2QldBhV ;Qf16 pgA)uKm^j郖ENv“'QTPZ`GݲjjCxCy TLLU]k 2+w4g!RYr6-W~?a|K]i^Q ޗ@&0mF;abC6&YcH222$]c3g-|e4ik*ekv&[֖$lk2چνWr7V_3Id/gܘle4͐rf:׹nj3g>s )ܴ!HnwQ&" >!]Yٺϗ|p堷Q.΀3={!ng>h}i[ӋYT{Oψ Vā@D 6DhI`)ӹ.a;=PڧvgXq|!h~D҈id"DS<1)@fq] Q(/Șrc6챏, نB<,T#ikʻ<59iOJDD'3a)t W<-CP%*KXB?0i`,3e׭jZf, ΆӹN4w1ʊV{*=uR$jBrT,T*(Dq9" 0Wцh|Z#R-)7B)JR[|cLcy4VnT3mxjT.gaSjDaʆGJ́(B\AX.&/(D )*|,,ɼCӔBd:@0uESC[, @CwȰZ|+ >86D3 ADkt%1HtDDK,MRr̲mN|PXp-j9EIEYQUُeYEMŕP/E&٘Ŕm٣3Te7SɦZ{ګ++Z#Z-$G4/X|CzGyd 4Ș,9ȄܱU?HZ1X`!$a|I6ͩ,[hDI\8̝4.ʘʝDʕ7*K};~k#Tˀ㖷>2>ݥ"]LL:L39LЌ|=ӕ=KMcMPMM쌥=:`N4N1%k_;Pko;);٢;; _E| Er؊X1 " $ , +#ESK)1` NjO7T8u:CAC;MT04T9 T@Ѳ T@@4a4U((+QUUqUW6!,e\6!bePDQBf.lV1Vj'$/h=PUVMcL`B C"3l035ܼ#ZWf|yC} >mIf^XU;D[D+HeՍ^]Z Y1AYzF-U\Zٝu-g&f̙*pvag6i>镾f>?^ZN5ʛFP v6 AHiM蟘ܧT͜@} 7h6Hj!iHU!N jX!9zK77C]]ץ;P7;D]Ԉ^̒M9LF$Є](Lk̎) F^Ͼl֐xv ߜ[MCTdFx9m#`%?n-.ϴ[F'd`|VNmFގ &nΚߊ6D,$`V= Eeh*p,%h;)&PQ`So `{JQgoF6pOKڔ❚ܫQ= b-6 -=!E@K.?/rJƽ¨Q2nX+bo6I95ܙ_y lPB,DRELuMHT5^SDE^/BG7tP}6ySDkvMFUOƭUUAZegE34I@ZF[F6<Y WOdBV/'(dAVV\ߎYIYB XoP-g'PuS`y1e/-PN_1frqvs Eȅ8D8O˂;J u}rxtXigsDJlJ/,j~p/qxRwvOhvrHnOin3 yib\?k4[!hy)y1hhxa褁薖 ڙ6tFzDNy[z^'7GW?1'/|CHyQgwLJȗɧʷ|OVg7GW'wׇؗ}oٷ'7~WgO~O;pyinotify/python3/docstrings/uml_class_diagram_for_pyinotif_13.gif0000644000175000017500000002211511402071465025145 0ustar ookoiookoiGIF87a|LBDĤBDĆ,"d^\Ԧjdbd|dJDT., <2,ܶĖvt|^TĞܪTJDlvllVL&$$D:4j\RTԢ,*$ԮĞ64 \F<̦rdnd쾼|fd~tL:4TB<~| ̤,"$Ԧ<24lVT$D:嚇.M~S壧|n/V.nS>s/o'i9џ.^gӄX3}/ELDŽzwֽYxLPף 64/x_FN'H%.zqAl["(HXrÕXe*V* [wEo]b!\"c\3 jhԝ,e)24DCrB,_/E`-)(`KǗ?h[BFp~H5[v2@>q%x GrK!SrDr(i#HapX2IEV{$"!yI24)O)Tu:[|q>1Kg=峜r2$ ,` 'Pa3LJ䑏":I}/GӪêW)ԏ6Ԉ =A-fII.xh`nرs-F I-|29tlߜ8Wdt)g\q3u(evޞ'繘.aԪ6ʫ[D9xzMmoLiK|J9!V1ى+>g=5 S6PEn\ U/P/hW2=y-lC.l! 3N6hCK~,SRA[{?U oD`S{/<,G߬w26 `(!vI쳒Wghv`إyaXK&[$P k;>A8%c E5/rh#'yb*GLʜ/4zl$!<.ϵیv|𹿽v#鼇f?a*AgЧ[_JOҪiV;y6ͨ_!H]up)ۑ%-mi_l&  a*no>(٩*6aLgBSdɶ!dHhD2{~.绫n6 1ŗ6h?/NW7g--~ S_`FRpC T `p`F`q~|A0G}gR"fr/s1$3 #CMqv郀 z@st?G7;Wt4ZvbIpuhsAucuW@rd'|$w\7Uutt-i(9WU{:jv1`Lngxp&dyr=t8SvxG|X:~TL5fUw!i9%yAi9878z1zSz zW0L,:T!5{V82vww(ŇlP,٤"$rmuJ!ȈNjFx^"vh([VVqwEn0o-"lQ 5%QBrr/ocR/Rq,r$ځR"51#r!s(Ȍ}"[.(vS687c7uSO587y󃠗A9vv1"9jP(hU8AX8ZE)4Bfw?H >ً(:{ѕ `IHWXEuAjFlXi4:Fbd {|5:(FZrGkKp{\Qԗaᅌօ]!r}*vU?n6~UO')A%BaMi* |p5pu13!h v׏aqsa.,7 0 1{cqt$cG*'7!?6aO7d mڃѓݩQĞt RjQeSy]FInIt9:J#*%' )+ڢe8yNS2*EQ9?9P?5xAGJpT6RBm^0DJrAn"ܸ~DEzW(tbzg )qэmZa7C(| y!)hJp_ٟ8闓ْC(S|fj: z j:*F Qj8Xv *Q*zxz5Z{i3*'|i!vѣ 7AChjkӁ\M\9R:9]ƥ!}HIF%kx:CvuZ9xq5pNǝ@r2[ut|'w$I=6c6t - ht{ʴhr;+:Rv*eLì`Kx.;8f hl+rJ:Ap{X-; @{;qv7qѮHz?#K* +$N״lݕD9ٞ<xrYT(Ӱkzaٸe[F(vX$`TRzgyՀi((&a'w0K iRR2;$kV ?ޛ>K6_]CA;L;F+yR1v+D_x7۳[ֵd%HZl[Cil l"LYx{hu¤ KU.pKUJ5}6V5MC,;G}^Uò*:dkrGpȼTR Ƚ4c kb3}`n;7<78>reƐcpx\0ܾX[eŊ <™y̼dw;y[8쨁;wܽ,t Lw9h b6tc \Zvq{ZĪ'%: 1W]훳̿i2\r/^g~i+ zvokoQ/2ɀٻ<l4a RUatHg&7l8 ;׿),>LI-4 #|!! *NPR=T]V}W\^Rm>Pf}hjlnք`t]v}k=z]g`׀` ؈@`D0ؐ= 0 9=9`0=9  V@ڬ]@{P ]/{` +a }]M ۾M}mo`}am]1 ^A. ^}>Q ">$^&~(n-`)..N׽W4n$0P4~3x$ >:}|yjύV9M.Z-h KS#f(\^[ K8d fNXRN$)Qb"ZP@%:M#$X 21bq-h✻&h-A!i.fKb'l-(`6h5[H,gtzr*nR>ئr/hrr^R虨 36/9㮾9c=c+1oRNZ55Z#r.Eo()TR8aCR9U=_=9ӖsCG$?&*?ePX2?4X3:wO/IAC+-EGIKM1_XZ;7<`O>/ZT=tiYQ(s ʢWHpx+ *,5~؀Ҷt1#d Kn R /˳1]_{.``; p}~.c0٧Lܷ KmʲſO!,)m `[L  H4;8Y_/بo7`-sb_OKs8,J@ DPB 1QDXEE:cE{%xdF3EZd2)8PN=y>YQ!<.q$"-H c!R1?ʤL ؈8}E!DD1sHb d(v+DHApɡ%*K֬ZʕmYs:+9"d'[Fz!fѭV-鈬b3V[w+|5}GdrCLι[zj̭_.9tjg^<]qͿ_=s=3w_A0@ D@D0cB0B 'B />C?G$Q CWdETĈNLpFoT(NTAFNJhN2I%LZ)e&pJ/TK VD3ͅR1`!5SN OO459 A OCA C HRR 0RMo|Ja!AٴTTUoD5U_eUXg%QVZoV\wNW^W`LXbEXdIYfUYh-HZjiv@7\q%\ssew v^{7_}_`xUzᏕ ʘ s-F`"B66 ;1X%Eq:ZQLcͨɆP jdڈ(MP7֙g7J+V 9UȖ5^HF i$H #QU2m ,PoC➻nzfѲ^hɐ6$hQx j% ˡ s0<ղy^hH&I~Yr/#*Wn:_,0ᮏ)@&|I ^qw$ J6џ!? 'zEZط/x10 J4g/ d hvNp )}d8 U*tCЇ?b8D"(aCpXD&6щOȐp5@h`1",Q! b3SdceF,wcu(E:Ďzd >rtcGD2Idd#HFR -yIdrdN _ JV+`,ȷ5KZe..X E/_K-J0OT S$r'g> NFhTGj+CiD:`:v;"HPQO: T?$Ozĝ(`,`¡5 &W`ʢD-.MGA $G%5RR0-rKWSj5Mq 4W7iz ,GEjRT6թOjT: LIժWjV@$ȫ_WI0լgEoz9`o}[:Wծw+]!׹8@׸ծlʇUucZڕXk[vV_ᚈE -g `uj=Y-mkVpE/Y> n- ؚ۸[k  zU}+W Mzw]W[oߚ-Cj1Yb Mz "xG`\c\ ̷q}jv{{z@A,bS b$bo݄f87?~ y,h 6?,|ȅ~q#s(1!I^r\klE<&!;d&u͛+e:'|ScuoE 7jC"VqLozHDQ PxWQL7Ak9a}CQze`9zk#=JԢkKd;{ף.Q^(Bz\lw\c; @uK\{/] $3"#΁mnt5q_mo|Vۖq%(WQkh*21H䛮p&gZf? \n#|pxeb\`)] 40J > j.4]\an\J]lW?>U{ouxO G6ꔉh bL$` ob ~z!R@ wa ݲDR`ⲽ+ ߸: a}oEҏ{q|_^-g.dB G_u@?_ُ7*5$ۿTd@<@# Af܀Rdtʬ{HA;Ac!$$T3@%(&ԉ'+BԈ@/01$C 4AHT5d6D8C†9C%C<Å+"Ί`,.a]? DDB:LXDAL8Jm BDbJ謼J9ĄDk+1J8r/+=/z]+8 F  Zŷ2F3fRĸSDG1{-P6I26dCǻGI pyinotify._SysProcessEvent
Module pyinotify :: Class _SysProcessEvent
[hide private]
[frames] | no frames]

Class _SysProcessEvent

source code


There is three kind of processing according to each event:

  1. special handling (deletion from internal container, bug, ...).
  2. default treatment: which is applied to the majority of events.
  3. IN_ISDIR is never sent alone, he is piggybacked with a standard event, he is not processed as the others events, instead, its value is captured and appropriately aggregated to dst event.
Instance Methods [hide private]
 
__init__(self, wm, notifier) source code
 
cleanup(self)
Cleanup (delete) old (>1mn) records contained in self._mv_cookie and self._mv.
source code
 
process_IN_CREATE(self, raw_event)
If the event affects a directory and the auto_add flag of the targetted watch is set to True, a new watch is added on this new directory, with the same attribute values than those of this watch.
source code
 
process_IN_MOVED_FROM(self, raw_event)
Map the cookie with the source path (+ date for cleaning).
source code
 
process_IN_MOVED_TO(self, raw_event)
Map the source path with the destination path (+ date for cleaning).
source code
 
process_IN_MOVE_SELF(self, raw_event)
STATUS: the following bug has been fixed in recent kernels (FIXME: which version ?).
source code
 
process_IN_Q_OVERFLOW(self, raw_event)
Only signal an overflow, most of the common flags are irrelevant for this event (path, wd, name).
source code
 
process_IN_IGNORED(self, raw_event)
The watch descriptor raised by this event is now ignored (forever), it can be safely deleted from the watch manager dictionary.
source code
 
process_default(self, raw_event, to_append=None)
Commons handling for the followings events:
source code

Inherited from _ProcessEvent: __call__, __repr__

Method Details [hide private]

__init__(self, wm, notifier)
(Constructor)

source code 
Parameters:
  • wm (WatchManager instance) - Watch Manager.
  • notifier (Notifier instance) - Notifier.

process_IN_MOVE_SELF(self, raw_event)

source code 

STATUS: the following bug has been fixed in recent kernels (FIXME: which version ?). Now it raises IN_DELETE_SELF instead.

Old kernels were bugged, this event raised when the watched item were moved, so we had to update its path, but under some circumstances it was impossible: if its parent directory and its destination directory wasn't watched. The kernel (see include/linux/fsnotify.h) doesn't bring us enough informations like the destination path of moved items.

process_IN_IGNORED(self, raw_event)

source code 

The watch descriptor raised by this event is now ignored (forever), it can be safely deleted from the watch manager dictionary. After this event we can be sure that neither the event queue nor the system will raise an event associated to this wd again.

process_default(self, raw_event, to_append=None)

source code 

Commons handling for the followings events:

IN_ACCESS, IN_MODIFY, IN_ATTRIB, IN_CLOSE_WRITE, IN_CLOSE_NOWRITE, IN_OPEN, IN_DELETE, IN_DELETE_SELF, IN_UNMOUNT.


pyinotify/python3/docstrings/class-tree.html0000644000175000017500000001433311402071464020650 0ustar ookoiookoi Class Hierarchy
 
[hide private]
[frames] | no frames]
[ Module Hierarchy | Class Hierarchy ]

Class Hierarchy

pyinotify/python3/docstrings/pyinotify.ChainIfTrue-class.html0000644000175000017500000003130111402071464024075 0ustar ookoiookoi pyinotify.ChainIfTrue
Module pyinotify :: Class ChainIfTrue
[hide private]
[frames] | no frames]

Class ChainIfTrue

source code


Makes conditional chaining depending on the result of the nested processing instance.

Instance Methods [hide private]
 
my_init(self, func)
Method automatically called from base class constructor.
source code
 
process_default(self, event)
Default processing event method.
source code

Inherited from ProcessEvent: __call__, __init__, nested_pevent, process_IN_Q_OVERFLOW

Inherited from _ProcessEvent: __repr__

Class Variables [hide private]

Inherited from ProcessEvent: pevent

Method Details [hide private]

my_init(self, func)

source code 

Method automatically called from base class constructor.

Parameters:
  • kargs - optional delegated arguments from __init__().
Overrides: ProcessEvent.my_init

process_default(self, event)

source code 

Default processing event method. By default does nothing. Subclass ProcessEvent and redefine this method in order to modify its behavior.

Parameters:
  • event - Event to be processed. Can be of any type of events but IN_Q_OVERFLOW events (see method process_IN_Q_OVERFLOW).
Overrides: ProcessEvent.process_default
(inherited documentation)

pyinotify/python3/docstrings/epydoc.js0000644000175000017500000002452511402071464017545 0ustar ookoiookoifunction toggle_private() { // Search for any private/public links on this page. Store // their old text in "cmd," so we will know what action to // take; and change their text to the opposite action. var cmd = "?"; var elts = document.getElementsByTagName("a"); for(var i=0; i...
"; elt.innerHTML = s; } } function toggle(id) { elt = document.getElementById(id+"-toggle"); if (elt.innerHTML == "-") collapse(id); else expand(id); return false; } function highlight(id) { var elt = document.getElementById(id+"-def"); if (elt) elt.className = "py-highlight-hdr"; var elt = document.getElementById(id+"-expanded"); if (elt) elt.className = "py-highlight"; var elt = document.getElementById(id+"-collapsed"); if (elt) elt.className = "py-highlight"; } function num_lines(s) { var n = 1; var pos = s.indexOf("\n"); while ( pos > 0) { n += 1; pos = s.indexOf("\n", pos+1); } return n; } // Collapse all blocks that mave more than `min_lines` lines. function collapse_all(min_lines) { var elts = document.getElementsByTagName("div"); for (var i=0; i 0) if (elt.id.substring(split, elt.id.length) == "-expanded") if (num_lines(elt.innerHTML) > min_lines) collapse(elt.id.substring(0, split)); } } function expandto(href) { var start = href.indexOf("#")+1; if (start != 0 && start != href.length) { if (href.substring(start, href.length) != "-") { collapse_all(4); pos = href.indexOf(".", start); while (pos != -1) { var id = href.substring(start, pos); expand(id); pos = href.indexOf(".", pos+1); } var id = href.substring(start, href.length); expand(id); highlight(id); } } } function kill_doclink(id) { var parent = document.getElementById(id); parent.removeChild(parent.childNodes.item(0)); } function auto_kill_doclink(ev) { if (!ev) var ev = window.event; if (!this.contains(ev.toElement)) { var parent = document.getElementById(this.parentID); parent.removeChild(parent.childNodes.item(0)); } } function doclink(id, name, targets_id) { var elt = document.getElementById(id); // If we already opened the box, then destroy it. // (This case should never occur, but leave it in just in case.) if (elt.childNodes.length > 1) { elt.removeChild(elt.childNodes.item(0)); } else { // The outer box: relative + inline positioning. var box1 = document.createElement("div"); box1.style.position = "relative"; box1.style.display = "inline"; box1.style.top = 0; box1.style.left = 0; // A shadow for fun var shadow = document.createElement("div"); shadow.style.position = "absolute"; shadow.style.left = "-1.3em"; shadow.style.top = "-1.3em"; shadow.style.background = "#404040"; // The inner box: absolute positioning. var box2 = document.createElement("div"); box2.style.position = "relative"; box2.style.border = "1px solid #a0a0a0"; box2.style.left = "-.2em"; box2.style.top = "-.2em"; box2.style.background = "white"; box2.style.padding = ".3em .4em .3em .4em"; box2.style.fontStyle = "normal"; box2.onmouseout=auto_kill_doclink; box2.parentID = id; // Get the targets var targets_elt = document.getElementById(targets_id); var targets = targets_elt.getAttribute("targets"); var links = ""; target_list = targets.split(","); for (var i=0; i" + target[0] + ""; } // Put it all together. elt.insertBefore(box1, elt.childNodes.item(0)); //box1.appendChild(box2); box1.appendChild(shadow); shadow.appendChild(box2); box2.innerHTML = "Which "+name+" do you want to see documentation for?" + ""; } return false; } function get_anchor() { var href = location.href; var start = href.indexOf("#")+1; if ((start != 0) && (start != href.length)) return href.substring(start, href.length); } function redirect_url(dottedName) { // Scan through each element of the "pages" list, and check // if "name" matches with any of them. for (var i=0; i-m" or "-c"; // extract the portion & compare it to dottedName. var pagename = pages[i].substring(0, pages[i].length-2); if (pagename == dottedName.substring(0,pagename.length)) { // We've found a page that matches `dottedName`; // construct its URL, using leftover `dottedName` // content to form an anchor. var pagetype = pages[i].charAt(pages[i].length-1); var url = pagename + ((pagetype=="m")?"-module.html": "-class.html"); if (dottedName.length > pagename.length) url += "#" + dottedName.substring(pagename.length+1, dottedName.length); return url; } } } pyinotify/python3/docstrings/pyinotify.ProcessEventError-class.html0000644000175000017500000002621511402071465025377 0ustar ookoiookoi pyinotify.ProcessEventError
Module pyinotify :: Class ProcessEventError
[hide private]
[frames] | no frames]

Class ProcessEventError

source code


ProcessEventError Exception. Raised on ProcessEvent error.

Instance Methods [hide private]
 
__init__(self, err)
x.__init__(...) initializes x; see x.__class__.__doc__ for signature
source code

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__, __unicode__

Inherited from object: __format__, __hash__, __reduce_ex__, __sizeof__, __subclasshook__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

Method Details [hide private]

__init__(self, err)
(Constructor)

source code 

x.__init__(...) initializes x; see x.__class__.__doc__ for signature

Parameters:
  • err (string) - Exception error description.
Overrides: object.__init__

pyinotify/python3/docstrings/uml_class_diagram_for_pyinotif_10.gif0000644000175000017500000002064711402071465025152 0ustar ookoiookoiGIF87a[<.,lRLtbdbdĂLBD|vtdԦ\NLܲrdf\,&$d24BD\F<  |D:4z|,ԪlZ\ܾnl̞ĺTJDĢ|bT$"$L:4 D64TB<~|$dNDĖvljd4&$ĚdJDzlܪtZT̪|bdtD2,~trdԢ䲤vtjlNL\JL |24쾼̢L>4TF<Ԕ&$VTJL䶴,*$|Ğܮ|fdԦ64Ԯ侼vț\FDD:<̞TJL|b\L:< TBD$dNLzttZ\L>3ψu択 BO}D"(BmEiYBrv9J]*SrէH%*̔J~Qrک3V0]D1RѤVFJ|jXr%xIZ²-fiY֔"jm\纮V$tͫ^3cWu ,_:EMb:d'KZͬf7X,#hGKҚMb=KHu!D ڶUmwTBD#o/>$qȖZ"'sk:@C(,' =sRXa0EhBN4Vƺ .vx&ARi$D0C gierQU E ^ڥ&>=b+7$DW%A*X{ 'B1FٙUh{Le}!حudy`W 090c.HFmtN˳>πoNF;*}h' 4d͔6Ly4$ONzVjIM]d=tqAHV3\ՔP2岦 `A-لn\PA&j8@fpyub Ѐ Νn:]N,lZ}y+$R]#r8MxSpVgKR8v0r' ,PIa=tfkIB *AͬηBʼoПoÚARxߜ]1y 4l q6A%#N50:ǹ`y:]0.p$ f`@$iEbO/C ťDD߷OXB bTpCR*A I=s ;UuM0y2i? W1pJ|RVc҅0`)}yAԥ([tB5 {Gjf`ПbfS:6tc4Wc;cc=&rGSc6ut%0 *=uvՖyǗjGVےc0T͢UGvUX%CVdK-JV0d)(vqI2V/x-&D`R`0 /_T X,I 7v.HuFW\(2T`lvb|kH(."F#~ #HgzTYAFPsE`VFiֈT(>FgVi[Z{twqj7o62rtkh~k(F/+Bm5RzmVTxDtr*roŠp#p^p4Ph˘*]y=WL ruKW_˄_BMV(hx]he|#tW$`w'y6]{yz5z ȤzcuQ|xQ|~Wt&ҕtq}R7k8IGGbSv$SMI1t1A 7`HcHzcSLTP}9Xakقdky1Éd_UlaUR\s"Ruz㒗}jo-*..ɠ?bY% eCYAJ]کXƩ\ 6Tji=0pv /Zrԫ~1 *˒8ՙ&&2vqZC%ȶW*!a7ʍ @r@{Qh#z(~UmO:]@u1nut&#[e3T2nؚja`r~aF|캒n0P~ k$fSxd^rI &GqknImX u!@ XKNk$%vJ!1ҁ~эpuK vS7)K ۩$Iuwwn =jZxq AG$k6PB :0)ɷٝPiILYu)jj^YW ` N99xWO{;Z0)XjjwPnwt1D 0AʐJכ ( fY{z#yP!{E{8gIQQ0 $ \+" V}ڠ0 &"}Co ]v{Y[u$1<{IUjf8?Y2:()Q `Rb)FIEZ&P``Z `)@.  u0džU jn\uz[Wj*S_QQj{Aqۥh &@8U[ɦ`*JǪaaU Y@ GK|6[=$2eʴz@8wnIʂ\Ŧk8dnҖU]Z [z*._1|ںY"ȏl1HlWZj̵L\dmӈcuCϮ{i0}Sqs }88 =8'B1BQ9ѕC::7:3qc;;(5< @2S>s&>>L13?C??Q/C?#;b-d]֋rh$jnpׯ1tv}׊z|[׀=HQ؆m' ْؐ=ٔ]ٖ}٘8ٞ٠ڒ}- ڪڬڮڰ۲=۴]۶}۱ 03==]}ܾPnSۖ`]}ۼ ]ݨ 0 C۳`ǭݥ=߭*ۖMMm2ܯ ϝMv w0N)pܚ0 0)`߯O}0d^1^>+Pp=ߜp J:7195n} -L B p PM^0OJSZ. PXfNc/e~M LMR_>P>@SP|yn/{m 30 pM-0 ߟ+ p)`=R>ްn.^뺾}ݒ.=>N+ pX 03.؞ڎYԾ^8~^:kb.NN~KNs>_Q-# Zxznݭx^=ݾ} `]p !O;`-߬ ;q0-0EO0 )0 ".>#n0b0J ⫠dP%>`K ]/.m. 2Npf0X0_ sLN_D~ߕ0n_F?OG-vO>O 0T ^ɯȯ0 `ܫo t^@_0Z~AIA >QD-dHF=~RH%KBxaʔ$A W (eƝ h"\2RMVTU^划 O%P啠*;b͞EZmjF +*da]})FuX`p-Rb%ƍ^:-JX橆//`ΥM,Zj13]:ukڵE[l۽}ŭ[[޿g|ő7L0QZjx Rӫ>ӥʙ79M?X'83 -_p$֋Ρb/cﳔf#1)Aj@-ЄDNdA_#! ,` bl;dÑؓ HF eTE r,č}҃>~R n |+, c 2 3bmFLO4"OO,k6m Oo3iSO},I`B& | Aǟ;+*b(j.-4(Iahғj*>[ t,iq^Z‡Fߑu -i_S'>YcTB=Dh(fѢozRhGf1(Ðp$6hRy450DLRTխ»dZ5+щԤ6vUO%UG9 B"g5U̬8)Zi:-ѹ kٳ2 s1:y$M$I6ֶm1R|X`Iڲql4vWd*pk[-iSQxiK X\eT5iQ/LcVl(r 34qΚ ;ULANrc:3S`Ȏv3aZ,hN}p%u ' xHXixVI:eH[Gp|d?d"$FIbJ!C8Q#5 -KxbQcc=O픾*eȉaAQ 6+ kiu7h.t.۬J"!$\N|"N 98uVB +UVt.+1'bK82T^y2,ɋ8X~+ewlh^zXe.c}ol?J^ʲ/L}{@~|7χ~?}W׏yOt?~Gտ~?$@/*DTdt ;pyinotify/python3/docstrings/pyinotify-module.html0000644000175000017500000005464011402071464022130 0ustar ookoiookoi pyinotify
Module pyinotify
[hide private]
[frames] | no frames]

Module pyinotify

source code

pyinotify


Author: Sebastien Martini

License: MIT License

Contact: seb@dbzteam.org

Version: 0.9.0

Classes [hide private]
  PyinotifyError
Indicates exceptions raised by a Pyinotify class.
  UnsupportedPythonVersionError
Raised on unsupported Python versions.
  UnsupportedLibcVersionError
Raised on unsupported libc versions.
  PyinotifyLogger
Pyinotify logger used for logging unicode strings.
  SysCtlINotify
Access (read, write) inotify's variables through sysctl.
  EventsCodes
Set of codes corresponding to each kind of events.
  _Event
Event structure, represent events raised by the system.
  _RawEvent
Raw event, it contains only the informations provided by the system.
  Event
This class contains all the useful informations about the observed event.
  ProcessEventError
ProcessEventError Exception.
  _ProcessEvent
Abstract processing event class.
  _SysProcessEvent
There is three kind of processing according to each event:
  ProcessEvent
Process events objects, can be specialized via subclassing, thus its behavior can be overriden:
  PrintAllEvents
Dummy class used to print events strings representations.
  ChainIfTrue
Makes conditional chaining depending on the result of the nested processing instance.
  Stats
Compute and display trivial statistics about processed events.
  NotifierError
Notifier Exception.
  Notifier
Read notifications, process events.
  ThreadedNotifier
This notifier inherits from threading.Thread for instanciating a separate thread, and also inherits from Notifier, because it is a threaded notifier.
  AsyncNotifier
This notifier inherits from asyncore.file_dispatcher in order to be able to use pyinotify along with the asyncore framework.
  Watch
Represent a watch, i.e.
  ExcludeFilter
ExcludeFilter is an exclusion filter.
  WatchManagerError
WatchManager Exception.
  WatchManager
Provide operations for watching files and directories.
  Color
Internal class.
Functions [hide private]
 
STRERRNO() source code
 
logger_init()
Initialize logger instance.
source code
 
compatibility_mode()
Use this function to turn on the compatibility mode.
source code
 
command_line()
By default the watched path is '/tmp' and all types of events are monitored.
source code
Variables [hide private]
  __author__ = "seb@dbzteam.org (Sebastien Martini)"
  COMPATIBILITY_MODE = False
  LIBC = ctypes.CDLL(ctypes.util.find_library('c'), use_errno= T...
  LIBC_VERSION = LIBC_VERSION.decode()
  log = logger_init()
  ALL_EVENTS = reduce(lambda x, y: x | y, EventsCodes.OP_FLAGS.v...
Function Details [hide private]

compatibility_mode()

source code 

Use this function to turn on the compatibility mode. The compatibility mode is used to improve compatibility with Pyinotify 0.7.1 (or older) programs. The compatibility mode provides additional variables 'is_dir', 'event_name', 'EventsCodes.IN_*' and 'EventsCodes.ALL_EVENTS' as Pyinotify 0.7.1 provided. Do not call this function from new programs!! Especially if there are developped for Pyinotify >= 0.8.x.

command_line()

source code 

By default the watched path is '/tmp' and all types of events are monitored. Events monitoring serves forever, type c^c to stop it.


Variables Details [hide private]

LIBC

Value:
ctypes.CDLL(ctypes.util.find_library('c'), use_errno= True)

ALL_EVENTS

Value:
reduce(lambda x, y: x | y, EventsCodes.OP_FLAGS.values())

pyinotify/python3/docstrings/uml_class_diagram_for_pyinotif_5.gif0000644000175000017500000001716111402071465025073 0ustar ookoiookoiGIF87a0LBDĤFDĢ$"$|lZ\f\nlvtĺ <2,dJDԦlfdfdĖTJDvl$D:4,t4&$Ć|bTnl T><ܲdRLԮ\F<Ğ|亼ĴtbdԦL:4TB4TFLh\`hޔk;ZO,Ъt7 !4$7MfCMv8E0SD_ F YzeN=-YxF]4ڈ#u~22!uazU]wHfOBE^1*Wf|-TndMB9](2".ڵD}v'}p&)kmyY]ه3AH}5C (][!2t) r)uޢ5 Wo@@HA [45*+XTtk,9G29j+.`v㦫n`嚻Xc+ܺ{oտ,Uz@T$ 7G,hKƨRs,2eT#W&0rl_,<7A ,DW4SL7=G'suOSSWu;jf $w0BfTj!E䦭65kW&Lw(!q1n& H݅t| H uO1X(\&x`~7*PH$3RzeXu@~SI7xbeV"JR^8~k]hv)uT0BG ĮT߫T~jFk&i*f%K<*֑0*L/^_w$xa\^@B-52`XzW B;!\EC}M]cJqEQ)buE,DE/)2H6n H:QM1cM> i LdrdB 1,@$#d$ ?  !A "A!EDc# Hȥ@bUH&Y1 Blhh8lj^z(:iZ1(d )x`=Oxʳ5'@yρFP5B2p}"*ѫQG(Ful6 HGJҒ(MJWҕҠ4hLgJӚt ӞTh?~ӢONKEE/= TBSH&ZWuե5_) X³Yݪ[ץ&7o3`);L(+2:_i+G YB=T}v+dgYr*]Uv\e_;GƃSVT&8/GP# `[i[jdF0|n>L. u ]87#-DS8Duj'/۝p@I^MmvRT(!3&::y:YjXVrx+`Ze&egZ' 8α|@~+e ȔE|&; J*[Xβ.S 'J2hNsS8q'QLgy"s{g^Tݳ9Ntd"slt` 6q{a,;c%MjI[h+Z (=Ug\Fޟ~[ )F3RiMP!n2M.K}'/+CVҦvC,2ZUЍXfAUP/,ouq + ./+D CKIx׺yA.W|lȔL8Lr.(?de]-:YSm~tzQUK渺Ě=:ZжΚ W_Ȃjis˶og; P E2(>ռwpWV/|54Pb9_8r4b;=z4VWuۀ$7Vq=v03pWa-d+,LIW} N.2Gm"F T ;wA%5~<<< kkv\\#t!$"$5AJj7%Fz)˳#s7G]Uz$f%^.vaT-Hm<N.6AN7 &ʖ]gyr&v8oAXmVpmFƆV7loj012_E@u= f=kX?6agVv$*Qa99vn vVx`2։G:[2Y=FbtC|w%AbroגAocFcaJy+2FbLb3}|q,,%DVU..w:֎"lg1U.=tF"v`=#~?X8EtDq@ DxkDP&xFYtgg}}$ o!ih# g.Yl0)296 Nu"CU]5y7I`GfǓv"z'+Yi-.g|Ӌ;(]uAy92WAȧ|gy%z#zXgnS} ZUy~W}c]Ȗv[}9i8X$f[ƙ%=5XvY== =El26`xK_tAt~mqr8(qu &b)Bhaha ؉nmay+,荲ID,f$)-foh/4.19V.(2虞HDŐ萕DP3ipס $q&z/)F1u(uvFY6^*.b6CvIi17Tɓ73Wxt8yXi9QjoiiqiOJzq&vI&JeE ut!@禉Y;Ҧ"@n@٤x\ &ȅ{ktk?k5`:@im]-Gl19&vș=]Rφ$ڇLL@tXsȫHXƩm`h*T7@T0DH3yѝwjʢFpGbHhA (h&8+by$ YUY(.JU z{aDHd.I* p% "h!{Ė*;k,ETRuh| 5{2@Л|ADJTU~8 *W˒ F>1@yuUD%n7W*V0S$ F;0{Jz(zpN`XO2imju[P `tظ#躵$p&k3Tbx`[S`|~t[s1]v*OvAbsX`LБJ2 rzԁ"{!aY3XSZ`W{,Wk[0A ujw7$XV@1Bzuoi t[q7r:o~Ej1-Gp[>Wva?YS@ L ~){ kl} ;|ʁ'[tAz,$o~1 o(L {-NAIGN`\LYjűY_uº> _|Y_j}\yBjA`*`IРUlţwOܠ3K20ɺmVil&@?`i靳LBC`p1bF$0CXPIº}-aqu1ZJ|!؉ջ &HbQˏN aP@6 0_\|$ºC<;F0qyt%Âoo֟t1ZZd +./ N- 17RJ(smdZ#z֊Ƶ|,tn 'FDpG؎ؐm$G]ٖ}٘F٠ڢ=ڤHTڨڪڃHI5dI}5ItG3JtJ 4J-#KdKdKtL144L4M.dMrQ(4NdN&NNM+Ur߰1~\  I~>EQ>AW">$^&~(*"nd,2>4^03{rjTCi8]0D^F~HG0K`PBW.JC\`-a~`~]\` hF^ V>Y\xg>ANjM h>+@ @ + vnndn2f^x>,vvMAo]BF%%]0~~XNꦎW~ qp0{e>jp vN ^Q ] M `מnc1_x ,`w>䈐DUn^: ] :d@ v$I C^ PQ Dež겾dq p@̮+^3,]P C^1_ _J^*vN]@ p`"@ On 0fh0M ^oB_0DYM O, MZ'0d-m9?? 솿//o/_@.??[#p ʿ?_؟r03EE&O_2o?/oE@ $` >QD-^B=~RH%M TQJ-]>L5męSN=}T(Or^E%M>UTU^ŚUVX)(V,C'͞EVځ)Ǿ,[u-6^X0]} v#Œ$r8:R³~t-|Xă!dq.59:sm6zhaK^吣=~R::DxwoG/ǃRJnԥ(peS  M.s38Գ=Pj@Q:/=Ѝ.Cs1rQN)SDc?hhb-Ҥ&@q R&,QE,h#HLq1!Toq 5 jc?(8# ӏRXd J`#;£6d DO.%҉Xdo P~ÆVāhzxݏ>{-@<7z"t ,BoEA( ~D$C8וU-F6&PW,JDHYa?G>@ZcVdC:Qꂜ45! s/V&F;ᩎ/:x3dS$E-N/!JYrŽUIT%SUIvpC)+Y%ST$V-e 'Ii[%|˗ #!JQAuhIY%VIxi qAqYB1˅=@d)+4g\%bw2|E3@T~@ @ůsJq+cIz0ɪ^eU IQ# e:r8dBd ׉8"3Y\3e9 : K .LP?SlJRHb TB)ҷ,uwr4j`vm3+:8oi[Yqկw^Y׿V1!lKkX*gCd%;YVֲlf5Yvֳf،tŴEmjUZ"mle;[ֶmnu[ַnp;\׸Enr+;pyinotify/python3/docstrings/help.html0000644000175000017500000002473511402071464017545 0ustar ookoiookoi Help
 
[hide private]
[frames] | no frames]

API Documentation

This document contains the API (Application Programming Interface) documentation for this project. Documentation for the Python objects defined by the project is divided into separate pages for each package, module, and class. The API documentation also includes two pages containing information about the project as a whole: a trees page, and an index page.

Object Documentation

Each Package Documentation page contains:

  • A description of the package.
  • A list of the modules and sub-packages contained by the package.
  • A summary of the classes defined by the package.
  • A summary of the functions defined by the package.
  • A summary of the variables defined by the package.
  • A detailed description of each function defined by the package.
  • A detailed description of each variable defined by the package.

Each Module Documentation page contains:

  • A description of the module.
  • A summary of the classes defined by the module.
  • A summary of the functions defined by the module.
  • A summary of the variables defined by the module.
  • A detailed description of each function defined by the module.
  • A detailed description of each variable defined by the module.

Each Class Documentation page contains:

  • A class inheritance diagram.
  • A list of known subclasses.
  • A description of the class.
  • A summary of the methods defined by the class.
  • A summary of the instance variables defined by the class.
  • A summary of the class (static) variables defined by the class.
  • A detailed description of each method defined by the class.
  • A detailed description of each instance variable defined by the class.
  • A detailed description of each class (static) variable defined by the class.

Project Documentation

The Trees page contains the module and class hierarchies:

  • The module hierarchy lists every package and module, with modules grouped into packages. At the top level, and within each package, modules and sub-packages are listed alphabetically.
  • The class hierarchy lists every class, grouped by base class. If a class has more than one base class, then it will be listed under each base class. At the top level, and under each base class, classes are listed alphabetically.

The Index page contains indices of terms and identifiers:

  • The term index lists every term indexed by any object's documentation. For each term, the index provides links to each place where the term is indexed.
  • The identifier index lists the (short) name of every package, module, class, method, function, variable, and parameter. For each identifier, the index provides a short description, and a link to its documentation.

The Table of Contents

The table of contents occupies the two frames on the left side of the window. The upper-left frame displays the project contents, and the lower-left frame displays the module contents:

Project
Contents
...
API
Documentation
Frame


Module
Contents
 
...
 

The project contents frame contains a list of all packages and modules that are defined by the project. Clicking on an entry will display its contents in the module contents frame. Clicking on a special entry, labeled "Everything," will display the contents of the entire project.

The module contents frame contains a list of every submodule, class, type, exception, function, and variable defined by a module or package. Clicking on an entry will display its documentation in the API documentation frame. Clicking on the name of the module, at the top of the frame, will display the documentation for the module itself.

The "frames" and "no frames" buttons below the top navigation bar can be used to control whether the table of contents is displayed or not.

The Navigation Bar

A navigation bar is located at the top and bottom of every page. It indicates what type of page you are currently viewing, and allows you to go to related pages. The following table describes the labels on the navigation bar. Note that not some labels (such as [Parent]) are not displayed on all pages.

Label Highlighted when... Links to...
[Parent] (never highlighted) the parent of the current package
[Package] viewing a package the package containing the current object
[Module] viewing a module the module containing the current object
[Class] viewing a class the class containing the current object
[Trees] viewing the trees page the trees page
[Index] viewing the index page the index page
[Help] viewing the help page the help page

The "show private" and "hide private" buttons below the top navigation bar can be used to control whether documentation for private objects is displayed. Private objects are usually defined as objects whose (short) names begin with a single underscore, but do not end with an underscore. For example, "_x", "__pprint", and "epydoc.epytext._tokenize" are private objects; but "re.sub", "__init__", and "type_" are not. However, if a module defines the "__all__" variable, then its contents are used to decide which objects are private.

A timestamp below the bottom navigation bar indicates when each page was last updated.

pyinotify/python3/docstrings/redirect.html0000644000175000017500000000327011402071465020406 0ustar ookoiookoiEpydoc Redirect Page

Epydoc Auto-redirect page

When javascript is enabled, this page will redirect URLs of the form redirect.html#dotted.name to the documentation for the object with the given fully-qualified dotted name.

 

pyinotify/python3/docstrings/pyinotify.Stats-class.html0000644000175000017500000004100311402071465023033 0ustar ookoiookoi pyinotify.Stats
Module pyinotify :: Class Stats
[hide private]
[frames] | no frames]

Class Stats

source code


Compute and display trivial statistics about processed events.

Instance Methods [hide private]
 
my_init(self)
Method automatically called from base class constructor.
source code
 
process_default(self, event)
Processes |event|.
source code
 
_stats_copy(self) source code
 
__repr__(self) source code
 
dump(self, filename)
Dumps statistics to file |filename|.
source code
 
__str__(self, scale=45) source code

Inherited from ProcessEvent: __call__, __init__, nested_pevent, process_IN_Q_OVERFLOW

Class Variables [hide private]

Inherited from ProcessEvent: pevent

Method Details [hide private]

my_init(self)

source code 

Method automatically called from base class constructor.

Parameters:
  • kargs - optional delegated arguments from __init__().
Overrides: ProcessEvent.my_init

process_default(self, event)

source code 

Processes |event|.

Parameters:
  • event - Event to be processed. Can be of any type of events but IN_Q_OVERFLOW events (see method process_IN_Q_OVERFLOW).
Overrides: ProcessEvent.process_default

__repr__(self)
(Representation operator)

source code 
Overrides: _ProcessEvent.__repr__

dump(self, filename)

source code 

Dumps statistics to file |filename|.

Parameters:
  • filename (string) - pathname.

pyinotify/python3/docstrings/pyinotify.ThreadedNotifier-class.html0000644000175000017500000005207011402071465025163 0ustar ookoiookoi pyinotify.ThreadedNotifier
Module pyinotify :: Class ThreadedNotifier
[hide private]
[frames] | no frames]

Class ThreadedNotifier

source code


This notifier inherits from threading.Thread for instanciating a separate thread, and also inherits from Notifier, because it is a threaded notifier.

Note that every functionality provided by this class is also provided through Notifier class. Moreover Notifier should be considered first because it is not threaded and could be easily daemonized.

Instance Methods [hide private]
 
__init__(self, watch_manager, default_proc_fun=None, read_freq=0, threshold=0, timeout=None)
Initialization, initialize base classes.
source code
 
stop(self)
Stop notifier's loop.
source code
 
loop(self)
Thread's main loop.
source code
 
run(self)
Start thread's loop: read and process events until the method stop() is called.
source code

Inherited from threading.Thread: __repr__, daemon, getName, ident, isAlive, isDaemon, is_alive, join, name, setDaemon, setName, start

Inherited from threading.Thread (private): _set_daemon, _set_ident

Inherited from threading._Verbose (private): _note

Inherited from object: __delattr__, __format__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __setattr__, __sizeof__, __str__, __subclasshook__

Inherited from Notifier: append_event, check_events, coalesce_events, proc_fun, process_events, read_events

Inherited from Notifier (private): _sleep

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, watch_manager, default_proc_fun=None, read_freq=0, threshold=0, timeout=None)
(Constructor)

source code 

Initialization, initialize base classes. read_freq, threshold and timeout parameters are used when looping.

Parameters:
  • watch_manager (WatchManager instance) - Watch Manager.
  • default_proc_fun (instance of ProcessEvent) - Default processing method. See base class.
  • read_freq (int) - if read_freq == 0, events are read asap, if read_freq is > 0, this thread sleeps max(0, read_freq - timeout) seconds.
  • threshold (int) - File descriptor will be read only if the accumulated size to read becomes >= threshold. If != 0, you likely want to use it in combination with an appropriate value set for read_freq because without that you would keep looping without really reading anything and that until the amount of events to read is >= threshold. At least with read_freq you might sleep.
  • timeout (int) - see http://docs.python.org/lib/poll-objects.html#poll-objects
Overrides: Notifier.__init__

stop(self)

source code 

Stop notifier's loop. Stop notification. Join the thread.

Overrides: Notifier.stop

loop(self)

source code 

Thread's main loop. Don't meant to be called by user directly. Call inherited start() method instead.

Events are read only once time every min(read_freq, timeout) seconds at best and only if the size of events to read is >= threshold.

Parameters:
  • callback - Functor called after each event processing iteration. Expects to receive the notifier object (self) as first parameter. If this function returns True the loop is immediately terminated otherwise the loop method keeps looping.
  • daemonize - This thread is daemonized if set to True.
  • args - Optional and relevant only if daemonize is True. Remaining keyworded arguments are directly passed to daemonize see __daemonize() method.
Overrides: Notifier.loop

run(self)

source code 

Start thread's loop: read and process events until the method stop() is called. Never call this method directly, instead call the start() method inherited from threading.Thread, which then will call run() in its turn.

Overrides: threading.Thread.run

pyinotify/python3/docstrings/pyinotify.PyinotifyLogger-class.html0000644000175000017500000003215211402071465025074 0ustar ookoiookoi pyinotify.PyinotifyLogger
Module pyinotify :: Class PyinotifyLogger
[hide private]
[frames] | no frames]

Class PyinotifyLogger

source code


Pyinotify logger used for logging unicode strings.

Instance Methods [hide private]
 
makeRecord(self, name, level, fn, lno, msg, args, exc_info, func=None, extra=None)
A factory method which can be overridden in subclasses to create specialized LogRecords.
source code

Inherited from logging.Logger: __init__, addHandler, callHandlers, critical, debug, error, exception, fatal, findCaller, getEffectiveLevel, handle, info, isEnabledFor, log, removeHandler, setLevel, warn, warning

Inherited from logging.Logger (private): _log

Inherited from logging.Filterer: addFilter, filter, removeFilter

Class Variables [hide private]

Inherited from logging.Logger: manager, root

Method Details [hide private]

makeRecord(self, name, level, fn, lno, msg, args, exc_info, func=None, extra=None)

source code 

A factory method which can be overridden in subclasses to create specialized LogRecords.

Overrides: logging.Logger.makeRecord
(inherited documentation)

pyinotify/python3/docstrings/pyinotify.SysCtlINotify-class.html0000644000175000017500000003030011402071465024456 0ustar ookoiookoi pyinotify.SysCtlINotify
Module pyinotify :: Class SysCtlINotify
[hide private]
[frames] | no frames]

Class SysCtlINotify

source code

Access (read, write) inotify's variables through sysctl. Usually it requires administrator rights to update them.

Examples:

  • Read max_queued_events attribute: myvar = max_queued_events.value
  • Update max_queued_events attribute: max_queued_events.value = 42
Instance Methods [hide private]
 
__init__(self, attrname) source code
int
get_val(self)
Gets attribute's value.
source code
 
set_val(self, nval)
Sets new attribute's value.
source code
 
__repr__(self) source code
Class Variables [hide private]
  inotify_attrs = {'max_user_instances': 1, 'max_user_watches': ...
  value = property(get_val, set_val)
Method Details [hide private]

get_val(self)

source code 

Gets attribute's value.

Returns: int
stored value.

set_val(self, nval)

source code 

Sets new attribute's value.

Parameters:
  • nval (int) - replaces current value by nval.

Class Variable Details [hide private]

inotify_attrs

Value:
{'max_user_instances': 1, 'max_user_watches': 2, 'max_queued_events': \
3}

pyinotify/python3/docstrings/pyinotify.WatchManagerError-class.html0000644000175000017500000002645011402071465025321 0ustar ookoiookoi pyinotify.WatchManagerError
Module pyinotify :: Class WatchManagerError
[hide private]
[frames] | no frames]

Class WatchManagerError

source code


WatchManager Exception. Raised on error encountered on watches operations.

Instance Methods [hide private]
 
__init__(self, msg, wmd)
x.__init__(...) initializes x; see x.__class__.__doc__ for signature
source code

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__, __unicode__

Inherited from object: __format__, __hash__, __reduce_ex__, __sizeof__, __subclasshook__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

Method Details [hide private]

__init__(self, msg, wmd)
(Constructor)

source code 

x.__init__(...) initializes x; see x.__class__.__doc__ for signature

Parameters:
  • msg (string) - Exception string's description.
  • wmd (dict) - This dictionary contains the wd assigned to paths of the same call for which watches were successfully added.
Overrides: object.__init__

pyinotify/python3/docstrings/epydoc.css0000644000175000017500000003722711402071464017724 0ustar ookoiookoi /* Epydoc CSS Stylesheet * * This stylesheet can be used to customize the appearance of epydoc's * HTML output. * */ /* Default Colors & Styles * - Set the default foreground & background color with 'body'; and * link colors with 'a:link' and 'a:visited'. * - Use bold for decision list terms. * - The heading styles defined here are used for headings *within* * docstring descriptions. All headings used by epydoc itself use * either class='epydoc' or class='toc' (CSS styles for both * defined below). */ body { background: #ffffff; color: #000000; } p { margin-top: 0.5em; margin-bottom: 0.5em; } a:link { color: #0000ff; } a:visited { color: #204080; } dt { font-weight: bold; } h1 { font-size: +140%; font-style: italic; font-weight: bold; } h2 { font-size: +125%; font-style: italic; font-weight: bold; } h3 { font-size: +110%; font-style: italic; font-weight: normal; } code { font-size: 100%; } /* N.B.: class, not pseudoclass */ a.link { font-family: monospace; } /* Page Header & Footer * - The standard page header consists of a navigation bar (with * pointers to standard pages such as 'home' and 'trees'); a * breadcrumbs list, which can be used to navigate to containing * classes or modules; options links, to show/hide private * variables and to show/hide frames; and a page title (using *

). The page title may be followed by a link to the * corresponding source code (using 'span.codelink'). * - The footer consists of a navigation bar, a timestamp, and a * pointer to epydoc's homepage. */ h1.epydoc { margin: 0; font-size: +140%; font-weight: bold; } h2.epydoc { font-size: +130%; font-weight: bold; } h3.epydoc { font-size: +115%; font-weight: bold; margin-top: 0.2em; } td h3.epydoc { font-size: +115%; font-weight: bold; margin-bottom: 0; } table.navbar { background: #a0c0ff; color: #000000; border: 2px groove #c0d0d0; } table.navbar table { color: #000000; } th.navbar-select { background: #70b0ff; color: #000000; } table.navbar a { text-decoration: none; } table.navbar a:link { color: #0000ff; } table.navbar a:visited { color: #204080; } span.breadcrumbs { font-size: 85%; font-weight: bold; } span.options { font-size: 70%; } span.codelink { font-size: 85%; } td.footer { font-size: 85%; } /* Table Headers * - Each summary table and details section begins with a 'header' * row. This row contains a section title (marked by * 'span.table-header') as well as a show/hide private link * (marked by 'span.options', defined above). * - Summary tables that contain user-defined groups mark those * groups using 'group header' rows. */ td.table-header { background: #70b0ff; color: #000000; border: 1px solid #608090; } td.table-header table { color: #000000; } td.table-header table a:link { color: #0000ff; } td.table-header table a:visited { color: #204080; } span.table-header { font-size: 120%; font-weight: bold; } th.group-header { background: #c0e0f8; color: #000000; text-align: left; font-style: italic; font-size: 115%; border: 1px solid #608090; } /* Summary Tables (functions, variables, etc) * - Each object is described by a single row of the table with * two cells. The left cell gives the object's type, and is * marked with 'code.summary-type'. The right cell gives the * object's name and a summary description. * - CSS styles for the table's header and group headers are * defined above, under 'Table Headers' */ table.summary { border-collapse: collapse; background: #e8f0f8; color: #000000; border: 1px solid #608090; margin-bottom: 0.5em; } td.summary { border: 1px solid #608090; } code.summary-type { font-size: 85%; } table.summary a:link { color: #0000ff; } table.summary a:visited { color: #204080; } /* Details Tables (functions, variables, etc) * - Each object is described in its own div. * - A single-row summary table w/ table-header is used as * a header for each details section (CSS style for table-header * is defined above, under 'Table Headers'). */ table.details { border-collapse: collapse; background: #e8f0f8; color: #000000; border: 1px solid #608090; margin: .2em 0 0 0; } table.details table { color: #000000; } table.details a:link { color: #0000ff; } table.details a:visited { color: #204080; } /* Fields */ dl.fields { margin-left: 2em; margin-top: 1em; margin-bottom: 1em; } dl.fields dd ul { margin-left: 0em; padding-left: 0em; } dl.fields dd ul li ul { margin-left: 2em; padding-left: 0em; } div.fields { margin-left: 2em; } div.fields p { margin-bottom: 0.5em; } /* Index tables (identifier index, term index, etc) * - link-index is used for indices containing lists of links * (namely, the identifier index & term index). * - index-where is used in link indices for the text indicating * the container/source for each link. * - metadata-index is used for indices containing metadata * extracted from fields (namely, the bug index & todo index). */ table.link-index { border-collapse: collapse; background: #e8f0f8; color: #000000; border: 1px solid #608090; } td.link-index { border-width: 0px; } table.link-index a:link { color: #0000ff; } table.link-index a:visited { color: #204080; } span.index-where { font-size: 70%; } table.metadata-index { border-collapse: collapse; background: #e8f0f8; color: #000000; border: 1px solid #608090; margin: .2em 0 0 0; } td.metadata-index { border-width: 1px; border-style: solid; } table.metadata-index a:link { color: #0000ff; } table.metadata-index a:visited { color: #204080; } /* Function signatures * - sig* is used for the signature in the details section. * - .summary-sig* is used for the signature in the summary * table, and when listing property accessor functions. * */ .sig-name { color: #006080; } .sig-arg { color: #008060; } .sig-default { color: #602000; } .summary-sig { font-family: monospace; } .summary-sig-name { color: #006080; font-weight: bold; } table.summary a.summary-sig-name:link { color: #006080; font-weight: bold; } table.summary a.summary-sig-name:visited { color: #006080; font-weight: bold; } .summary-sig-arg { color: #006040; } .summary-sig-default { color: #501800; } /* Subclass list */ ul.subclass-list { display: inline; } ul.subclass-list li { display: inline; } /* To render variables, classes etc. like functions */ table.summary .summary-name { color: #006080; font-weight: bold; font-family: monospace; } table.summary a.summary-name:link { color: #006080; font-weight: bold; font-family: monospace; } table.summary a.summary-name:visited { color: #006080; font-weight: bold; font-family: monospace; } /* Variable values * - In the 'variable details' sections, each varaible's value is * listed in a 'pre.variable' box. The width of this box is * restricted to 80 chars; if the value's repr is longer than * this it will be wrapped, using a backslash marked with * class 'variable-linewrap'. If the value's repr is longer * than 3 lines, the rest will be ellided; and an ellipsis * marker ('...' marked with 'variable-ellipsis') will be used. * - If the value is a string, its quote marks will be marked * with 'variable-quote'. * - If the variable is a regexp, it is syntax-highlighted using * the re* CSS classes. */ pre.variable { padding: .5em; margin: 0; background: #dce4ec; color: #000000; border: 1px solid #708890; } .variable-linewrap { color: #604000; font-weight: bold; } .variable-ellipsis { color: #604000; font-weight: bold; } .variable-quote { color: #604000; font-weight: bold; } .variable-group { color: #008000; font-weight: bold; } .variable-op { color: #604000; font-weight: bold; } .variable-string { color: #006030; } .variable-unknown { color: #a00000; font-weight: bold; } .re { color: #000000; } .re-char { color: #006030; } .re-op { color: #600000; } .re-group { color: #003060; } .re-ref { color: #404040; } /* Base tree * - Used by class pages to display the base class hierarchy. */ pre.base-tree { font-size: 80%; margin: 0; } /* Frames-based table of contents headers * - Consists of two frames: one for selecting modules; and * the other listing the contents of the selected module. * - h1.toc is used for each frame's heading * - h2.toc is used for subheadings within each frame. */ h1.toc { text-align: center; font-size: 105%; margin: 0; font-weight: bold; padding: 0; } h2.toc { font-size: 100%; font-weight: bold; margin: 0.5em 0 0 -0.3em; } /* Syntax Highlighting for Source Code * - doctest examples are displayed in a 'pre.py-doctest' block. * If the example is in a details table entry, then it will use * the colors specified by the 'table pre.py-doctest' line. * - Source code listings are displayed in a 'pre.py-src' block. * Each line is marked with 'span.py-line' (used to draw a line * down the left margin, separating the code from the line * numbers). Line numbers are displayed with 'span.py-lineno'. * The expand/collapse block toggle button is displayed with * 'a.py-toggle' (Note: the CSS style for 'a.py-toggle' should not * modify the font size of the text.) * - If a source code page is opened with an anchor, then the * corresponding code block will be highlighted. The code * block's header is highlighted with 'py-highlight-hdr'; and * the code block's body is highlighted with 'py-highlight'. * - The remaining py-* classes are used to perform syntax * highlighting (py-string for string literals, py-name for names, * etc.) */ pre.py-doctest { padding: .5em; margin: 1em; background: #e8f0f8; color: #000000; border: 1px solid #708890; } table pre.py-doctest { background: #dce4ec; color: #000000; } pre.py-src { border: 2px solid #000000; background: #f0f0f0; color: #000000; } .py-line { border-left: 2px solid #000000; margin-left: .2em; padding-left: .4em; } .py-lineno { font-style: italic; font-size: 90%; padding-left: .5em; } a.py-toggle { text-decoration: none; } div.py-highlight-hdr { border-top: 2px solid #000000; border-bottom: 2px solid #000000; background: #d8e8e8; } div.py-highlight { border-bottom: 2px solid #000000; background: #d0e0e0; } .py-prompt { color: #005050; font-weight: bold;} .py-more { color: #005050; font-weight: bold;} .py-string { color: #006030; } .py-comment { color: #003060; } .py-keyword { color: #600000; } .py-output { color: #404040; } .py-name { color: #000050; } .py-name:link { color: #000050 !important; } .py-name:visited { color: #000050 !important; } .py-number { color: #005000; } .py-defname { color: #000060; font-weight: bold; } .py-def-name { color: #000060; font-weight: bold; } .py-base-class { color: #000060; } .py-param { color: #000060; } .py-docstring { color: #006030; } .py-decorator { color: #804020; } /* Use this if you don't want links to names underlined: */ /*a.py-name { text-decoration: none; }*/ /* Graphs & Diagrams * - These CSS styles are used for graphs & diagrams generated using * Graphviz dot. 'img.graph-without-title' is used for bare * diagrams (to remove the border created by making the image * clickable). */ img.graph-without-title { border: none; } img.graph-with-title { border: 1px solid #000000; } span.graph-title { font-weight: bold; } span.graph-caption { } /* General-purpose classes * - 'p.indent-wrapped-lines' defines a paragraph whose first line * is not indented, but whose subsequent lines are. * - The 'nomargin-top' class is used to remove the top margin (e.g. * from lists). The 'nomargin' class is used to remove both the * top and bottom margin (but not the left or right margin -- * for lists, that would cause the bullets to disappear.) */ p.indent-wrapped-lines { padding: 0 0 0 7em; text-indent: -7em; margin: 0; } .nomargin-top { margin-top: 0; } .nomargin { margin-top: 0; margin-bottom: 0; } /* HTML Log */ div.log-block { padding: 0; margin: .5em 0 .5em 0; background: #e8f0f8; color: #000000; border: 1px solid #000000; } div.log-error { padding: .1em .3em .1em .3em; margin: 4px; background: #ffb0b0; color: #000000; border: 1px solid #000000; } div.log-warning { padding: .1em .3em .1em .3em; margin: 4px; background: #ffffb0; color: #000000; border: 1px solid #000000; } div.log-info { padding: .1em .3em .1em .3em; margin: 4px; background: #b0ffb0; color: #000000; border: 1px solid #000000; } h2.log-hdr { background: #70b0ff; color: #000000; margin: 0; padding: 0em 0.5em 0em 0.5em; border-bottom: 1px solid #000000; font-size: 110%; } p.log { font-weight: bold; margin: .5em 0 .5em 0; } tr.opt-changed { color: #000000; font-weight: bold; } tr.opt-default { color: #606060; } pre.log { margin: 0; padding: 0; padding-left: 1em; } pyinotify/python3/docstrings/index.html0000644000175000017500000000111711402071465017712 0ustar ookoiookoi API Documentation pyinotify/python3/docstrings/pyinotify.PrintAllEvents-class.html0000644000175000017500000003231511402071465024655 0ustar ookoiookoi pyinotify.PrintAllEvents
Module pyinotify :: Class PrintAllEvents
[hide private]
[frames] | no frames]

Class PrintAllEvents

source code


Dummy class used to print events strings representations. For instance this class is used from command line to print all received events to stdout.

Instance Methods [hide private]
 
my_init(self, out=None)
This method is called from ProcessEvent.__init__().
source code
 
process_default(self, event)
Writes event string representation to file object provided to my_init().
source code

Inherited from ProcessEvent: __call__, __init__, nested_pevent, process_IN_Q_OVERFLOW

Inherited from _ProcessEvent: __repr__

Class Variables [hide private]

Inherited from ProcessEvent: pevent

Method Details [hide private]

my_init(self, out=None)

source code 

This method is called from ProcessEvent.__init__(). This method is empty here and must be redefined to be useful. In effect, if you need to specifically initialize your subclass' instance then you just have to override this method in your subclass. Then all the keyworded arguments passed to ProcessEvent.__init__() will be transmitted as parameters to this method. Beware you MUST pass keyword arguments though.

Parameters:
  • out (Object providing a valid file object interface.) - Where events will be written.
Overrides: ProcessEvent.my_init

process_default(self, event)

source code 

Writes event string representation to file object provided to my_init().

Parameters:
  • event (Event instance) - Event to be processed. Can be of any type of events but IN_Q_OVERFLOW events (see method process_IN_Q_OVERFLOW).
Overrides: ProcessEvent.process_default

pyinotify/python3/docstrings/uml_class_diagram_for_pyinotif_11.gif0000644000175000017500000004155411402071465025153 0ustar ookoiookoiGIF87aS|LBDĤBDĂTd^\Ģ$"$jdd*,|bdĺdJD<2,vt |rlܪ&$̒|^T|TJD̪dVTD:4vl4&$ܲ24|fdĬRT$Ěܺ,Ԧrt \F<쾼rdt^T̢,"|vl|bdԪlVL䲤̬Z\,亼Ԣ t̚L>4jlTF< ld24dND|vt䮜"$|bTzl4*$$Ğz|  rt|ܜ:<<.,|jl̼j\D6,\NL,&$lĤFDĆ|fdܮ̖ܶ64VTĞܾrd̤NLĎnl.,^\侼Ԧ̞&$~|ܜ>< ̦Ԯ<24TJLD:<$Ԧ \FD̞tZ\L:<~|TBD\JLrlt^\,"$vtlVTL>}xFulvM8{tHmUd256%e܈>Ҡ coPn=7a!pq(mxFEh!n^FL_th$n5\ (m{\qA ~ܶ01"nqH4\͊%]U  Lm?5? *WpZ"9]b$n5X#MEr)ã+gWmX8еH]hJ)ntqv]a*+pIRdȮ5wg;`"n|va-wW9 ՎXy"8=KƛײzWyyBI87m\ݫ] VvH̰\,n*5pۺ.y;$w 8-Qf2*3x蠅v%*Svspag(5;އqmW4SEJ54;78ʠp1^g @X%L9w_1Ո6EōGzR'nXKθ\@9NJ^n:X5Xn8ƞnVˮر/To' S!Wogw@ϗTznFߒ _H 6:17 ł E'dD“D|0 gHo-!H4>ǃy("^H&Hbtw?'Z#PbX&^Y r8E} #/`2hcB:w C yIBL" !$'yH% q\ы eH ZV(Wɑ E*YI˚X!E D1Z%X,z;‰2B 02IMD.1jz#B8; :KP @:癑SaI~RD0`"ӟZІ}0(B'S쒡 C RQ3{ Ғ&D4JR-Kazt*)?qӚ=N RzEK:QLESuը~q9Uju` JֲhMZֶUnp\J׺,_+W> `KMb&0x+l:?ۼMrJ"b98mlf(y@M"TЁv,y-VHz%]k5ZVT-F2R2-D*q?46Χ n\ iC(zW*.D%+aQJD&(MMc (5 zb0uaLeڭ *_tF%kSVpAj[ζn{mȎs6v^[n${V]zxY]^O8}}~&WM?-p\-߸u81QwW.8Ӣ8Ϲcn%#yɥrrAУRtIҡt -ęz_> :n*}8bwJnPs.A&M;E&Bz3q]$+~/ lOyt.*Q}͂3lh7W=›8V $ w5կuM{wqll*]jqkO)շF1G.e\_r}s~4}4s7A4Mfvw1f#`L7"hk8[79r8yP-xF1XvgÀ2-肅&dC1 G G0 GȃEJ(AxdD[]RC!cehHBkm>?!suh>{fYa]uj^~x8kCv m FNZ,xww(!\^7$] Cyi4B2y \z6_g(WΦG!\,a%5|.}voh5z[Sd6ꢏG~3ǨvYSeb621[q9(\8""hv#2D_LgH wp?vU6y8:<ٓc2!\&x\iQ#X(8*+:1uXZ\ٕ^\Dx689(0I9F` a]уo}xavbȖQYqa}(Th}yjt\0y~y/чY1q>qA}0|j7?2~ rW)g 97F䆹aGC(ƒ8~x7?ifrraB}V7#+ }5I51˩\  y}if6"Z*)(0XGxAs!ꃈpY&q!"=""S4ȡ뗠"v;G ;TP@.[0Jt2 >fw8:CəL7UW7>f!]Ë8ye)$Re  UyҦudY3#u7 8 Z3zfdNCIs_z{w"6{L W;Y*5h⪲''jW+R3鸎|,yZ#b*᝹*jI1/:21Ӧsz蚮 };f:})~z/m}yc(.xZ~'1A꺰 ۰nꮹUg+0i۬B1֙]Пɭ  걷q! (ڬ)I={ fz:Hs+ɗP02}4kk:8Z]]0Ny )ٚc"$~Q6ʦ[ JoJU˘Ške8xRg2}W A -Q;AvK% 8YFTgk;i:[{1뗨;v>A;[x ;l+wغ\л:x[='ڋ|ɽuG)@K48$>բk%?o{@;vCE:+# ;,׫{?Zb+A%l \'f5PÏZ)\sݥ÷Ryi"2.r:7ˆ>@B &,ojĶ8Ùɧ~ SyILT<*㒢;,}].ԗh`gzǧG%=`xȋy)ڌj3ZqȑȒ\_ͲyŽy]%ǩ_ȣy̪ɞl/b1|.P|G|ڎƧb!9 Hج+ ) ʬӼ|<, iזݜB}1}D͐A&UW-o.Lx"h>]< 4i xKv!t~f"c5V~z=8O*le|#Hu"iс+@څS/JI_۔͵ڬ]YxŻ؛i`^ =Sm#+u,/C+23Ss)|?k㻢ֽ>K>}>>kl`:;;j ;kN*ނޫ ~3  (a n");&⚗dH&$ su2 \@=8^:[쿜C.kݗvVnM.O~[ݡT~-|Qw]`@}a>٫xlʨ.l :eKl1j~+J]sKVD\tܗu}'7 z}rm6ʠɁ\3Ck2ɨɋJ ރw\#acĥJa\\3 4ka*LbYxzd`d! *,-Ά}~6t4~g+Ξl[:m0[͝~Z1־..:l%é2 ͐E{{֮C pdxM+?- h|SS ^sڶ[ܴ=8 , zڠƣ5LyP5߮}0O$`axH4qW xz/=93Sx |χ6~߱91T/q^?1~xa/p Ho_1Ȯl(?<e^B۟IlISQZ8^/IaE@DPB \C!RX0ƅ9 !LDRJ-O~ Xp<(qE"?5.ET)K>e١A!4"p%P J xլgӮ]V-[+PawoA[>!lj6@x'~*V\Kle]O>.i̊3|nwK0$T,aVxJ](m<ڹA]p Ş]AR B.?ʡC+j1 *L nR/.S=O{Mr[0A- Ь"p=܃O.?B3ql#j`"`'2\\P.A8PCoЬ 3̏#L3OL"H *--8)H#Т7 ʳ=*I邇ԓJ ?. TD%4!7ᔓN4>촋Q !)Mճ\h752,N ''E}VMWXi\ŤZ5;6/|JT ݁DtM<@C*JW! FJX݂4_w󅖡)=xewҝ5p}L.qs^i.8тMV7sckgێo>[2(.J¹2>(g8^h郎`B~7.e{냼K-Ͳ}Vg ά) { rgt$h" W k>hl;ʳ9s1ms4=y~9j&!Tja,lObv-o wCw}g\!MG=Uluzu|YN -.ơ"p_"| bq7gPxwog:s`yD `uيZwfw pboA*xΈ h2@0aB`BVAH`.Qd"s>a "9c!aPg{DhhCCA;qJ#1R%=d"3a %A$AP c dP&IN2DV!AyDvҔ`PsD&SWDRb#$`Kb:HI K (,)q2rf6MeZg'IMX g: nF넧INӐg>vvI% hB*/]s@ {(@ fԣ*Du)^\' FANT$UJE#ЎmhHG  )Ԏ}?Rϝ;h[N3S(y)LBRa2Bw*/* @PkY^!YժQdN>5G>P?.ۈb1r'! lK;ͅ3F"ˋm2(c82miۉ e(&ʶ]Qƪy/ LtsB\g;LSe,e)m\W.ΥNfم6+-zV"@DZ'7 t X_H \%A6b38 Br.yu < B!IHߥJ 'E!$.`)FZDi^ZAPZrAjDUr5)YUԗ.'39_Sic+m5@6 M*ͼ!qYˠʹ#7\, ͸҅2|,9 UZ0֚װ Ж.mV8& y̞֏0dqfNWz+u͢Eľ\'HrԮ*bA\qfCP&= ܟG|:64;[k۳;79s+hHvvnr\ RhoӾF쾈g %B?!oP<#iCqo}Q^0v_-O ^9n.ׅ; _ ;3%b1|aYH3!Xa x1xSꍨm 3x"o@jF ^ݎ#-40!`8.#Ng7\3B3foR| о2Ќdg$?S?btf9|;TVN?B|w!Gz| ciFc~s_V~h- _[Ce_Ť?ls?3@E @])jRڬపęwR@@"vR$Tzs<< `Op8 .<˄S6 =^GJ%EЉJB[==}Aw uN .S >dўASіb>eQt?C-҈zNN"=)!I"eQM(=@9R MX-('K(ӌJRo3m>2Q3uӿ]9 (8R9"R*6=) L, ]dr $D-AEu:;<զDĬ+SG6|4%(M N&& BFtCU?ň+ '(Y'Z} IgȃCT֢Gl9T`KݪV)qi-;<+U5n? L,DN.O#F-p.׌2VrBЩ5MX)cޜ 0^H01m hEC `Ձ@lEndFK0irWL~] I l7WKzDJ0H|L+3/CKW-9lys-8m }&U Iʖ|5x٭_5Hmɚ\֏JZ3dK5[hQJ[J\ۤp\6,~K|<9ܸṱˍշU 1] ŨE I 0MK#dd\YX -:H2NLUc^<)%= 1|sh碻+:OL;<"OOO(P5>y1_]"4]-I5 l6  ^&  U FG v n?%-PF\6E \Xaຂ@ůӦcap$J.B Bub"[h*5$)^ [-9x+,bAC3VC@"0c7,(5N>?@A&B6Cv;0DfFF5׺=4 =F؂LMNOPQ&R6SF-;pBHWQVc)5b[YEX>"`HTr ?&d`6\fS%[f5^UUV)5¬Sgfi` A_ufbc]J$auUd]5=<8 2Ѕ`^14FLgZlݪm2Z΂QxCdkۡV\|툠ۆlmd˦H;pnX:8|K]74 ]]LLPݵώt]\]hvc`> Y ;+k pqp 6X]M5w,NEŹཽ؞.oC;0A7o(Ͽ낷+f; 6D G"XOvT`tӺ`nl EE`% G:.& ' &p1p[;%7 /&=rIr)Y(;XAr*'&!>)"ir/ߙW@s; 4d-Ήs9bXTPr5eFq@?pAX;(qC?tƆsEq!X =>?t!X嵖pI7OPp ;8>:&fjJ}Em)O VpaXV8n~ug_}U"uu`2XU>Y燀d }gbgh Umn>d c.0i7LzDz .QD/쮅Uuh( X81YY}j ֽ/oXU6k9T!42ZEJxfUml화5Z쾝J,ʷ-m[wBvU ` $7vAn_[U/xp_~o&^:'3{;q')e@qp if]#_ WVXea |nѣZn!w+8;SIJ0ڃፐwl_X<쏹\Q^>ז];t'vP~>WuFI]?a]OW72_XW`?tWX_2,h „ 2l]&Rh"ƌ7r#Ȑ"=^$ʔ*.X%̘2gҬi;w `đB-jВ?l)ԨRrN0AT> *2E*JD:ea֣oG*jwӻzkN~z Y&,-aRɠv",6RȲe1oԀ6I}v7S|)jB( .'VJY eʈ,ѧwirK^}E>p{x0^y1znivLA8!zڄr As* 0vfW\P1a["hDٌ XԡqXV/H݌5ޘc#984у$ay,t40&f(6Mőe`"] qv1DϰǦ JhǞ{B矁IsOnQi6 :-!Ш'6E#u H:-IS(]jQ݁^@7Ld(GvQCYW4S8+6YO8IMDhcueltE;4O :rw@FYmU8^~8Y00\% ]cyNN-MrD!1Is XY4;> Gq!}R5&CYUw` #( R 3 np, a\SRB8A'*|! c(Ұ6!s !r p"1 2q)l"i B>D3y8a,'B҆ : X0ʱd(ȅqL,NB1C/*CR dU0# I:aP03 s0C,&>q#, 8ûH1mjԸ>1,!C$\%3N~{cOY1 pae`6,1>C;a3n~s,*g8Ǝ0b8~3?5І>􉥌2x@6rfmp# \̀m0GIWҒqў9.}WzԔ!]4~paRfD&t\5Al 3(=pΆsmn81s j|HgG{٦.6=@3D7LcS89 ŸxB/xx@YF9r6xS^9c>b9;Ų: wW s\M :N;t9ԣb` :Ʉ:֣NsSX`8Qc8\ 9ŋ~a\#טiz\!;Uwޗ3цnSj$^\xh>Q ɳp4Ĺ.y;wYӳ؃cP P^i$/=(fO~9﹆58/SѩG߫s5?ʯ1?ݬ~d??OzM.  &. 6> FN V^ fn v~ _C Ơ  2 Y!nE.!B5N!Fafna]ar!> !!ʠ `!!*V]!bQ]}!"6#a#N"%a$6Dq܍0L&؎X'ZnUX)Y*Xm+Xt37"&"홆b."bXޑ3C)˱#݉Y&n*v]caY3Y8~ُ$ 0m58m;£2fnJm2lXZl knu-}-:]kwɭ\թQcDln3\d5T/&@9*-2A>vrݟ~]6.jjzݝĵAf.>)].e./\n Kl&C:m /n.l1%fZzЊv]/7*30 NfCQC"3)^@}0| $@ &(A&DovipppUyY&Hѯa'uB}-p Cq^e0 7ばVC$cd (& 1M[mpobO#TI2f^p gBop[,+.^2߾z$h!@6@PFg%HXy4B6eIr'Z2$_%U*}pB]U l+g\r&뮎r+c!2,O+[d3/"l.$.$!Xe]ɂB#=dItY%C#4:*y|X`]C&0HEJyrN .Q0tmAP횊 mV]*BJ,R,T_5V%VuVwWV+U5YuzY5[75AG\ϵޡuB)}"0'45`5B6j A c?v"]ujC.$do6gd gRA&%bRXQh/: wl 6aD&}g*(VnHB)6rumD&ƫ&oV:+>&7wrD&j,f]flَrv{cwz*nNot#.#.}w {8|5!2p{{@ۯ+17g$@d9%.3 ![3i@k#"aߣ!4i!W셁ٴ8eI57G9CW9wSgygcwcsrxWsRc_ߣ_9Xbߣ1v9]6f빠sgx^bj2qkZl*ovnpi~)a:ytSXu;+C: m=Z-ԑztcoZXw[:#󰃳*SoW_M7;x?3j r|ox{9fxB˻㏇4 <;[<#7ğOC_<ǟ^w<ȏzcaȗ}ɧm^׼{XW7wX>~y <׾ާu%<-߽XvO?F6aT_?go?w?????ǿ?8???@8`A&TaC!F8bE1flWG?.9dI'QTeK/aƔ9fM7qԹgO?M:hQG&UiSOS :jUWfպUT_;lY5Um[oLn]w:Wo_WpaÇ'.JXqcǏ!GXre˗1];pyinotify/python3/docstrings/pyinotify-pysrc.html0000644000175000017500000205045211402071465022003 0ustar ookoiookoi pyinotify
Module pyinotify
[hide private]
[frames] | no frames]

Source Code for Module pyinotify

   1  #!/usr/bin/env python 
   2   
   3  # pyinotify.py - python interface to inotify 
   4  # Copyright (c) 2010 Sebastien Martini <seb@dbzteam.org> 
   5  # 
   6  # Permission is hereby granted, free of charge, to any person obtaining a copy 
   7  # of this software and associated documentation files (the "Software"), to deal 
   8  # in the Software without restriction, including without limitation the rights 
   9  # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
  10  # copies of the Software, and to permit persons to whom the Software is 
  11  # furnished to do so, subject to the following conditions: 
  12  # 
  13  # The above copyright notice and this permission notice shall be included in 
  14  # all copies or substantial portions of the Software. 
  15  # 
  16  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
  17  # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
  18  # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
  19  # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
  20  # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
  21  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
  22  # THE SOFTWARE. 
  23  """ 
  24  pyinotify 
  25   
  26  @author: Sebastien Martini 
  27  @license: MIT License 
  28  @contact: seb@dbzteam.org 
  29  """ 
30 31 -class PyinotifyError(Exception):
32 """Indicates exceptions raised by a Pyinotify class.""" 33 pass
34
35 36 -class UnsupportedPythonVersionError(PyinotifyError):
37 """ 38 Raised on unsupported Python versions. 39 """
40 - def __init__(self, version):
41 """ 42 @param version: Current Python version 43 @type version: string 44 """ 45 PyinotifyError.__init__(self, 46 ('Python %s is unsupported, requires ' 47 'at least Python 3.0') % version)
48
49 50 -class UnsupportedLibcVersionError(PyinotifyError):
51 """ 52 Raised on unsupported libc versions. 53 """
54 - def __init__(self, version):
55 """ 56 @param version: Current Libc version 57 @type version: string 58 """ 59 PyinotifyError.__init__(self, 60 ('Libc %s is not supported, requires ' 61 'at least Libc 2.4') % version)
62 63 64 # Check Python version 65 import sys 66 if sys.version < '3.0': 67 raise UnsupportedPythonVersionError(sys.version) 68 69 70 # Import directives 71 import threading 72 import os 73 import select 74 import struct 75 import fcntl 76 import errno 77 import termios 78 import array 79 import logging 80 import atexit 81 from collections import deque 82 from datetime import datetime, timedelta 83 import time 84 import fnmatch 85 import re 86 import ctypes 87 import ctypes.util 88 import asyncore 89 import glob 90 91 try: 92 from functools import reduce 93 except ImportError: 94 pass # Will fail on Python 2.4 which has reduce() builtin anyway. 95 96 __author__ = "seb@dbzteam.org (Sebastien Martini)" 97 98 __version__ = "0.9.0" 99 100 101 # Compatibity mode: set to True to improve compatibility with 102 # Pyinotify 0.7.1. Do not set this variable yourself, call the 103 # function compatibility_mode() instead. 104 COMPATIBILITY_MODE = False 105 106 107 # Load libc 108 LIBC = ctypes.CDLL(ctypes.util.find_library('c'), use_errno=True)
109 110 -def STRERRNO():
111 code = ctypes.get_errno() 112 return '%s (%s)' % (os.strerror(code), errno.errorcode[code])
113 114 # The libc version > 2.4 check. 115 # XXX: Maybe it is better to check if the libc has the needed functions inside? 116 # Because there are inotify patches for libc 2.3.6. 117 LIBC.gnu_get_libc_version.restype = ctypes.c_char_p 118 LIBC_VERSION = LIBC.gnu_get_libc_version() 119 if not isinstance(LIBC_VERSION, str): 120 LIBC_VERSION = LIBC_VERSION.decode() 121 if (int(LIBC_VERSION.split('.')[0]) < 2 or 122 (int(LIBC_VERSION.split('.')[0]) == 2 and 123 int(LIBC_VERSION.split('.')[1]) < 4)): 124 raise UnsupportedLibcVersionError(LIBC_VERSION)
125 126 127 -class PyinotifyLogger(logging.Logger):
128 """ 129 Pyinotify logger used for logging unicode strings. 130 """
131 - def makeRecord(self, name, level, fn, lno, msg, args, exc_info, func=None, 132 extra=None):
133 rv = UnicodeLogRecord(name, level, fn, lno, msg, args, exc_info, func) 134 if extra is not None: 135 for key in extra: 136 if (key in ["message", "asctime"]) or (key in rv.__dict__): 137 raise KeyError("Attempt to overwrite %r in LogRecord" % key) 138 rv.__dict__[key] = extra[key] 139 return rv
140
141 142 # Logging 143 -def logger_init():
144 """Initialize logger instance.""" 145 log = logging.getLogger("pyinotify") 146 console_handler = logging.StreamHandler() 147 console_handler.setFormatter( 148 logging.Formatter("[Pyinotify %(levelname)s] %(message)s")) 149 log.addHandler(console_handler) 150 log.setLevel(20) 151 return log
152 153 log = logger_init()
154 155 156 # inotify's variables 157 -class SysCtlINotify:
158 """ 159 Access (read, write) inotify's variables through sysctl. Usually it 160 requires administrator rights to update them. 161 162 Examples: 163 - Read max_queued_events attribute: myvar = max_queued_events.value 164 - Update max_queued_events attribute: max_queued_events.value = 42 165 """ 166 167 inotify_attrs = {'max_user_instances': 1, 168 'max_user_watches': 2, 169 'max_queued_events': 3} 170
171 - def __init__(self, attrname):
172 sino = ctypes.c_int * 3 173 self._attrname = attrname 174 self._attr = sino(5, 20, SysCtlINotify.inotify_attrs[attrname])
175
176 - def get_val(self):
177 """ 178 Gets attribute's value. 179 180 @return: stored value. 181 @rtype: int 182 """ 183 oldv = ctypes.c_int(0) 184 size = ctypes.c_int(ctypes.sizeof(oldv)) 185 LIBC.sysctl(self._attr, 3, 186 ctypes.c_voidp(ctypes.addressof(oldv)), 187 ctypes.addressof(size), 188 None, 0) 189 return oldv.value
190
191 - def set_val(self, nval):
192 """ 193 Sets new attribute's value. 194 195 @param nval: replaces current value by nval. 196 @type nval: int 197 """ 198 oldv = ctypes.c_int(0) 199 sizeo = ctypes.c_int(ctypes.sizeof(oldv)) 200 newv = ctypes.c_int(nval) 201 sizen = ctypes.c_int(ctypes.sizeof(newv)) 202 LIBC.sysctl(self._attr, 3, 203 ctypes.c_voidp(ctypes.addressof(oldv)), 204 ctypes.addressof(sizeo), 205 ctypes.c_voidp(ctypes.addressof(newv)), 206 ctypes.addressof(sizen))
207 208 value = property(get_val, set_val) 209
210 - def __repr__(self):
211 return '<%s=%d>' % (self._attrname, self.get_val())
212 213 214 # Singleton instances 215 # 216 # read: myvar = max_queued_events.value 217 # update: max_queued_events.value = 42 218 # 219 for attrname in ('max_queued_events', 'max_user_instances', 'max_user_watches'): 220 globals()[attrname] = SysCtlINotify(attrname)
221 222 223 -class EventsCodes:
224 """ 225 Set of codes corresponding to each kind of events. 226 Some of these flags are used to communicate with inotify, whereas 227 the others are sent to userspace by inotify notifying some events. 228 229 @cvar IN_ACCESS: File was accessed. 230 @type IN_ACCESS: int 231 @cvar IN_MODIFY: File was modified. 232 @type IN_MODIFY: int 233 @cvar IN_ATTRIB: Metadata changed. 234 @type IN_ATTRIB: int 235 @cvar IN_CLOSE_WRITE: Writtable file was closed. 236 @type IN_CLOSE_WRITE: int 237 @cvar IN_CLOSE_NOWRITE: Unwrittable file closed. 238 @type IN_CLOSE_NOWRITE: int 239 @cvar IN_OPEN: File was opened. 240 @type IN_OPEN: int 241 @cvar IN_MOVED_FROM: File was moved from X. 242 @type IN_MOVED_FROM: int 243 @cvar IN_MOVED_TO: File was moved to Y. 244 @type IN_MOVED_TO: int 245 @cvar IN_CREATE: Subfile was created. 246 @type IN_CREATE: int 247 @cvar IN_DELETE: Subfile was deleted. 248 @type IN_DELETE: int 249 @cvar IN_DELETE_SELF: Self (watched item itself) was deleted. 250 @type IN_DELETE_SELF: int 251 @cvar IN_MOVE_SELF: Self (watched item itself) was moved. 252 @type IN_MOVE_SELF: int 253 @cvar IN_UNMOUNT: Backing fs was unmounted. 254 @type IN_UNMOUNT: int 255 @cvar IN_Q_OVERFLOW: Event queued overflowed. 256 @type IN_Q_OVERFLOW: int 257 @cvar IN_IGNORED: File was ignored. 258 @type IN_IGNORED: int 259 @cvar IN_ONLYDIR: only watch the path if it is a directory (new 260 in kernel 2.6.15). 261 @type IN_ONLYDIR: int 262 @cvar IN_DONT_FOLLOW: don't follow a symlink (new in kernel 2.6.15). 263 IN_ONLYDIR we can make sure that we don't watch 264 the target of symlinks. 265 @type IN_DONT_FOLLOW: int 266 @cvar IN_MASK_ADD: add to the mask of an already existing watch (new 267 in kernel 2.6.14). 268 @type IN_MASK_ADD: int 269 @cvar IN_ISDIR: Event occurred against dir. 270 @type IN_ISDIR: int 271 @cvar IN_ONESHOT: Only send event once. 272 @type IN_ONESHOT: int 273 @cvar ALL_EVENTS: Alias for considering all of the events. 274 @type ALL_EVENTS: int 275 """ 276 277 # The idea here is 'configuration-as-code' - this way, we get our nice class 278 # constants, but we also get nice human-friendly text mappings to do lookups 279 # against as well, for free: 280 FLAG_COLLECTIONS = {'OP_FLAGS': { 281 'IN_ACCESS' : 0x00000001, # File was accessed 282 'IN_MODIFY' : 0x00000002, # File was modified 283 'IN_ATTRIB' : 0x00000004, # Metadata changed 284 'IN_CLOSE_WRITE' : 0x00000008, # Writable file was closed 285 'IN_CLOSE_NOWRITE' : 0x00000010, # Unwritable file closed 286 'IN_OPEN' : 0x00000020, # File was opened 287 'IN_MOVED_FROM' : 0x00000040, # File was moved from X 288 'IN_MOVED_TO' : 0x00000080, # File was moved to Y 289 'IN_CREATE' : 0x00000100, # Subfile was created 290 'IN_DELETE' : 0x00000200, # Subfile was deleted 291 'IN_DELETE_SELF' : 0x00000400, # Self (watched item itself) 292 # was deleted 293 'IN_MOVE_SELF' : 0x00000800, # Self (watched item itself) was moved 294 }, 295 'EVENT_FLAGS': { 296 'IN_UNMOUNT' : 0x00002000, # Backing fs was unmounted 297 'IN_Q_OVERFLOW' : 0x00004000, # Event queued overflowed 298 'IN_IGNORED' : 0x00008000, # File was ignored 299 }, 300 'SPECIAL_FLAGS': { 301 'IN_ONLYDIR' : 0x01000000, # only watch the path if it is a 302 # directory 303 'IN_DONT_FOLLOW' : 0x02000000, # don't follow a symlink 304 'IN_MASK_ADD' : 0x20000000, # add to the mask of an already 305 # existing watch 306 'IN_ISDIR' : 0x40000000, # event occurred against dir 307 'IN_ONESHOT' : 0x80000000, # only send event once 308 }, 309 } 310
311 - def maskname(mask):
312 """ 313 Returns the event name associated to mask. IN_ISDIR is appended to 314 the result when appropriate. Note: only one event is returned, because 315 only one event can be raised at a given time. 316 317 @param mask: mask. 318 @type mask: int 319 @return: event name. 320 @rtype: str 321 """ 322 ms = mask 323 name = '%s' 324 if mask & IN_ISDIR: 325 ms = mask - IN_ISDIR 326 name = '%s|IN_ISDIR' 327 return name % EventsCodes.ALL_VALUES[ms]
328 329 maskname = staticmethod(maskname)
330 331 332 # So let's now turn the configuration into code 333 EventsCodes.ALL_FLAGS = {} 334 EventsCodes.ALL_VALUES = {} 335 for flagc, valc in EventsCodes.FLAG_COLLECTIONS.items(): 336 # Make the collections' members directly accessible through the 337 # class dictionary 338 setattr(EventsCodes, flagc, valc) 339 340 # Collect all the flags under a common umbrella 341 EventsCodes.ALL_FLAGS.update(valc) 342 343 # Make the individual masks accessible as 'constants' at globals() scope 344 # and masknames accessible by values. 345 for name, val in valc.items(): 346 globals()[name] = val 347 EventsCodes.ALL_VALUES[val] = name 348 349 350 # all 'normal' events 351 ALL_EVENTS = reduce(lambda x, y: x | y, EventsCodes.OP_FLAGS.values()) 352 EventsCodes.ALL_FLAGS['ALL_EVENTS'] = ALL_EVENTS 353 EventsCodes.ALL_VALUES[ALL_EVENTS] = 'ALL_EVENTS'
354 355 356 -class _Event:
357 """ 358 Event structure, represent events raised by the system. This 359 is the base class and should be subclassed. 360 361 """
362 - def __init__(self, dict_):
363 """ 364 Attach attributes (contained in dict_) to self. 365 366 @param dict_: Set of attributes. 367 @type dict_: dictionary 368 """ 369 for tpl in dict_.items(): 370 setattr(self, *tpl)
371
372 - def __repr__(self):
373 """ 374 @return: Generic event string representation. 375 @rtype: str 376 """ 377 s = '' 378 for attr, value in sorted(self.__dict__.items(), key=lambda x: x[0]): 379 if attr.startswith('_'): 380 continue 381 if attr == 'mask': 382 value = hex(getattr(self, attr)) 383 elif isinstance(value, str) and not value: 384 value = "''" 385 s += ' %s%s%s' % (Color.field_name(attr), 386 Color.punctuation('='), 387 Color.field_value(value)) 388 389 s = '%s%s%s %s' % (Color.punctuation('<'), 390 Color.class_name(self.__class__.__name__), 391 s, 392 Color.punctuation('>')) 393 return s
394
395 396 -class _RawEvent(_Event):
397 """ 398 Raw event, it contains only the informations provided by the system. 399 It doesn't infer anything. 400 """
401 - def __init__(self, wd, mask, cookie, name):
402 """ 403 @param wd: Watch Descriptor. 404 @type wd: int 405 @param mask: Bitmask of events. 406 @type mask: int 407 @param cookie: Cookie. 408 @type cookie: int 409 @param name: Basename of the file or directory against which the 410 event was raised in case where the watched directory 411 is the parent directory. None if the event was raised 412 on the watched item itself. 413 @type name: string or None 414 """ 415 # name: remove trailing '\0' 416 _Event.__init__(self, {'wd': wd, 417 'mask': mask, 418 'cookie': cookie, 419 'name': name.rstrip('\0')}) 420 log.debug(repr(self)) 421 # Use this variable to cache the result of str(self) 422 self._str = None
423
424 - def __str__(self):
425 if self._str is None: 426 self._str = '%s %s %s %s' % (str(self.wd), str(self.mask), 427 str(self.cookie), self.name) 428 return self._str
429
430 431 -class Event(_Event):
432 """ 433 This class contains all the useful informations about the observed 434 event. However, the presence of each field is not guaranteed and 435 depends on the type of event. In effect, some fields are irrelevant 436 for some kind of event (for example 'cookie' is meaningless for 437 IN_CREATE whereas it is mandatory for IN_MOVE_TO). 438 439 The possible fields are: 440 - wd (int): Watch Descriptor. 441 - mask (int): Mask. 442 - maskname (str): Readable event name. 443 - path (str): path of the file or directory being watched. 444 - name (str): Basename of the file or directory against which the 445 event was raised in case where the watched directory 446 is the parent directory. None if the event was raised 447 on the watched item itself. This field is always provided 448 even if the string is ''. 449 - pathname (str): Concatenation of 'path' and 'name'. 450 - src_pathname (str): Only present for IN_MOVED_TO events and only in 451 the case where IN_MOVED_FROM events are watched too. Holds the 452 source pathname from where pathname was moved from. 453 - cookie (int): Cookie. 454 - dir (bool): True if the event was raised against a directory. 455 456 """
457 - def __init__(self, raw):
458 """ 459 Concretely, this is the raw event plus inferred infos. 460 """ 461 _Event.__init__(self, raw) 462 self.maskname = EventsCodes.maskname(self.mask) 463 if COMPATIBILITY_MODE: 464 self.event_name = self.maskname 465 try: 466 if self.name: 467 self.pathname = os.path.abspath(os.path.join(self.path, 468 self.name)) 469 else: 470 self.pathname = os.path.abspath(self.path) 471 except AttributeError as err: 472 # Usually it is not an error some events are perfectly valids 473 # despite the lack of these attributes. 474 log.debug(err)
475
476 477 -class ProcessEventError(PyinotifyError):
478 """ 479 ProcessEventError Exception. Raised on ProcessEvent error. 480 """
481 - def __init__(self, err):
482 """ 483 @param err: Exception error description. 484 @type err: string 485 """ 486 PyinotifyError.__init__(self, err)
487
488 489 -class _ProcessEvent:
490 """ 491 Abstract processing event class. 492 """
493 - def __call__(self, event):
494 """ 495 To behave like a functor the object must be callable. 496 This method is a dispatch method. Its lookup order is: 497 1. process_MASKNAME method 498 2. process_FAMILY_NAME method 499 3. otherwise calls process_default 500 501 @param event: Event to be processed. 502 @type event: Event object 503 @return: By convention when used from the ProcessEvent class: 504 - Returning False or None (default value) means keep on 505 executing next chained functors (see chain.py example). 506 - Returning True instead means do not execute next 507 processing functions. 508 @rtype: bool 509 @raise ProcessEventError: Event object undispatchable, 510 unknown event. 511 """ 512 stripped_mask = event.mask - (event.mask & IN_ISDIR) 513 maskname = EventsCodes.ALL_VALUES.get(stripped_mask) 514 if maskname is None: 515 raise ProcessEventError("Unknown mask 0x%08x" % stripped_mask) 516 517 # 1- look for process_MASKNAME 518 meth = getattr(self, 'process_' + maskname, None) 519 if meth is not None: 520 return meth(event) 521 # 2- look for process_FAMILY_NAME 522 meth = getattr(self, 'process_IN_' + maskname.split('_')[1], None) 523 if meth is not None: 524 return meth(event) 525 # 3- default call method process_default 526 return self.process_default(event)
527
528 - def __repr__(self):
529 return '<%s>' % self.__class__.__name__
530
531 532 -class _SysProcessEvent(_ProcessEvent):
533 """ 534 There is three kind of processing according to each event: 535 536 1. special handling (deletion from internal container, bug, ...). 537 2. default treatment: which is applied to the majority of events. 538 3. IN_ISDIR is never sent alone, he is piggybacked with a standard 539 event, he is not processed as the others events, instead, its 540 value is captured and appropriately aggregated to dst event. 541 """
542 - def __init__(self, wm, notifier):
543 """ 544 545 @param wm: Watch Manager. 546 @type wm: WatchManager instance 547 @param notifier: Notifier. 548 @type notifier: Notifier instance 549 """ 550 self._watch_manager = wm # watch manager 551 self._notifier = notifier # notifier 552 self._mv_cookie = {} # {cookie(int): (src_path(str), date), ...} 553 self._mv = {} # {src_path(str): (dst_path(str), date), ...}
554
555 - def cleanup(self):
556 """ 557 Cleanup (delete) old (>1mn) records contained in self._mv_cookie 558 and self._mv. 559 """ 560 date_cur_ = datetime.now() 561 for seq in (self._mv_cookie, self._mv): 562 for k in list(seq.keys()): 563 if (date_cur_ - seq[k][1]) > timedelta(minutes=1): 564 log.debug('Cleanup: deleting entry %s', seq[k][0]) 565 del seq[k]
566
567 - def process_IN_CREATE(self, raw_event):
568 """ 569 If the event affects a directory and the auto_add flag of the 570 targetted watch is set to True, a new watch is added on this 571 new directory, with the same attribute values than those of 572 this watch. 573 """ 574 if raw_event.mask & IN_ISDIR: 575 watch_ = self._watch_manager.get_watch(raw_event.wd) 576 created_dir = os.path.join(watch_.path, raw_event.name) 577 if watch_.auto_add and not watch_.exclude_filter(created_dir): 578 addw = self._watch_manager.add_watch 579 # The newly monitored directory inherits attributes from its 580 # parent directory. 581 addw_ret = addw(created_dir, watch_.mask, 582 proc_fun=watch_.proc_fun, 583 rec=False, auto_add=watch_.auto_add, 584 exclude_filter=watch_.exclude_filter) 585 586 # Trick to handle mkdir -p /t1/t2/t3 where t1 is watched and 587 # t2 and t3 are created. 588 # Since the directory is new, then everything inside it 589 # must also be new. 590 created_dir_wd = addw_ret.get(created_dir) 591 if (created_dir_wd is not None) and created_dir_wd > 0: 592 for name in os.listdir(created_dir): 593 inner = os.path.join(created_dir, name) 594 if (os.path.isdir(inner) and 595 self._watch_manager.get_wd(inner) is None): 596 # Generate (simulate) creation event for sub 597 # directories. 598 rawevent = _RawEvent(created_dir_wd, 599 IN_CREATE | IN_ISDIR, 600 0, name) 601 self._notifier.append_event(rawevent) 602 return self.process_default(raw_event)
603
604 - def process_IN_MOVED_FROM(self, raw_event):
605 """ 606 Map the cookie with the source path (+ date for cleaning). 607 """ 608 watch_ = self._watch_manager.get_watch(raw_event.wd) 609 path_ = watch_.path 610 src_path = os.path.normpath(os.path.join(path_, raw_event.name)) 611 self._mv_cookie[raw_event.cookie] = (src_path, datetime.now()) 612 return self.process_default(raw_event, {'cookie': raw_event.cookie})
613
614 - def process_IN_MOVED_TO(self, raw_event):
615 """ 616 Map the source path with the destination path (+ date for 617 cleaning). 618 """ 619 watch_ = self._watch_manager.get_watch(raw_event.wd) 620 path_ = watch_.path 621 dst_path = os.path.normpath(os.path.join(path_, raw_event.name)) 622 mv_ = self._mv_cookie.get(raw_event.cookie) 623 to_append = {'cookie': raw_event.cookie} 624 if mv_ is not None: 625 self._mv[mv_[0]] = (dst_path, datetime.now()) 626 # Let's assume that IN_MOVED_FROM event is always queued before 627 # that its associated (they share a common cookie) IN_MOVED_TO 628 # event is queued itself. It is then possible in that scenario 629 # to provide as additional information to the IN_MOVED_TO event 630 # the original pathname of the moved file/directory. 631 to_append['src_pathname'] = mv_[0] 632 elif (raw_event.mask & IN_ISDIR and watch_.auto_add and 633 not watch_.exclude_filter(dst_path)): 634 # We got a diretory that's "moved in" from an unknown source and 635 # auto_add is enabled. Manually add watches to the inner subtrees. 636 # The newly monitored directory inherits attributes from its 637 # parent directory. 638 self._watch_manager.add_watch(dst_path, watch_.mask, 639 proc_fun=watch_.proc_fun, 640 rec=True, auto_add=True, 641 exclude_filter=watch_.exclude_filter) 642 return self.process_default(raw_event, to_append)
643
644 - def process_IN_MOVE_SELF(self, raw_event):
645 """ 646 STATUS: the following bug has been fixed in recent kernels (FIXME: 647 which version ?). Now it raises IN_DELETE_SELF instead. 648 649 Old kernels were bugged, this event raised when the watched item 650 were moved, so we had to update its path, but under some circumstances 651 it was impossible: if its parent directory and its destination 652 directory wasn't watched. The kernel (see include/linux/fsnotify.h) 653 doesn't bring us enough informations like the destination path of 654 moved items. 655 """ 656 watch_ = self._watch_manager.get_watch(raw_event.wd) 657 src_path = watch_.path 658 mv_ = self._mv.get(src_path) 659 if mv_: 660 dest_path = mv_[0] 661 watch_.path = dest_path 662 # add the separator to the source path to avoid overlapping 663 # path issue when testing with startswith() 664 src_path += os.path.sep 665 src_path_len = len(src_path) 666 # The next loop renames all watches with src_path as base path. 667 # It seems that IN_MOVE_SELF does not provide IN_ISDIR information 668 # therefore the next loop is iterated even if raw_event is a file. 669 for w in self._watch_manager.watches.values(): 670 if w.path.startswith(src_path): 671 # Note that dest_path is a normalized path. 672 w.path = os.path.join(dest_path, w.path[src_path_len:]) 673 else: 674 log.error("The pathname '%s' of this watch %s has probably changed " 675 "and couldn't be updated, so it cannot be trusted " 676 "anymore. To fix this error move directories/files only " 677 "between watched parents directories, in this case e.g. " 678 "put a watch on '%s'.", 679 watch_.path, watch_, 680 os.path.normpath(os.path.join(watch_.path, 681 os.path.pardir))) 682 if not watch_.path.endswith('-unknown-path'): 683 watch_.path += '-unknown-path' 684 return self.process_default(raw_event)
685
686 - def process_IN_Q_OVERFLOW(self, raw_event):
687 """ 688 Only signal an overflow, most of the common flags are irrelevant 689 for this event (path, wd, name). 690 """ 691 return Event({'mask': raw_event.mask})
692
693 - def process_IN_IGNORED(self, raw_event):
694 """ 695 The watch descriptor raised by this event is now ignored (forever), 696 it can be safely deleted from the watch manager dictionary. 697 After this event we can be sure that neither the event queue nor 698 the system will raise an event associated to this wd again. 699 """ 700 event_ = self.process_default(raw_event) 701 self._watch_manager.del_watch(raw_event.wd) 702 return event_
703
704 - def process_default(self, raw_event, to_append=None):
705 """ 706 Commons handling for the followings events: 707 708 IN_ACCESS, IN_MODIFY, IN_ATTRIB, IN_CLOSE_WRITE, IN_CLOSE_NOWRITE, 709 IN_OPEN, IN_DELETE, IN_DELETE_SELF, IN_UNMOUNT. 710 """ 711 watch_ = self._watch_manager.get_watch(raw_event.wd) 712 if raw_event.mask & (IN_DELETE_SELF | IN_MOVE_SELF): 713 # Unfornulately this information is not provided by the kernel 714 dir_ = watch_.dir 715 else: 716 dir_ = bool(raw_event.mask & IN_ISDIR) 717 dict_ = {'wd': raw_event.wd, 718 'mask': raw_event.mask, 719 'path': watch_.path, 720 'name': raw_event.name, 721 'dir': dir_} 722 if COMPATIBILITY_MODE: 723 dict_['is_dir'] = dir_ 724 if to_append is not None: 725 dict_.update(to_append) 726 return Event(dict_)
727
728 729 -class ProcessEvent(_ProcessEvent):
730 """ 731 Process events objects, can be specialized via subclassing, thus its 732 behavior can be overriden: 733 734 Note: you should not override __init__ in your subclass instead define 735 a my_init() method, this method will be called automatically from the 736 constructor of this class with its optionals parameters. 737 738 1. Provide specialized individual methods, e.g. process_IN_DELETE for 739 processing a precise type of event (e.g. IN_DELETE in this case). 740 2. Or/and provide methods for processing events by 'family', e.g. 741 process_IN_CLOSE method will process both IN_CLOSE_WRITE and 742 IN_CLOSE_NOWRITE events (if process_IN_CLOSE_WRITE and 743 process_IN_CLOSE_NOWRITE aren't defined though). 744 3. Or/and override process_default for catching and processing all 745 the remaining types of events. 746 """ 747 pevent = None 748
749 - def __init__(self, pevent=None, **kargs):
750 """ 751 Enable chaining of ProcessEvent instances. 752 753 @param pevent: Optional callable object, will be called on event 754 processing (before self). 755 @type pevent: callable 756 @param kargs: This constructor is implemented as a template method 757 delegating its optionals keyworded arguments to the 758 method my_init(). 759 @type kargs: dict 760 """ 761 self.pevent = pevent 762 self.my_init(**kargs)
763
764 - def my_init(self, **kargs):
765 """ 766 This method is called from ProcessEvent.__init__(). This method is 767 empty here and must be redefined to be useful. In effect, if you 768 need to specifically initialize your subclass' instance then you 769 just have to override this method in your subclass. Then all the 770 keyworded arguments passed to ProcessEvent.__init__() will be 771 transmitted as parameters to this method. Beware you MUST pass 772 keyword arguments though. 773 774 @param kargs: optional delegated arguments from __init__(). 775 @type kargs: dict 776 """ 777 pass
778
779 - def __call__(self, event):
780 stop_chaining = False 781 if self.pevent is not None: 782 # By default methods return None so we set as guideline 783 # that methods asking for stop chaining must explicitely 784 # return non None or non False values, otherwise the default 785 # behavior will be to accept chain call to the corresponding 786 # local method. 787 stop_chaining = self.pevent(event) 788 if not stop_chaining: 789 return _ProcessEvent.__call__(self, event)
790
791 - def nested_pevent(self):
792 return self.pevent
793
794 - def process_IN_Q_OVERFLOW(self, event):
795 """ 796 By default this method only reports warning messages, you can overredide 797 it by subclassing ProcessEvent and implement your own 798 process_IN_Q_OVERFLOW method. The actions you can take on receiving this 799 event is either to update the variable max_queued_events in order to 800 handle more simultaneous events or to modify your code in order to 801 accomplish a better filtering diminishing the number of raised events. 802 Because this method is defined, IN_Q_OVERFLOW will never get 803 transmitted as arguments to process_default calls. 804 805 @param event: IN_Q_OVERFLOW event. 806 @type event: dict 807 """ 808 log.warning('Event queue overflowed.')
809
810 - def process_default(self, event):
811 """ 812 Default processing event method. By default does nothing. Subclass 813 ProcessEvent and redefine this method in order to modify its behavior. 814 815 @param event: Event to be processed. Can be of any type of events but 816 IN_Q_OVERFLOW events (see method process_IN_Q_OVERFLOW). 817 @type event: Event instance 818 """ 819 pass
820
821 822 -class PrintAllEvents(ProcessEvent):
823 """ 824 Dummy class used to print events strings representations. For instance this 825 class is used from command line to print all received events to stdout. 826 """
827 - def my_init(self, out=None):
828 """ 829 @param out: Where events will be written. 830 @type out: Object providing a valid file object interface. 831 """ 832 if out is None: 833 out = sys.stdout 834 self._out = out
835
836 - def process_default(self, event):
837 """ 838 Writes event string representation to file object provided to 839 my_init(). 840 841 @param event: Event to be processed. Can be of any type of events but 842 IN_Q_OVERFLOW events (see method process_IN_Q_OVERFLOW). 843 @type event: Event instance 844 """ 845 self._out.write(repr(event)) 846 self._out.write('\n')
847
848 849 -class ChainIfTrue(ProcessEvent):
850 """ 851 Makes conditional chaining depending on the result of the nested 852 processing instance. 853 """
854 - def my_init(self, func):
855 """ 856 Method automatically called from base class constructor. 857 """ 858 self._func = func
859
860 - def process_default(self, event):
861 return not self._func(event)
862
863 864 -class Stats(ProcessEvent):
865 """ 866 Compute and display trivial statistics about processed events. 867 """
868 - def my_init(self):
869 """ 870 Method automatically called from base class constructor. 871 """ 872 self._start_time = time.time() 873 self._stats = {} 874 self._stats_lock = threading.Lock()
875
876 - def process_default(self, event):
877 """ 878 Processes |event|. 879 """ 880 self._stats_lock.acquire() 881 try: 882 events = event.maskname.split('|') 883 for event_name in events: 884 count = self._stats.get(event_name, 0) 885 self._stats[event_name] = count + 1 886 finally: 887 self._stats_lock.release()
888
889 - def _stats_copy(self):
890 self._stats_lock.acquire() 891 try: 892 return self._stats.copy() 893 finally: 894 self._stats_lock.release()
895
896 - def __repr__(self):
897 stats = self._stats_copy() 898 899 elapsed = int(time.time() - self._start_time) 900 elapsed_str = '' 901 if elapsed < 60: 902 elapsed_str = str(elapsed) + 'sec' 903 elif 60 <= elapsed < 3600: 904 elapsed_str = '%dmn%dsec' % (elapsed / 60, elapsed % 60) 905 elif 3600 <= elapsed < 86400: 906 elapsed_str = '%dh%dmn' % (elapsed / 3600, (elapsed % 3600) / 60) 907 elif elapsed >= 86400: 908 elapsed_str = '%dd%dh' % (elapsed / 86400, (elapsed % 86400) / 3600) 909 stats['ElapsedTime'] = elapsed_str 910 911 l = [] 912 for ev, value in sorted(stats.items(), key=lambda x: x[0]): 913 l.append(' %s=%s' % (Color.field_name(ev), 914 Color.field_value(value))) 915 s = '<%s%s >' % (Color.class_name(self.__class__.__name__), 916 ''.join(l)) 917 return s
918
919 - def dump(self, filename):
920 """ 921 Dumps statistics to file |filename|. 922 923 @param filename: pathname. 924 @type filename: string 925 """ 926 with open(filename, 'w') as file_obj: 927 file_obj.write(str(self))
928
929 - def __str__(self, scale=45):
930 stats = self._stats_copy() 931 if not stats: 932 return '' 933 934 m = max(stats.values()) 935 unity = scale / m 936 fmt = '%%-26s%%-%ds%%s' % (len(Color.field_value('@' * scale)) 937 + 1) 938 def func(x): 939 return fmt % (Color.field_name(x[0]), 940 Color.field_value('@' * int(x[1] * unity)), 941 Color.simple('%d' % x[1], 'yellow'))
942 s = '\n'.join(map(func, sorted(stats.items(), key=lambda x: x[0]))) 943 return s
944
945 946 -class NotifierError(PyinotifyError):
947 """ 948 Notifier Exception. Raised on Notifier error. 949 950 """
951 - def __init__(self, err):
952 """ 953 @param err: Exception string's description. 954 @type err: string 955 """ 956 PyinotifyError.__init__(self, err)
957
958 959 -class Notifier:
960 """ 961 Read notifications, process events. 962 963 """
964 - def __init__(self, watch_manager, default_proc_fun=None, read_freq=0, 965 threshold=0, timeout=None):
966 """ 967 Initialization. read_freq, threshold and timeout parameters are used 968 when looping. 969 970 @param watch_manager: Watch Manager. 971 @type watch_manager: WatchManager instance 972 @param default_proc_fun: Default processing method. If None, a new 973 instance of PrintAllEvents will be assigned. 974 @type default_proc_fun: instance of ProcessEvent 975 @param read_freq: if read_freq == 0, events are read asap, 976 if read_freq is > 0, this thread sleeps 977 max(0, read_freq - timeout) seconds. But if 978 timeout is None it may be different because 979 poll is blocking waiting for something to read. 980 @type read_freq: int 981 @param threshold: File descriptor will be read only if the accumulated 982 size to read becomes >= threshold. If != 0, you likely 983 want to use it in combination with an appropriate 984 value for read_freq because without that you would 985 keep looping without really reading anything and that 986 until the amount of events to read is >= threshold. 987 At least with read_freq set you might sleep. 988 @type threshold: int 989 @param timeout: 990 http://docs.python.org/lib/poll-objects.html#poll-objects 991 @type timeout: int 992 """ 993 # Watch Manager instance 994 self._watch_manager = watch_manager 995 # File descriptor 996 self._fd = self._watch_manager.get_fd() 997 # Poll object and registration 998 self._pollobj = select.poll() 999 self._pollobj.register(self._fd, select.POLLIN) 1000 # This pipe is correctely initialized and used by ThreadedNotifier 1001 self._pipe = (-1, -1) 1002 # Event queue 1003 self._eventq = deque() 1004 # System processing functor, common to all events 1005 self._sys_proc_fun = _SysProcessEvent(self._watch_manager, self) 1006 # Default processing method 1007 self._default_proc_fun = default_proc_fun 1008 if default_proc_fun is None: 1009 self._default_proc_fun = PrintAllEvents() 1010 # Loop parameters 1011 self._read_freq = read_freq 1012 self._threshold = threshold 1013 self._timeout = timeout 1014 # Coalesce events option 1015 self._coalesce = False 1016 # set of str(raw_event), only used when coalesce option is True 1017 self._eventset = set()
1018
1019 - def append_event(self, event):
1020 """ 1021 Append a raw event to the event queue. 1022 1023 @param event: An event. 1024 @type event: _RawEvent instance. 1025 """ 1026 self._eventq.append(event)
1027
1028 - def proc_fun(self):
1029 return self._default_proc_fun
1030
1031 - def coalesce_events(self, coalesce=True):
1032 """ 1033 Coalescing events. Events are usually processed by batchs, their size 1034 depend on various factors. Thus, before processing them, events received 1035 from inotify are aggregated in a fifo queue. If this coalescing 1036 option is enabled events are filtered based on their unicity, only 1037 unique events are enqueued, doublons are discarded. An event is unique 1038 when the combination of its fields (wd, mask, cookie, name) is unique 1039 among events of a same batch. After a batch of events is processed any 1040 events is accepted again. By default this option is disabled, you have 1041 to explictly call this function to turn it on. 1042 1043 @param coalesce: Optional new coalescing value. True by default. 1044 @type coalesce: Bool 1045 """ 1046 self._coalesce = coalesce 1047 if not coalesce: 1048 self._eventset.clear()
1049
1050 - def check_events(self, timeout=None):
1051 """ 1052 Check for new events available to read, blocks up to timeout 1053 milliseconds. 1054 1055 @param timeout: If specified it overrides the corresponding instance 1056 attribute _timeout. 1057 @type timeout: int 1058 1059 @return: New events to read. 1060 @rtype: bool 1061 """ 1062 while True: 1063 try: 1064 # blocks up to 'timeout' milliseconds 1065 if timeout is None: 1066 timeout = self._timeout 1067 ret = self._pollobj.poll(timeout) 1068 except select.error as err: 1069 if err.errno == errno.EINTR: 1070 continue # interrupted, retry 1071 else: 1072 raise 1073 else: 1074 break 1075 1076 if not ret or (self._pipe[0] == ret[0][0]): 1077 return False 1078 # only one fd is polled 1079 return ret[0][1] & select.POLLIN
1080
1081 - def read_events(self):
1082 """ 1083 Read events from device, build _RawEvents, and enqueue them. 1084 """ 1085 buf_ = array.array('i', [0]) 1086 # get event queue size 1087 if fcntl.ioctl(self._fd, termios.FIONREAD, buf_, 1) == -1: 1088 return 1089 queue_size = buf_[0] 1090 if queue_size < self._threshold: 1091 log.debug('(fd: %d) %d bytes available to read but threshold is ' 1092 'fixed to %d bytes', self._fd, queue_size, 1093 self._threshold) 1094 return 1095 1096 try: 1097 # Read content from file 1098 r = os.read(self._fd, queue_size) 1099 except Exception as msg: 1100 raise NotifierError(msg) 1101 log.debug('Event queue size: %d', queue_size) 1102 rsum = 0 # counter 1103 while rsum < queue_size: 1104 s_size = 16 1105 # Retrieve wd, mask, cookie and fname_len 1106 wd, mask, cookie, fname_len = struct.unpack('iIII', 1107 r[rsum:rsum+s_size]) 1108 # Retrieve name 1109 bname, = struct.unpack('%ds' % fname_len, 1110 r[rsum + s_size:rsum + s_size + fname_len]) 1111 # FIXME: should we explictly call sys.getdefaultencoding() here ?? 1112 uname = bname.decode() 1113 rawevent = _RawEvent(wd, mask, cookie, uname) 1114 if self._coalesce: 1115 # Only enqueue new (unique) events. 1116 raweventstr = str(rawevent) 1117 if raweventstr not in self._eventset: 1118 self._eventset.add(raweventstr) 1119 self._eventq.append(rawevent) 1120 else: 1121 self._eventq.append(rawevent) 1122 rsum += s_size + fname_len
1123
1124 - def process_events(self):
1125 """ 1126 Routine for processing events from queue by calling their 1127 associated proccessing method (an instance of ProcessEvent). 1128 It also does internal processings, to keep the system updated. 1129 """ 1130 while self._eventq: 1131 raw_event = self._eventq.popleft() # pop next event 1132 watch_ = self._watch_manager.get_watch(raw_event.wd) 1133 if watch_ is None: 1134 # Not really sure how we ended up here, nor how we should 1135 # handle these types of events and if it is appropriate to 1136 # completly skip them (like we are doing here). 1137 log.warning("Unable to retrieve Watch object associated to %s", 1138 repr(raw_event)) 1139 continue 1140 revent = self._sys_proc_fun(raw_event) # system processings 1141 if watch_ and watch_.proc_fun: 1142 watch_.proc_fun(revent) # user processings 1143 else: 1144 self._default_proc_fun(revent) 1145 self._sys_proc_fun.cleanup() # remove olds MOVED_* events records 1146 if self._coalesce: 1147 self._eventset.clear()
1148
1149 - def __daemonize(self, pid_file=None, force_kill=False, stdin=os.devnull, 1150 stdout=os.devnull, stderr=os.devnull):
1151 """ 1152 pid_file: file to which the pid will be written. 1153 force_kill: if True kill the process associated to pid_file. 1154 stdin, stdout, stderr: files associated to common streams. 1155 """ 1156 if pid_file is None: 1157 dirname = '/var/run/' 1158 basename = os.path.basename(sys.argv[0]) or 'pyinotify' 1159 pid_file = os.path.join(dirname, basename + '.pid') 1160 1161 if os.path.exists(pid_file): 1162 with open(pid_file, 'r') as fo: 1163 try: 1164 pid = int(fo.read()) 1165 except ValueError: 1166 pid = None 1167 if pid is not None: 1168 try: 1169 os.kill(pid, 0) 1170 except OSError as err: 1171 if err.errno == errno.ESRCH: 1172 log.debug(err) 1173 else: 1174 log.error(err) 1175 else: 1176 if not force_kill: 1177 s = 'There is already a pid file %s with pid %d' 1178 raise NotifierError(s % (pid_file, pid)) 1179 else: 1180 os.kill(pid, 9) 1181 1182 1183 def fork_daemon(): 1184 # Adapted from Chad J. Schroeder's recipe 1185 # @see http://code.activestate.com/recipes/278731/ 1186 pid = os.fork() 1187 if (pid == 0): 1188 # parent 2 1189 os.setsid() 1190 pid = os.fork() 1191 if (pid == 0): 1192 # child 1193 os.chdir('/') 1194 os.umask(0) 1195 else: 1196 # parent 2 1197 os._exit(0) 1198 else: 1199 # parent 1 1200 os._exit(0) 1201 1202 fd_inp = open(stdin, 'r') 1203 os.dup2(fd_inp.fileno(), 0) 1204 fd_out = open(stdout, 'w') 1205 os.dup2(fd_out.fileno(), 1) 1206 fd_err = open(stderr, 'w') 1207 os.dup2(fd_err.fileno(), 2)
1208 1209 # Detach task 1210 fork_daemon() 1211 1212 # Write pid 1213 with open(pid_file, 'w') as file_obj: 1214 file_obj.write(str(os.getpid()) + '\n') 1215 1216 atexit.register(lambda : os.unlink(pid_file))
1217 1218
1219 - def _sleep(self, ref_time):
1220 # Only consider sleeping if read_freq is > 0 1221 if self._read_freq > 0: 1222 cur_time = time.time() 1223 sleep_amount = self._read_freq - (cur_time - ref_time) 1224 if sleep_amount > 0: 1225 log.debug('Now sleeping %d seconds', sleep_amount) 1226 time.sleep(sleep_amount)
1227 1228
1229 - def loop(self, callback=None, daemonize=False, **args):
1230 """ 1231 Events are read only one time every min(read_freq, timeout) 1232 seconds at best and only if the size to read is >= threshold. 1233 After this method returns it must not be called again for the same 1234 instance. 1235 1236 @param callback: Functor called after each event processing iteration. 1237 Expects to receive the notifier object (self) as first 1238 parameter. If this function returns True the loop is 1239 immediately terminated otherwise the loop method keeps 1240 looping. 1241 @type callback: callable object or function 1242 @param daemonize: This thread is daemonized if set to True. 1243 @type daemonize: boolean 1244 @param args: Optional and relevant only if daemonize is True. Remaining 1245 keyworded arguments are directly passed to daemonize see 1246 __daemonize() method. 1247 @type args: various 1248 """ 1249 if daemonize: 1250 self.__daemonize(**args) 1251 1252 # Read and process events forever 1253 while 1: 1254 try: 1255 self.process_events() 1256 if (callback is not None) and (callback(self) is True): 1257 break 1258 ref_time = time.time() 1259 # check_events is blocking 1260 if self.check_events(): 1261 self._sleep(ref_time) 1262 self.read_events() 1263 except KeyboardInterrupt: 1264 # Stop monitoring if sigint is caught (Control-C). 1265 log.debug('Pyinotify stops monitoring.') 1266 break 1267 # Close internals 1268 self.stop()
1269 1270
1271 - def stop(self):
1272 """ 1273 Close inotify's instance (close its file descriptor). 1274 It destroys all existing watches, pending events,... 1275 This method is automatically called at the end of loop(). 1276 """ 1277 self._pollobj.unregister(self._fd) 1278 os.close(self._fd)
1279
1280 1281 -class ThreadedNotifier(threading.Thread, Notifier):
1282 """ 1283 This notifier inherits from threading.Thread for instanciating a separate 1284 thread, and also inherits from Notifier, because it is a threaded notifier. 1285 1286 Note that every functionality provided by this class is also provided 1287 through Notifier class. Moreover Notifier should be considered first because 1288 it is not threaded and could be easily daemonized. 1289 """
1290 - def __init__(self, watch_manager, default_proc_fun=None, read_freq=0, 1291 threshold=0, timeout=None):
1292 """ 1293 Initialization, initialize base classes. read_freq, threshold and 1294 timeout parameters are used when looping. 1295 1296 @param watch_manager: Watch Manager. 1297 @type watch_manager: WatchManager instance 1298 @param default_proc_fun: Default processing method. See base class. 1299 @type default_proc_fun: instance of ProcessEvent 1300 @param read_freq: if read_freq == 0, events are read asap, 1301 if read_freq is > 0, this thread sleeps 1302 max(0, read_freq - timeout) seconds. 1303 @type read_freq: int 1304 @param threshold: File descriptor will be read only if the accumulated 1305 size to read becomes >= threshold. If != 0, you likely 1306 want to use it in combination with an appropriate 1307 value set for read_freq because without that you would 1308 keep looping without really reading anything and that 1309 until the amount of events to read is >= threshold. At 1310 least with read_freq you might sleep. 1311 @type threshold: int 1312 @param timeout: 1313 see http://docs.python.org/lib/poll-objects.html#poll-objects 1314 @type timeout: int 1315 """ 1316 # Init threading base class 1317 threading.Thread.__init__(self) 1318 # Stop condition 1319 self._stop_event = threading.Event() 1320 # Init Notifier base class 1321 Notifier.__init__(self, watch_manager, default_proc_fun, read_freq, 1322 threshold, timeout) 1323 # Create a new pipe used for thread termination 1324 self._pipe = os.pipe() 1325 self._pollobj.register(self._pipe[0], select.POLLIN)
1326
1327 - def stop(self):
1328 """ 1329 Stop notifier's loop. Stop notification. Join the thread. 1330 """ 1331 self._stop_event.set() 1332 os.write(self._pipe[1], b'stop') 1333 threading.Thread.join(self) 1334 Notifier.stop(self) 1335 self._pollobj.unregister(self._pipe[0]) 1336 os.close(self._pipe[0]) 1337 os.close(self._pipe[1])
1338
1339 - def loop(self):
1340 """ 1341 Thread's main loop. Don't meant to be called by user directly. 1342 Call inherited start() method instead. 1343 1344 Events are read only once time every min(read_freq, timeout) 1345 seconds at best and only if the size of events to read is >= threshold. 1346 """ 1347 # When the loop must be terminated .stop() is called, 'stop' 1348 # is written to pipe fd so poll() returns and .check_events() 1349 # returns False which make evaluate the While's stop condition 1350 # ._stop_event.isSet() wich put an end to the thread's execution. 1351 while not self._stop_event.isSet(): 1352 self.process_events() 1353 ref_time = time.time() 1354 if self.check_events(): 1355 self._sleep(ref_time) 1356 self.read_events()
1357
1358 - def run(self):
1359 """ 1360 Start thread's loop: read and process events until the method 1361 stop() is called. 1362 Never call this method directly, instead call the start() method 1363 inherited from threading.Thread, which then will call run() in 1364 its turn. 1365 """ 1366 self.loop()
1367
1368 1369 -class AsyncNotifier(asyncore.file_dispatcher, Notifier):
1370 """ 1371 This notifier inherits from asyncore.file_dispatcher in order to be able to 1372 use pyinotify along with the asyncore framework. 1373 1374 """
1375 - def __init__(self, watch_manager, default_proc_fun=None, read_freq=0, 1376 threshold=0, timeout=None, channel_map=None):
1377 """ 1378 Initializes the async notifier. The only additional parameter is 1379 'channel_map' which is the optional asyncore private map. See 1380 Notifier class for the meaning of the others parameters. 1381 1382 """ 1383 Notifier.__init__(self, watch_manager, default_proc_fun, read_freq, 1384 threshold, timeout) 1385 asyncore.file_dispatcher.__init__(self, self._fd, channel_map)
1386
1387 - def handle_read(self):
1388 """ 1389 When asyncore tells us we can read from the fd, we proceed processing 1390 events. This method can be overridden for handling a notification 1391 differently. 1392 1393 """ 1394 self.read_events() 1395 self.process_events()
1396
1397 1398 -class Watch:
1399 """ 1400 Represent a watch, i.e. a file or directory being watched. 1401 1402 """
1403 - def __init__(self, wd, path, mask, proc_fun, auto_add, exclude_filter):
1404 """ 1405 Initializations. 1406 1407 @param wd: Watch descriptor. 1408 @type wd: int 1409 @param path: Path of the file or directory being watched. 1410 @type path: str 1411 @param mask: Mask. 1412 @type mask: int 1413 @param proc_fun: Processing callable object. 1414 @type proc_fun: 1415 @param auto_add: Automatically add watches on new directories. 1416 @type auto_add: bool 1417 @param exclude_filter: Boolean function, used to exclude new 1418 directories from being automatically watched. 1419 See WatchManager.__init__ 1420 @type exclude_filter: callable object 1421 """ 1422 self.wd = wd 1423 self.path = path 1424 self.mask = mask 1425 self.proc_fun = proc_fun 1426 self.auto_add = auto_add 1427 self.exclude_filter = exclude_filter 1428 self.dir = os.path.isdir(self.path)
1429
1430 - def __repr__(self):
1431 """ 1432 @return: String representation. 1433 @rtype: str 1434 """ 1435 s = ' '.join(['%s%s%s' % (Color.field_name(attr), 1436 Color.punctuation('='), 1437 Color.field_value(getattr(self, attr))) \ 1438 for attr in self.__dict__ if not attr.startswith('_')]) 1439 1440 s = '%s%s %s %s' % (Color.punctuation('<'), 1441 Color.class_name(self.__class__.__name__), 1442 s, 1443 Color.punctuation('>')) 1444 return s
1445
1446 1447 -class ExcludeFilter:
1448 """ 1449 ExcludeFilter is an exclusion filter. 1450 """
1451 - def __init__(self, arg_lst):
1452 """ 1453 Examples: 1454 ef1 = ExcludeFilter(["^/etc/rc.*", "^/etc/hostname"]) 1455 ef2 = ExcludeFilter("/my/path/exclude.lst") 1456 Where exclude.lst contains: 1457 ^/etc/rc.* 1458 ^/etc/hostname 1459 1460 @param arg_lst: is either a list of patterns or a filename from which 1461 patterns will be loaded. 1462 @type arg_lst: list of str or str 1463 """ 1464 if isinstance(arg_lst, str): 1465 lst = self._load_patterns_from_file(arg_lst) 1466 elif isinstance(arg_lst, list): 1467 lst = arg_lst 1468 else: 1469 raise TypeError 1470 1471 self._lregex = [] 1472 for regex in lst: 1473 self._lregex.append(re.compile(regex, re.UNICODE))
1474
1475 - def _load_patterns_from_file(self, filename):
1476 lst = [] 1477 with open(filename, 'r') as file_obj: 1478 for line in file_obj.readlines(): 1479 # Trim leading an trailing whitespaces 1480 pattern = line.strip() 1481 if not pattern or pattern.startswith('#'): 1482 continue 1483 lst.append(pattern) 1484 return lst
1485
1486 - def _match(self, regex, path):
1487 return regex.match(path) is not None
1488
1489 - def __call__(self, path):
1490 """ 1491 @param path: Path to match against provided regexps. 1492 @type path: str 1493 @return: Return True if path has been matched and should 1494 be excluded, False otherwise. 1495 @rtype: bool 1496 """ 1497 for regex in self._lregex: 1498 if self._match(regex, path): 1499 return True 1500 return False
1501
1502 1503 -class WatchManagerError(Exception):
1504 """ 1505 WatchManager Exception. Raised on error encountered on watches 1506 operations. 1507 1508 """
1509 - def __init__(self, msg, wmd):
1510 """ 1511 @param msg: Exception string's description. 1512 @type msg: string 1513 @param wmd: This dictionary contains the wd assigned to paths of the 1514 same call for which watches were successfully added. 1515 @type wmd: dict 1516 """ 1517 self.wmd = wmd 1518 Exception.__init__(self, msg)
1519
1520 1521 -class WatchManager:
1522 """ 1523 Provide operations for watching files and directories. Its internal 1524 dictionary is used to reference watched items. When used inside 1525 threaded code, one must instanciate as many WatchManager instances as 1526 there are ThreadedNotifier instances. 1527 1528 """
1529 - def __init__(self, exclude_filter=lambda path: False):
1530 """ 1531 Initialization: init inotify, init watch manager dictionary. 1532 Raise OSError if initialization fails. 1533 1534 @param exclude_filter: boolean function, returns True if current 1535 path must be excluded from being watched. 1536 Convenient for providing a common exclusion 1537 filter for every call to add_watch. 1538 @type exclude_filter: callable object 1539 """ 1540 self._exclude_filter = exclude_filter 1541 self._wmd = {} # watch dict key: watch descriptor, value: watch 1542 self._fd = LIBC.inotify_init() # inotify's init, file descriptor 1543 if self._fd < 0: 1544 err = 'Cannot initialize new instance of inotify Errno=%s' 1545 raise OSError(err % STRERRNO())
1546
1547 - def get_fd(self):
1548 """ 1549 Return assigned inotify's file descriptor. 1550 1551 @return: File descriptor. 1552 @rtype: int 1553 """ 1554 return self._fd
1555
1556 - def get_watch(self, wd):
1557 """ 1558 Get watch from provided watch descriptor wd. 1559 1560 @param wd: Watch descriptor. 1561 @type wd: int 1562 """ 1563 return self._wmd.get(wd)
1564
1565 - def del_watch(self, wd):
1566 """ 1567 Remove watch entry associated to watch descriptor wd. 1568 1569 @param wd: Watch descriptor. 1570 @type wd: int 1571 """ 1572 try: 1573 del self._wmd[wd] 1574 except KeyError as err: 1575 log.error(str(err))
1576 1577 @property
1578 - def watches(self):
1579 """ 1580 Get a reference on the internal watch manager dictionary. 1581 1582 @return: Internal watch manager dictionary. 1583 @rtype: dict 1584 """ 1585 return self._wmd
1586
1587 - def __format_path(self, path):
1588 """ 1589 Format path to its internal (stored in watch manager) representation. 1590 """ 1591 # path must be a unicode string (str) and is just normalized. 1592 return os.path.normpath(path)
1593
1594 - def __add_watch(self, path, mask, proc_fun, auto_add, exclude_filter):
1595 """ 1596 Add a watch on path, build a Watch object and insert it in the 1597 watch manager dictionary. Return the wd value. 1598 """ 1599 path = self.__format_path(path) 1600 # path to a bytes string. This conversion seems to be required because 1601 # ctypes.create_string_buffer seems to manipulate bytes 1602 # strings representations internally. 1603 # Moreover it seems that LIBC.inotify_add_watch does not work very 1604 # well when it receives an ctypes.create_unicode_buffer instance as 1605 # argument. However wd are _always_ indexed with their original 1606 # unicode paths in wmd. 1607 byte_path = path.encode(sys.getfilesystemencoding()) 1608 wd_ = LIBC.inotify_add_watch(self._fd, 1609 ctypes.create_string_buffer(byte_path), 1610 mask) 1611 if wd_ < 0: 1612 return wd_ 1613 watch_ = Watch(wd=wd_, path=path, mask=mask, proc_fun=proc_fun, 1614 auto_add=auto_add, exclude_filter=exclude_filter) 1615 self._wmd[wd_] = watch_ 1616 log.debug('New %s', watch_) 1617 return wd_
1618
1619 - def __glob(self, path, do_glob):
1620 if do_glob: 1621 return glob.iglob(path) 1622 else: 1623 return [path]
1624
1625 - def add_watch(self, path, mask, proc_fun=None, rec=False, 1626 auto_add=False, do_glob=False, quiet=True, 1627 exclude_filter=None):
1628 """ 1629 Add watch(s) on the provided |path|(s) with associated |mask| flag 1630 value and optionally with a processing |proc_fun| function and 1631 recursive flag |rec| set to True. 1632 All |path| components _must_ be str (i.e. unicode) objects. 1633 If |path| is already watched it is ignored, but if it is called with 1634 option rec=True a watch is put on each one of its not-watched 1635 subdirectory. 1636 1637 @param path: Path to watch, the path can either be a file or a 1638 directory. Also accepts a sequence (list) of paths. 1639 @type path: string or list of strings 1640 @param mask: Bitmask of events. 1641 @type mask: int 1642 @param proc_fun: Processing object. 1643 @type proc_fun: function or ProcessEvent instance or instance of 1644 one of its subclasses or callable object. 1645 @param rec: Recursively add watches from path on all its 1646 subdirectories, set to False by default (doesn't 1647 follows symlinks in any case). 1648 @type rec: bool 1649 @param auto_add: Automatically add watches on newly created 1650 directories in watched parent |path| directory. 1651 @type auto_add: bool 1652 @param do_glob: Do globbing on pathname (see standard globbing 1653 module for more informations). 1654 @type do_glob: bool 1655 @param quiet: if False raises a WatchManagerError exception on 1656 error. See example not_quiet.py. 1657 @type quiet: bool 1658 @param exclude_filter: predicate (boolean function), which returns 1659 True if the current path must be excluded 1660 from being watched. This argument has 1661 precedence over exclude_filter passed to 1662 the class' constructor. 1663 @type exclude_filter: callable object 1664 @return: dict of paths associated to watch descriptors. A wd value 1665 is positive if the watch was added sucessfully, otherwise 1666 the value is negative. If the path was invalid or was already 1667 watched it is not included into this returned dictionary. 1668 @rtype: dict of {str: int} 1669 """ 1670 ret_ = {} # return {path: wd, ...} 1671 1672 if exclude_filter is None: 1673 exclude_filter = self._exclude_filter 1674 1675 # normalize args as list elements 1676 for npath in self.__format_param(path): 1677 # Require that path be a unicode string 1678 if not isinstance(npath, str): 1679 ret_[path] = -3 1680 continue 1681 1682 # unix pathname pattern expansion 1683 for apath in self.__glob(npath, do_glob): 1684 # recursively list subdirs according to rec param 1685 for rpath in self.__walk_rec(apath, rec): 1686 if self.get_wd(rpath) is not None: 1687 # We decide to ignore paths already inserted into 1688 # the watch manager. Need to be removed with rm_watch() 1689 # first. Or simply call update_watch() to update it. 1690 continue 1691 if not exclude_filter(rpath): 1692 wd = ret_[rpath] = self.__add_watch(rpath, mask, 1693 proc_fun, 1694 auto_add, 1695 exclude_filter) 1696 if wd < 0: 1697 err = 'add_watch: cannot watch %s WD=%d Errno=%s' 1698 err = err % (rpath, wd, STRERRNO()) 1699 if quiet: 1700 log.error(err) 1701 else: 1702 raise WatchManagerError(err, ret_) 1703 else: 1704 # Let's say -2 means 'explicitely excluded 1705 # from watching'. 1706 ret_[rpath] = -2 1707 return ret_
1708
1709 - def __get_sub_rec(self, lpath):
1710 """ 1711 Get every wd from self._wmd if its path is under the path of 1712 one (at least) of those in lpath. Doesn't follow symlinks. 1713 1714 @param lpath: list of watch descriptor 1715 @type lpath: list of int 1716 @return: list of watch descriptor 1717 @rtype: list of int 1718 """ 1719 for d in lpath: 1720 root = self.get_path(d) 1721 if root is not None: 1722 # always keep root 1723 yield d 1724 else: 1725 # if invalid 1726 continue 1727 1728 # nothing else to expect 1729 if not os.path.isdir(root): 1730 continue 1731 1732 # normalization 1733 root = os.path.normpath(root) 1734 # recursion 1735 lend = len(root) 1736 for iwd in self._wmd.items(): 1737 cur = iwd[1].path 1738 pref = os.path.commonprefix([root, cur]) 1739 if root == os.sep or (len(pref) == lend and \ 1740 len(cur) > lend and \ 1741 cur[lend] == os.sep): 1742 yield iwd[1].wd
1743
1744 - def update_watch(self, wd, mask=None, proc_fun=None, rec=False, 1745 auto_add=False, quiet=True):
1746 """ 1747 Update existing watch descriptors |wd|. The |mask| value, the 1748 processing object |proc_fun|, the recursive param |rec| and the 1749 |auto_add| and |quiet| flags can all be updated. 1750 1751 @param wd: Watch Descriptor to update. Also accepts a list of 1752 watch descriptors. 1753 @type wd: int or list of int 1754 @param mask: Optional new bitmask of events. 1755 @type mask: int 1756 @param proc_fun: Optional new processing function. 1757 @type proc_fun: function or ProcessEvent instance or instance of 1758 one of its subclasses or callable object. 1759 @param rec: Optionally adds watches recursively on all 1760 subdirectories contained into |wd| directory. 1761 @type rec: bool 1762 @param auto_add: Automatically adds watches on newly created 1763 directories in the watch's path corresponding to 1764 |wd|. 1765 @type auto_add: bool 1766 @param quiet: If False raises a WatchManagerError exception on 1767 error. See example not_quiet.py 1768 @type quiet: bool 1769 @return: dict of watch descriptors associated to booleans values. 1770 True if the corresponding wd has been successfully 1771 updated, False otherwise. 1772 @rtype: dict of {int: bool} 1773 """ 1774 lwd = self.__format_param(wd) 1775 if rec: 1776 lwd = self.__get_sub_rec(lwd) 1777 1778 ret_ = {} # return {wd: bool, ...} 1779 for awd in lwd: 1780 apath = self.get_path(awd) 1781 if not apath or awd < 0: 1782 err = 'update_watch: invalid WD=%d' % awd 1783 if quiet: 1784 log.error(err) 1785 continue 1786 raise WatchManagerError(err, ret_) 1787 1788 if mask: 1789 addw = LIBC.inotify_add_watch 1790 # apath is always stored as unicode string so encode it to 1791 # bytes. 1792 byte_path = apath.encode(sys.getfilesystemencoding()) 1793 wd_ = addw(self._fd, ctypes.create_string_buffer(byte_path), 1794 mask) 1795 if wd_ < 0: 1796 ret_[awd] = False 1797 err = 'update_watch: cannot update %s WD=%d Errno=%s' 1798 err = err % (apath, wd_, STRERRNO()) 1799 if quiet: 1800 log.error(err) 1801 continue 1802 raise WatchManagerError(err, ret_) 1803 1804 assert(awd == wd_) 1805 1806 if proc_fun or auto_add: 1807 watch_ = self._wmd[awd] 1808 1809 if proc_fun: 1810 watch_.proc_fun = proc_fun 1811 1812 if auto_add: 1813 watch_.auto_add = auto_add 1814 1815 ret_[awd] = True 1816 log.debug('Updated watch - %s', self._wmd[awd]) 1817 return ret_
1818
1819 - def __format_param(self, param):
1820 """ 1821 @param param: Parameter. 1822 @type param: string or int 1823 @return: wrap param. 1824 @rtype: list of type(param) 1825 """ 1826 if isinstance(param, list): 1827 for p_ in param: 1828 yield p_ 1829 else: 1830 yield param
1831
1832 - def get_wd(self, path):
1833 """ 1834 Returns the watch descriptor associated to path. This method 1835 presents a prohibitive cost, always prefer to keep the WD 1836 returned by add_watch(). If the path is unknown it returns None. 1837 1838 @param path: Path. 1839 @type path: str 1840 @return: WD or None. 1841 @rtype: int or None 1842 """ 1843 path = self.__format_path(path) 1844 for iwd in self._wmd.items(): 1845 if iwd[1].path == path: 1846 return iwd[0]
1847
1848 - def get_path(self, wd):
1849 """ 1850 Returns the path associated to WD, if WD is unknown it returns None. 1851 1852 @param wd: Watch descriptor. 1853 @type wd: int 1854 @return: Path or None. 1855 @rtype: string or None 1856 """ 1857 watch_ = self._wmd.get(wd) 1858 if watch_ is not None: 1859 return watch_.path
1860
1861 - def __walk_rec(self, top, rec):
1862 """ 1863 Yields each subdirectories of top, doesn't follow symlinks. 1864 If rec is false, only yield top. 1865 1866 @param top: root directory. 1867 @type top: string 1868 @param rec: recursive flag. 1869 @type rec: bool 1870 @return: path of one subdirectory. 1871 @rtype: string 1872 """ 1873 if not rec or os.path.islink(top) or not os.path.isdir(top): 1874 yield top 1875 else: 1876 for root, dirs, files in os.walk(top): 1877 yield root
1878
1879 - def rm_watch(self, wd, rec=False, quiet=True):
1880 """ 1881 Removes watch(s). 1882 1883 @param wd: Watch Descriptor of the file or directory to unwatch. 1884 Also accepts a list of WDs. 1885 @type wd: int or list of int. 1886 @param rec: Recursively removes watches on every already watched 1887 subdirectories and subfiles. 1888 @type rec: bool 1889 @param quiet: If False raises a WatchManagerError exception on 1890 error. See example not_quiet.py 1891 @type quiet: bool 1892 @return: dict of watch descriptors associated to booleans values. 1893 True if the corresponding wd has been successfully 1894 removed, False otherwise. 1895 @rtype: dict of {int: bool} 1896 """ 1897 lwd = self.__format_param(wd) 1898 if rec: 1899 lwd = self.__get_sub_rec(lwd) 1900 1901 ret_ = {} # return {wd: bool, ...} 1902 for awd in lwd: 1903 # remove watch 1904 wd_ = LIBC.inotify_rm_watch(self._fd, awd) 1905 if wd_ < 0: 1906 ret_[awd] = False 1907 err = 'rm_watch: cannot remove WD=%d Errno=%s' % (awd, STRERRNO()) 1908 if quiet: 1909 log.error(err) 1910 continue 1911 raise WatchManagerError(err, ret_) 1912 1913 ret_[awd] = True 1914 log.debug('Watch WD=%d (%s) removed', awd, self.get_path(awd)) 1915 return ret_
1916 1917
1918 - def watch_transient_file(self, filename, mask, proc_class):
1919 """ 1920 Watch a transient file, which will be created and deleted frequently 1921 over time (e.g. pid file). 1922 1923 @attention: Currently under the call to this function it is not 1924 possible to correctly watch the events triggered into the same 1925 base directory than the directory where is located this watched 1926 transient file. For instance it would be wrong to make these 1927 two successive calls: wm.watch_transient_file('/var/run/foo.pid', ...) 1928 and wm.add_watch('/var/run/', ...) 1929 1930 @param filename: Filename. 1931 @type filename: string 1932 @param mask: Bitmask of events, should contain IN_CREATE and IN_DELETE. 1933 @type mask: int 1934 @param proc_class: ProcessEvent (or of one of its subclass), beware of 1935 accepting a ProcessEvent's instance as argument into 1936 __init__, see transient_file.py example for more 1937 details. 1938 @type proc_class: ProcessEvent's instance or of one of its subclasses. 1939 @return: Same as add_watch(). 1940 @rtype: Same as add_watch(). 1941 """ 1942 dirname = os.path.dirname(filename) 1943 if dirname == '': 1944 return {} # Maintains coherence with add_watch() 1945 basename = os.path.basename(filename) 1946 # Assuming we are watching at least for IN_CREATE and IN_DELETE 1947 mask |= IN_CREATE | IN_DELETE 1948 1949 def cmp_name(event): 1950 if getattr(event, 'name') is None: 1951 return False 1952 return basename == event.name
1953 return self.add_watch(dirname, mask, 1954 proc_fun=proc_class(ChainIfTrue(func=cmp_name)), 1955 rec=False, 1956 auto_add=False, do_glob=False, 1957 exclude_filter=lambda path: False)
1958
1959 1960 -class Color:
1961 """ 1962 Internal class. Provide fancy colors used by string representations. 1963 """ 1964 normal = "\033[0m" 1965 black = "\033[30m" 1966 red = "\033[31m" 1967 green = "\033[32m" 1968 yellow = "\033[33m" 1969 blue = "\033[34m" 1970 purple = "\033[35m" 1971 cyan = "\033[36m" 1972 bold = "\033[1m" 1973 uline = "\033[4m" 1974 blink = "\033[5m" 1975 invert = "\033[7m" 1976 1977 @staticmethod
1978 - def punctuation(s):
1979 """Punctuation color.""" 1980 return Color.normal + s + Color.normal
1981 1982 @staticmethod
1983 - def field_value(s):
1984 """Field value color.""" 1985 if not isinstance(s, str): 1986 s = str(s) 1987 return Color.purple + s + Color.normal
1988 1989 @staticmethod
1990 - def field_name(s):
1991 """Field name color.""" 1992 return Color.blue + s + Color.normal
1993 1994 @staticmethod
1995 - def class_name(s):
1996 """Class name color.""" 1997 return Color.red + Color.bold + s + Color.normal
1998 1999 @staticmethod
2000 - def simple(s, color):
2001 if not isinstance(s, str): 2002 s = str(s) 2003 try: 2004 color_attr = getattr(Color, color) 2005 except AttributeError: 2006 return s 2007 return color_attr + s + Color.normal
2008
2009 2010 -def compatibility_mode():
2011 """ 2012 Use this function to turn on the compatibility mode. The compatibility 2013 mode is used to improve compatibility with Pyinotify 0.7.1 (or older) 2014 programs. The compatibility mode provides additional variables 'is_dir', 2015 'event_name', 'EventsCodes.IN_*' and 'EventsCodes.ALL_EVENTS' as 2016 Pyinotify 0.7.1 provided. Do not call this function from new programs!! 2017 Especially if there are developped for Pyinotify >= 0.8.x. 2018 """ 2019 setattr(EventsCodes, 'ALL_EVENTS', ALL_EVENTS) 2020 for evname in globals(): 2021 if evname.startswith('IN_'): 2022 setattr(EventsCodes, evname, globals()[evname]) 2023 global COMPATIBILITY_MODE 2024 COMPATIBILITY_MODE = True
2025
2026 2027 -def command_line():
2028 """ 2029 By default the watched path is '/tmp' and all types of events are 2030 monitored. Events monitoring serves forever, type c^c to stop it. 2031 """ 2032 from optparse import OptionParser 2033 2034 usage = "usage: %prog [options] [path1] [path2] [pathn]" 2035 2036 parser = OptionParser(usage=usage) 2037 parser.add_option("-v", "--verbose", action="store_true", 2038 dest="verbose", help="Verbose mode") 2039 parser.add_option("-r", "--recursive", action="store_true", 2040 dest="recursive", 2041 help="Add watches recursively on paths") 2042 parser.add_option("-a", "--auto_add", action="store_true", 2043 dest="auto_add", 2044 help="Automatically add watches on new directories") 2045 parser.add_option("-e", "--events-list", metavar="EVENT[,...]", 2046 dest="events_list", 2047 help=("A comma-separated list of events to watch for - " 2048 "see the documentation for valid options (defaults" 2049 " to everything)")) 2050 parser.add_option("-s", "--stats", action="store_true", 2051 dest="stats", 2052 help="Display dummy statistics") 2053 2054 (options, args) = parser.parse_args() 2055 2056 if options.verbose: 2057 log.setLevel(10) 2058 2059 if len(args) < 1: 2060 path = '/tmp' # default watched path 2061 else: 2062 path = args 2063 2064 # watch manager instance 2065 wm = WatchManager() 2066 # notifier instance and init 2067 if options.stats: 2068 notifier = Notifier(wm, default_proc_fun=Stats(), read_freq=5) 2069 else: 2070 notifier = Notifier(wm, default_proc_fun=PrintAllEvents()) 2071 2072 # What mask to apply 2073 mask = 0 2074 if options.events_list: 2075 events_list = options.events_list.split(',') 2076 for ev in events_list: 2077 evcode = EventsCodes.ALL_FLAGS.get(ev, 0) 2078 if evcode: 2079 mask |= evcode 2080 else: 2081 parser.error("The event '%s' specified with option -e" 2082 " is not valid" % ev) 2083 else: 2084 mask = ALL_EVENTS 2085 2086 # stats 2087 cb_fun = None 2088 if options.stats: 2089 def cb(s): 2090 print('%s\n%s\n' % (repr(s.proc_fun()), 2091 s.proc_fun()))
2092 cb_fun = cb 2093 2094 log.debug('Start monitoring %s, (press c^c to halt pyinotify)' % path) 2095 2096 wm.add_watch(path, mask, rec=options.recursive, auto_add=options.auto_add) 2097 # Loop forever (until sigint signal get caught) 2098 notifier.loop(callback=cb_fun) 2099 2100 2101 if __name__ == '__main__': 2102 command_line() 2103

pyinotify/python3/docstrings/pyinotify.WatchManager-class.html0000644000175000017500000012014311402071465024301 0ustar ookoiookoi pyinotify.WatchManager
Module pyinotify :: Class WatchManager
[hide private]
[frames] | no frames]

Class WatchManager

source code

Provide operations for watching files and directories. Its internal dictionary is used to reference watched items. When used inside threaded code, one must instanciate as many WatchManager instances as there are ThreadedNotifier instances.

Instance Methods [hide private]
 
__init__(self, exclude_filter=lambda path: False)
Initialization: init inotify, init watch manager dictionary.
source code
int
get_fd(self)
Return assigned inotify's file descriptor.
source code
 
get_watch(self, wd)
Get watch from provided watch descriptor wd.
source code
 
del_watch(self, wd)
Remove watch entry associated to watch descriptor wd.
source code
dict
watches(self)
Get a reference on the internal watch manager dictionary.
source code
 
__format_path(self, path)
Format path to its internal (stored in watch manager) representation.
source code
 
__add_watch(self, path, mask, proc_fun, auto_add, exclude_filter)
Add a watch on path, build a Watch object and insert it in the watch manager dictionary.
source code
 
__glob(self, path, do_glob) source code
dict of {str: int}
add_watch(self, path, mask, proc_fun=None, rec=False, auto_add=False, do_glob=False, quiet=True, exclude_filter=None)
Add watch(s) on the provided |path|(s) with associated |mask| flag value and optionally with a processing |proc_fun| function and recursive flag |rec| set to True.
source code
list of int
__get_sub_rec(self, lpath)
Get every wd from self._wmd if its path is under the path of one (at least) of those in lpath.
source code
dict of {int: bool}
update_watch(self, wd, mask=None, proc_fun=None, rec=False, auto_add=False, quiet=True)
Update existing watch descriptors |wd|.
source code
list of type(param)
__format_param(self, param)
Returns: wrap param.
source code
int or None
get_wd(self, path)
Returns the watch descriptor associated to path.
source code
string or None
get_path(self, wd)
Returns the path associated to WD, if WD is unknown it returns None.
source code
string
__walk_rec(self, top, rec)
Yields each subdirectories of top, doesn't follow symlinks.
source code
dict of {int: bool}
rm_watch(self, wd, rec=False, quiet=True)
Removes watch(s).
source code
Same as add_watch().
watch_transient_file(self, filename, mask, proc_class)
Watch a transient file, which will be created and deleted frequently over time (e.g.
source code
Method Details [hide private]

__init__(self, exclude_filter=lambda path: False)
(Constructor)

source code 

Initialization: init inotify, init watch manager dictionary. Raise OSError if initialization fails.

Parameters:
  • exclude_filter (callable object) - boolean function, returns True if current path must be excluded from being watched. Convenient for providing a common exclusion filter for every call to add_watch.

get_fd(self)

source code 

Return assigned inotify's file descriptor.

Returns: int
File descriptor.

get_watch(self, wd)

source code 

Get watch from provided watch descriptor wd.

Parameters:
  • wd (int) - Watch descriptor.

del_watch(self, wd)

source code 

Remove watch entry associated to watch descriptor wd.

Parameters:
  • wd (int) - Watch descriptor.

watches(self)

source code 

Get a reference on the internal watch manager dictionary.

Returns: dict
Internal watch manager dictionary.
Decorators:
  • @property

__add_watch(self, path, mask, proc_fun, auto_add, exclude_filter)

source code 

Add a watch on path, build a Watch object and insert it in the watch manager dictionary. Return the wd value.

add_watch(self, path, mask, proc_fun=None, rec=False, auto_add=False, do_glob=False, quiet=True, exclude_filter=None)

source code 

Add watch(s) on the provided |path|(s) with associated |mask| flag value and optionally with a processing |proc_fun| function and recursive flag |rec| set to True. All |path| components _must_ be str (i.e. unicode) objects. If |path| is already watched it is ignored, but if it is called with option rec=True a watch is put on each one of its not-watched subdirectory.

Parameters:
  • path (string or list of strings) - Path to watch, the path can either be a file or a directory. Also accepts a sequence (list) of paths.
  • mask (int) - Bitmask of events.
  • proc_fun (function or ProcessEvent instance or instance of one of its subclasses or callable object.) - Processing object.
  • rec (bool) - Recursively add watches from path on all its subdirectories, set to False by default (doesn't follows symlinks in any case).
  • auto_add (bool) - Automatically add watches on newly created directories in watched parent |path| directory.
  • do_glob (bool) - Do globbing on pathname (see standard globbing module for more informations).
  • quiet (bool) - if False raises a WatchManagerError exception on error. See example not_quiet.py.
  • exclude_filter (callable object) - predicate (boolean function), which returns True if the current path must be excluded from being watched. This argument has precedence over exclude_filter passed to the class' constructor.
Returns: dict of {str: int}
dict of paths associated to watch descriptors. A wd value is positive if the watch was added sucessfully, otherwise the value is negative. If the path was invalid or was already watched it is not included into this returned dictionary.

__get_sub_rec(self, lpath)

source code 

Get every wd from self._wmd if its path is under the path of one (at least) of those in lpath. Doesn't follow symlinks.

Parameters:
  • lpath (list of int) - list of watch descriptor
Returns: list of int
list of watch descriptor

update_watch(self, wd, mask=None, proc_fun=None, rec=False, auto_add=False, quiet=True)

source code 

Update existing watch descriptors |wd|. The |mask| value, the processing object |proc_fun|, the recursive param |rec| and the |auto_add| and |quiet| flags can all be updated.

Parameters:
  • wd (int or list of int) - Watch Descriptor to update. Also accepts a list of watch descriptors.
  • mask (int) - Optional new bitmask of events.
  • proc_fun (function or ProcessEvent instance or instance of one of its subclasses or callable object.) - Optional new processing function.
  • rec (bool) - Optionally adds watches recursively on all subdirectories contained into |wd| directory.
  • auto_add (bool) - Automatically adds watches on newly created directories in the watch's path corresponding to |wd|.
  • quiet (bool) - If False raises a WatchManagerError exception on error. See example not_quiet.py
Returns: dict of {int: bool}
dict of watch descriptors associated to booleans values. True if the corresponding wd has been successfully updated, False otherwise.

__format_param(self, param)

source code 
Parameters:
  • param (string or int) - Parameter.
Returns: list of type(param)
wrap param.

get_wd(self, path)

source code 

Returns the watch descriptor associated to path. This method presents a prohibitive cost, always prefer to keep the WD returned by add_watch(). If the path is unknown it returns None.

Parameters:
  • path (str) - Path.
Returns: int or None
WD or None.

get_path(self, wd)

source code 

Returns the path associated to WD, if WD is unknown it returns None.

Parameters:
  • wd (int) - Watch descriptor.
Returns: string or None
Path or None.

__walk_rec(self, top, rec)

source code 

Yields each subdirectories of top, doesn't follow symlinks. If rec is false, only yield top.

Parameters:
  • top (string) - root directory.
  • rec (bool) - recursive flag.
Returns: string
path of one subdirectory.

rm_watch(self, wd, rec=False, quiet=True)

source code 

Removes watch(s).

Parameters:
  • wd (int or list of int.) - Watch Descriptor of the file or directory to unwatch. Also accepts a list of WDs.
  • rec (bool) - Recursively removes watches on every already watched subdirectories and subfiles.
  • quiet (bool) - If False raises a WatchManagerError exception on error. See example not_quiet.py
Returns: dict of {int: bool}
dict of watch descriptors associated to booleans values. True if the corresponding wd has been successfully removed, False otherwise.

watch_transient_file(self, filename, mask, proc_class)

source code 

Watch a transient file, which will be created and deleted frequently over time (e.g. pid file).

Parameters:
  • filename (string) - Filename.
  • mask (int) - Bitmask of events, should contain IN_CREATE and IN_DELETE.
  • proc_class (ProcessEvent's instance or of one of its subclasses.) - ProcessEvent (or of one of its subclass), beware of accepting a ProcessEvent's instance as argument into __init__, see transient_file.py example for more details.
Returns: Same as add_watch().
Same as add_watch().

Attention: Currently under the call to this function it is not possible to correctly watch the events triggered into the same base directory than the directory where is located this watched transient file. For instance it would be wrong to make these two successive calls: wm.watch_transient_file('/var/run/foo.pid', ...) and wm.add_watch('/var/run/', ...)


pyinotify/python3/docstrings/module-tree.html0000644000175000017500000000702711402071464021032 0ustar ookoiookoi Module Hierarchy
 
[hide private]
[frames] | no frames]
[ Module Hierarchy | Class Hierarchy ]

Module Hierarchy

pyinotify/python3/docstrings/pyinotify._RawEvent-class.html0000644000175000017500000002272311402071465023637 0ustar ookoiookoi pyinotify._RawEvent
Module pyinotify :: Class _RawEvent
[hide private]
[frames] | no frames]

Class _RawEvent

source code


Raw event, it contains only the informations provided by the system. It doesn't infer anything.

Instance Methods [hide private]
 
__init__(self, wd, mask, cookie, name)
Attach attributes (contained in dict_) to self.
source code
 
__str__(self) source code

Inherited from _Event: __repr__

Method Details [hide private]

__init__(self, wd, mask, cookie, name)
(Constructor)

source code 

Attach attributes (contained in dict_) to self.

Parameters:
  • wd (int) - Watch Descriptor.
  • mask (int) - Bitmask of events.
  • cookie (int) - Cookie.
  • name (string or None) - Basename of the file or directory against which the event was raised in case where the watched directory is the parent directory. None if the event was raised on the watched item itself.
Overrides: _Event.__init__

pyinotify/python3/docstrings/crarr.png0000644000175000017500000000052411402071464017534 0ustar ookoiookoiPNG  IHDR eE,tEXtCreation TimeTue 22 Aug 2006 00:43:10 -0500` XtIME)} pHYsnu>gAMA aEPLTEðf4sW ЊrD`@bCܖX{`,lNo@xdE螊dƴ~TwvtRNS@fMIDATxc`@0&+(;; /EXؑ? n  b;'+Y#(r<"IENDB`pyinotify/python3/docstrings/uml_class_diagram_for_pyinotif.gif0000644000175000017500000005560711402071464024655 0ustar ookoiookoiGIF87aLBDĤBDTĢ$"$b\ĆlZ\bdT2,ĺD<2,rd dJD|fdtvlԦ|&$D:4̖TJD|^TܲԬRT4&$~|Ԫ24ܺrtdRT \F4jlTF<,rtdNDĖzl"$D>< |bT4*$Ԫ  vl ~t|j\lZ\d\64ĎĔz|̢̒nd䶴L|Ğ̞<.,Ċ|jl̚D6,$lVL,&$\NLlFDfd䬊|ܶԬVT64ܾvtdVTĔ.,ܮ̒ NLndnlԦ><侼~|̌vtĚ&$Ԯ ^\̤̦<24ԦD:< \FDrl~|L:va8%qmgpdx!iQ)9nQ@[p 1b '1) wippjFʺ)VkRNKAРxx8:3EJ(|znS;pZp~!ms^k>e;&Nt{LTQlxL οjm`UlO 2\|V$㝷"~nհo8?޼'^h Q BP)%2QҜ(7i80`B4g 0"X/Q+gVÙ Hw+8%N^瑑 %\D20; ֆ M8)=IOdM-k[(`x7жZ:7̥4Ϣυ $0Hx7qg7ќ:rB$:9]G}`.~& hVکh"C?*ІR -JQ@T-+Q\4 C;Jң|4(FKҧ4)iKg0{)Mwn8Y$NS&>Nz#ԡ槨GK9yPVURMQBz*CRф*d#0OlUEҭgv4uiQ=ZΘLC!6}9׼e 7F}LZjH0(flM-G&)Jk+0Lִjw%͌c*$ VQd6M)g[閷%5Vs[0v%\6=!'ZsŘ8Άuؤ[!::MB2NpA l`O"Xfp`'Xc-,` g0z=a$X%q}xbV+a]ZX31dm|ƹձ!Vy|9V #[/Jfȭ^b7"/YE'5hFBoNp' |c|4y {gu1Z#5HE=PL1$q5Go'Ғf`0MpX2Mb,qPTIl#uknlhSwׅ1e2SֳMmQ%p^l~q3ٟ|. cd[hண=rWgn%9EzئP&ܱ&8o ~p* opuF\8Tsc<1?ㄇ#'9 )~rQvuĐ) k̕+?m/9)U)^=R3JTaft"Kt>Fe-lz\^Wo۞Н0ZL:vWnV6l(]J[v! [[y;Mxq[;pxm|O"Uk} ;{zƶg{^}7x|;hSG-j3۾z}s^*'P?:~_kvRXMwh+h Ga^/Evƀ;5j Sj`\T2h8i}CwEh%A؃N3PR8S"xXBKȄC…]h-Zhb8R xhh)b70cdžmx$@qwptXCKq.`{ȇ!v%Rb V3VC>#X7\9~Gm%nQHmJLYqNNnBTVc`Pq'l^.dx^OB8n\ /q zD_u!Gr" !AE˜RO(jWٵ"L%6,򯉢ڴ5:}>OM4q,ƹ=ųQ^\Q_^+_\ܻ-0Z?mV,iee.mV[Ls  1I,C-}P,?pVqȂ[4~OXlL&>aF8 $6Y,X.=yˋ˚5to]KNn̶xI|O=,_Lh j].'睚ik m}]j/4HLBWoD4 f?%k`0rUЂZy$ Б;ȱxB< aH8tA$ ?⧸qG*""(D&6MCL#FQDKtb$(jt4(",LV,F6NhcF:Q6oc/5G;я',>ѐ4 H>$OHJVˇd&2JvJd(1I\ճ.+O񒢄e,]H!ypY^i*irQe0HJr|r._„f&Q6 SP谅`sa G&&! ?[ee͎Uc09& j@#Њ4oD`>/$j:[gӢ~Dv Df& k!8-D$ϋT}(SHV׺ׁw;u|J v\;66q*X/"GJ"LP_g$|SKTFխtj@ dρ KH*M4}kbMW) X P G0h!| *ִ#f"$=ml/6M1Du`+[ކl*cΘ[7!eo;Q"׹RrVwRѕn+k]o;^va7.yK'w]o|ˤȅʘJ*3+ʽڭ||(R"~H.{?i0t BO8SP 0DD`x $Ư(՛@8I>s`X99bwZÓ0l(u!Ejg@ZЃ>4Sc@|C3 B7wiIR!/v2PR$m P{Vvʻ1ySAse&<`\ĸ솙bM+JQU+4iZۈjX_J^2ů|l`:X6!u'Z5 ,fqz!hFLO joV{֮~w_Cζ=pYn~o7^^tp+OW+q\8EW!KnrS<*!bhlq=l]Je{s1Ӧ +}LzMbNt)lցsͺ3eOhu@qwZ=w/elnHY-g/.,clBe@1C5gS8f}2SK/ֻrGvI/_vfjzݬXUU/vC;DM@`7/N b: DtDgg?zlvք몌Q7s%8!-7$ s@![*@[9# A<KAt̾AFaA/AEAT/?A/? /S*c!$B2BS1:;@()=Z4[:+ 8)B#'P;&v̺[287|CB)3P@~*<:<('Dq26 D43b(R5jLT"X[8D$EBAE멣;BP4z3`ČQE?C +b>a5y>YQFCb(D ?> +a |d t|9 7ӫͲ?kĈojȂČ|FL9:I@-YHk/  ~ǎ9D$P5]N=5A ` ]HQԻB>z|{+pQ>$%GIP9T*x3`ȁqH-HHH,-RْJHL1-{>I IL!%7535D# l;ü̅xLPh10̈DLm͙͒yM\T^t=Ƃλ(DRW{%ZҼSZlŻyEu^^'Ҝ-CXU|X߷* :FKŪrpp-JQ{DžeGGǭu`l uRt.FɪncȤe?m25%"IŐŐ:^a"v 8,U(6\b0F-1c!,c3Mc1acr7f5Bc:Tc=>c doAƠ<.dKBdac=>F.E^Xzd:KL~Mdd eQ4RSTVeP][^X\['e_fT;.f>fdeF$a[bf2溥jޖfvfLUfm* Ba\[2fp^qV&.\[ʍ uf$q %I]{|V:8`]͌LXLb]]Ei/|&A'm2%2=LWh"Ck_\[u5= Q.86і& 0` amuk 9kn_?ɬ%=H-*L7qɖ*n&$&-V ˰bxn#7b mކ7fh#k.Nfn(A}n+X6b&6FVfohoXnモ'7Gς,Hw odZ0# d2HQ cRWp, bbq3VbHHbP<ȂPxPȂ<r'.OO($oZI IZ,_'%5rSȃ4WsS2/DX8,q7?^\Xp\ ,=>s@<'tC/t?WtMFGIJtLMtO/Pu%uv!TWUgVwWXYZ[\]^_S12cGdWegfwghijk8bEB%랴vlvp#Ov}[kiwCm;M@qi|wbwM 1|qʁGʄ2klЅ;xa\G_`)\`d|yVy?=wxCIH@l֜Cql^v7BlOLyVz~_guu{w{U_Գ7O{iPMpWgwLJȗɧʷw|耬gGWgwקf A/{*|PO}|i~O!Ag~t~~J'7|~Ӈwח/v\,h „ 2l!DPh"ƌ7r#Ȑ"G,i$ʔ*3f%̘2gҬi&Μ:ʒEΠB$Y!dR0qtP)6rkǖDǒ-k,ڳ=m(؍QֱHT⼊[L*q.\RĊ3ns5>{{ >K5wp!#(A%ЁlM rتC DF٠SBӀЄ.LLBL* qJ^"k  3<^呻p/~H) BhYd3!h(FmϊfT 87zF&IG5fZ+?!yt=Ji2hIH! 8<+֐^␂h1Ҥ4"!o&MIAjЄomۊ)@=a7ks'=aҩҥ>[#Z!!I)SAJ-II*ְ(5f-U;U$b$3*W`*8׽v5#^Wv~k?,+bϪX1ֱa# +}{=-jS՚($X+vmgG;l J E$ZbfGۖ}.t+Rֽ.vFMKn湿l?Kf$0r lxKb6Kۜ$2 o~;,/6+]Ɂ17f璨[*|A6zlSIz(<;H!tǏzR .6d`|Gˑ1ntrz,dqu˳8ĈTaL z%I0FÌ̦&5EH |IOoΈ*_7L gTr2HE\g4GtTT 9YIBҦfq> ΰWe$AuJGq+$B82!V1ҜimZ zFCc1//-"O0" (EQ$ǼS2I)MLRLnLƄWoSdնȵ uW=S'e[>tve=rt &EΠ};XPĬIgbxU;F^mXݔUTT*fXRzqB˗ ZEb)=Jf(SMQ=o:S7(/V'v9 Or7Dn}D*xF9f.0ϝ2z^$!1~owz12aP/XMyzY<_siGCҩاNZiUUǺ1Qu 'ЧmVoJ|CfZɜ404*ۯEi>iЂS~|u-r,?_=^l+AQ aA^E ̜ܥE^D,L?p R n?OIMTLA@pMP)MYNFDC QA*OA![t !ʑR !PUhaJTT]!UEpE@ qzDͅF YCQDGp!2 YXIJNQUʡ|FEVu šL r!A(Kyaـ!<ҞN" 3}UHQXu'†فD5J̠BXpa\Qb22zh&<# q#hcHc7B7vD,|Ëy ,PP:c;>#H @?2D3ԖC>$DFDN4C0"$Fj?.Xt@HH$II$JJ$KK$U\dF$($G&;dEdAN$GMDNP>AVH@IWFGUho1%3S(qUPDQWSZ%IXXFWTF%]YXyW%MeRN=ƀqF_ޓ͍ĂU]%^Τ^J)ۉafD]njgJ( rA`@(eXǼ5+l)٘bdcfcE5ɛ{fڎ!@gx!Yڡ&E,Aw!aZ`ZyRtF~N4$E~'EJ^a2,A}[܀߉^\}#229+DphJ]֧}G$((H$``JϩX)f-UhKRE0lµ=QD'M 'Fy vSGl؞~F 뱩]iy`)hBO}ricx)BĎ$&+#F "uyR. !`a0eߨF"!#R'GE8EؗwRTNFl)NJ*DA*!崢 U2!^)rapaF]E@Gf"*L*i_]yǼQ]~PR^&&'.j~= khbbֿN񨐫j&;dX{%hx욹Cy E=6V6*zjzuf'mUOȅ΄O%^.2N>i2,ITdզU\?.#%)^) v6eF-JE2;E*M>ũUA pV.Im;.JbpW2!!rT+Z.~v2b+>熡N"TO܍ph@n*ZDzRn`E䪇Won2&UdHlGt/LXY~[^Z*>Ax8H` / FKIk1 ((2))2** Ot,2("W5 \ATnwr4B(x䕍&bFvk!VQɺ*234I-  ܂`],/IsX0*-X>l\HoCD d*$x4Ԇta=HgIA3@+)5O3uSSC0BVP{B@/$B(uPoS,boZWIWuB @1d-5o6Q_Z vlOA/OIg%~EEWvbAOCe۬ŦE撱zfl~I%kp,,jj[Y-(tHRTR5چ' AM'pv"v*mTpsn`?O+\R)R\FY (+1UDwj,ɂOVsM55qx۾Љq7A3KsS#D+Ԃ׼ Ɠ)2#i$©%O8;*8sBtB-C*$ a0M/O/GE1sj: C/9F\v#H-O@KsKX vk-"ZN7s֢8S+3yPwN(OWH3?zB.D1PBo2ov Ozip4XxtHzR$aocz"y*O ;Rg$?{I,E d##-5]R|6+VϾ#BlIX~aVvE"q&krJED;(PRDz!ќ6%ZE›p/tʷ<_D$W};zI&<of+D5t3,}Q0-Nzf[}k. @t{ge702'a 0ASڢ I+z窢wQFx'?|~%(ɪ00̑3F O”cIWqw2 %@2&BL:CƊ%4CeS̈P H$+#7Vq%Y83$Ģ,y $J/F-R'A,4U*eꔠ=}5lYgѦUm[oƕ;n]wջ,Y;-hF+6 @180'')Ap ϡ5C4c ̘ki͛_w~ȸtӢ]N합@|`nẇy̥Ji{K|yѧWZj?0mb[ &":rh'a4PbBТz%5[I?,/Ϊj& %LJĉԄ: :S@Q$N\thȮo)+Q%˹K y"L4+r & 28"⡂Wf1!6⡏W04b6CI4A 9}D(6,ܳO7"BTPF1f!=[ʹ$U5J jvF6CZ.N[Fmr*  [V/Zl05ۉO\oqg[>pB-9,pZCYoa]*hld߁Vn!eO^o6^驟@j?//bx{_'-ZG?D@Ʌ+@NdA F(%A %|7Bލ K+jq- Hl6ذ"'=L WD!ZK)Ta- MkTx?@ˇUb8D-nJh_ jIPQ$PIlmtٲE91=_dQ llY8˙G6IE`7N*#1I>Y(?bK N40h 5Q ψ+6̀/;Mz)`iem)M}N )@ZqKxݤ%Nq% /P& pj`77iEpղ@/I&0T!5b"(哢=g?1ZLR- R֘œ堒#n$ RV`\EaJ‹f򀥬h'u.]g{xpL_I[ZLJ֔rHq%Vk^3ܢNe"%+mf%)^*VΏf ǰ>_TGIȦ6~ua3hoJ}%ciXNVpJnVg' ^a>_8ڱy^ _C@{mq[os05q\.us al:w^BYxћ^u{_wյF1Α _w_Y#8 aa 0B!a }@8AbC,cd;bϘƽ(_ЩBU$(YN!F@?A\ H"Y|U8* /3 (le17KN3Vxadp"g9YEV3؂OϽxqhAYÔH@H .fz60zpb~pMW=qcO>@,T//!0%po(05p5rr Jo/H/HFH/!H/!2Z! 2!v3Z0wX ,0/ 0F@a Ho`Zp aH 7a1A!!w0aZ00 p0)a`ZP O/O/1maZ,} #q/&#0r#H !1IA Pi/bѱIpAI/qK cqP߱!21/!)"gh`a@ 2! a8@[a"ur'!Qy2(K IF2Q ~* IO<&6arR(r'#/&2--Mo..+'%(r/u,`203.r0!211Q00!2-213 %.F<3A34Es4I4M4Q35C<5a36es6i6m6q37us7y7}738s88839s9993:}S R233;s;ӱ::331S.>s?'3.?t@ .:S5tAAA!4B%tBË5]S:14C5tC9C=CA4DEtDID:@UtEY-EetFi4^-b oAb/otGwHoIoO42 AIQHtL KKYLKtt4,g!2S"SfQL o!o/PP5J/NQo,@ r0U/PF-6S?"Zu+OӯJ(kU4Emu"Ad!r5X5T/Y/HAXW uTtXNT5JiuZeOLn-rtJ])aOP<c23C2A* @pl!0g[)An`jHabw^d@d6špzfr`UdU`L`1gr Y=%Lgds0iKd5fuf3`pgYft`kvA^sy^Q.e˶hϖ_u-)fq`aq6bi17c?6koÑlCju}MoVdPi+nCaWj5sQkTWQc9clw0ha&vqrYh1k4oAN/^b^50,w u 0mW!  [0#o A6{w#|Io\`7\ a7w~VV\%Ɨ}}p;y U1`㐀 xcOIQex#@kXzŐ yEp Iχ4q՗}#i}WW/y]~͸׌ XUI҂XY!x-T\wp7=K 1 58qUo&ԇAl q1Qf2]yRXuWQ* ypeѕC9ɔZ -9[y|@wQBuWY;y m1!UMi!qY 2YDYyٝQTYy :ZIw-Y 5.d  @ { zzeZz`iѨ}zYWXyRXGxk7Q:WӚZIm+ϚzrZZvgYGz9x:[;wn#۬iI"z_RS/@XŁIraY1g)]Y!1p^1﹉5:[g2RQyX њ]ە;_[u1푖m\<ۣݻgUϻ۱RXw0+m?s[ W `ha#Oy9&qRQ@{21bĹ$Q/<{6ʓoڠ& ty<PVtw%0&SHɟ|%[%gw|:o@!U "uh~=a2]S-0U:ǜ|Yc;}J$|ʑɛ_=]́w_t,eOʀ)Q+=,[ U@~!L*Pٽc0la,To,=/߅` ݃{q}i/{^IT~ ࿹P> AKiLw!ba7=湝) muQ灚S! +42Wë࿺giqm^GS ݤ09 qOz}Qa\P   a'o  2? C?ϵQpq ykЋA5vo^P1KF)c\>W]?\;-`?-"?տ@,??<, :]Ν`<7<0ĉ+Z1ƍ;z2ȑ$K<2ʕ,+̙4kڌ !ylР<yzХL:} 5ԩTZe֭2s)H4#.յlۺ} 7ܹVr[ӫA'[8 D;'f&umdʀ1O:ܤVAsHٴk۾;nvp" ^Q$@  qg]1mc~xХS@O${v ;_QoB$1>(-M!YsGXfHZ >@udx3 QAVxaP.B2Hc6hnUO<5q6"zXkI䣒?9aGDax 29YOHfbIn:xS{ɓ-bܱYTIOw"Mo68g9C@ED_L> it&yf}Yfp.s1 uLbAbv G:sF4C N? uROMuV_uZou^ vbMvfvjͶ 4@!rMwvߍwzw~ xNxx/x?yON9o_yoyz袏Nz馟zꪯz뮿{N{ߎ{{|O||/|?}OO}_}o}~O~柏~~;pyinotify/python3/docstrings/pyinotify.ProcessEvent-class.html0000644000175000017500000005115011402071465024361 0ustar ookoiookoi pyinotify.ProcessEvent
Module pyinotify :: Class ProcessEvent
[hide private]
[frames] | no frames]

Class ProcessEvent

source code


Process events objects, can be specialized via subclassing, thus its behavior can be overriden:

Note: you should not override __init__ in your subclass instead define a my_init() method, this method will be called automatically from the constructor of this class with its optionals parameters.

  1. Provide specialized individual methods, e.g. process_IN_DELETE for processing a precise type of event (e.g. IN_DELETE in this case).
  2. Or/and provide methods for processing events by 'family', e.g. process_IN_CLOSE method will process both IN_CLOSE_WRITE and IN_CLOSE_NOWRITE events (if process_IN_CLOSE_WRITE and process_IN_CLOSE_NOWRITE aren't defined though).
  3. Or/and override process_default for catching and processing all the remaining types of events.
Instance Methods [hide private]
 
__init__(self, pevent=None, **kargs)
Enable chaining of ProcessEvent instances.
source code
 
my_init(self, **kargs)
This method is called from ProcessEvent.__init__().
source code
bool
__call__(self, event)
To behave like a functor the object must be callable.
source code
 
nested_pevent(self) source code
 
process_IN_Q_OVERFLOW(self, event)
By default this method only reports warning messages, you can overredide it by subclassing ProcessEvent and implement your own process_IN_Q_OVERFLOW method.
source code
 
process_default(self, event)
Default processing event method.
source code

Inherited from _ProcessEvent: __repr__

Class Variables [hide private]
  pevent = None
Method Details [hide private]

__init__(self, pevent=None, **kargs)
(Constructor)

source code 

Enable chaining of ProcessEvent instances.

Parameters:
  • pevent (callable) - Optional callable object, will be called on event processing (before self).
  • kargs (dict) - This constructor is implemented as a template method delegating its optionals keyworded arguments to the method my_init().

my_init(self, **kargs)

source code 

This method is called from ProcessEvent.__init__(). This method is empty here and must be redefined to be useful. In effect, if you need to specifically initialize your subclass' instance then you just have to override this method in your subclass. Then all the keyworded arguments passed to ProcessEvent.__init__() will be transmitted as parameters to this method. Beware you MUST pass keyword arguments though.

Parameters:
  • kargs (dict) - optional delegated arguments from __init__().

__call__(self, event)
(Call operator)

source code 

To behave like a functor the object must be callable. This method is a dispatch method. Its lookup order is:

  1. process_MASKNAME method
  2. process_FAMILY_NAME method
  3. otherwise calls process_default
Parameters:
  • event - Event to be processed.
Returns: bool
By convention when used from the ProcessEvent class:
  • Returning False or None (default value) means keep on executing next chained functors (see chain.py example).
  • Returning True instead means do not execute next processing functions.
Raises:
Overrides: _ProcessEvent.__call__
(inherited documentation)

process_IN_Q_OVERFLOW(self, event)

source code 

By default this method only reports warning messages, you can overredide it by subclassing ProcessEvent and implement your own process_IN_Q_OVERFLOW method. The actions you can take on receiving this event is either to update the variable max_queued_events in order to handle more simultaneous events or to modify your code in order to accomplish a better filtering diminishing the number of raised events. Because this method is defined, IN_Q_OVERFLOW will never get transmitted as arguments to process_default calls.

Parameters:
  • event (dict) - IN_Q_OVERFLOW event.

process_default(self, event)

source code 

Default processing event method. By default does nothing. Subclass ProcessEvent and redefine this method in order to modify its behavior.

Parameters:
  • event (Event instance) - Event to be processed. Can be of any type of events but IN_Q_OVERFLOW events (see method process_IN_Q_OVERFLOW).

pyinotify/python3/docstrings/api-objects.txt0000644000175000017500000003433411402071465020665 0ustar ookoiookoipyinotify pyinotify-module.html pyinotify.LIBC pyinotify-module.html#LIBC pyinotify.compatibility_mode pyinotify-module.html#compatibility_mode pyinotify.STRERRNO pyinotify-module.html#STRERRNO pyinotify.LIBC_VERSION pyinotify-module.html#LIBC_VERSION pyinotify.COMPATIBILITY_MODE pyinotify-module.html#COMPATIBILITY_MODE pyinotify.__author__ pyinotify-module.html#__author__ pyinotify.log pyinotify-module.html#log pyinotify.command_line pyinotify-module.html#command_line pyinotify.ALL_EVENTS pyinotify-module.html#ALL_EVENTS pyinotify.logger_init pyinotify-module.html#logger_init pyinotify.AsyncNotifier pyinotify.AsyncNotifier-class.html pyinotify.Notifier.read_events pyinotify.Notifier-class.html#read_events pyinotify.Notifier.proc_fun pyinotify.Notifier-class.html#proc_fun pyinotify.Notifier._sleep pyinotify.Notifier-class.html#_sleep pyinotify.AsyncNotifier.__init__ pyinotify.AsyncNotifier-class.html#__init__ pyinotify.Notifier.process_events pyinotify.Notifier-class.html#process_events pyinotify.Notifier.append_event pyinotify.Notifier-class.html#append_event pyinotify.Notifier.stop pyinotify.Notifier-class.html#stop pyinotify.AsyncNotifier.handle_read pyinotify.AsyncNotifier-class.html#handle_read pyinotify.Notifier.check_events pyinotify.Notifier-class.html#check_events pyinotify.Notifier.coalesce_events pyinotify.Notifier-class.html#coalesce_events pyinotify.Notifier.loop pyinotify.Notifier-class.html#loop pyinotify.ChainIfTrue pyinotify.ChainIfTrue-class.html pyinotify.ChainIfTrue.my_init pyinotify.ChainIfTrue-class.html#my_init pyinotify.ProcessEvent.nested_pevent pyinotify.ProcessEvent-class.html#nested_pevent pyinotify.ProcessEvent.process_IN_Q_OVERFLOW pyinotify.ProcessEvent-class.html#process_IN_Q_OVERFLOW pyinotify.ProcessEvent.pevent pyinotify.ProcessEvent-class.html#pevent pyinotify._ProcessEvent.__repr__ pyinotify._ProcessEvent-class.html#__repr__ pyinotify.ChainIfTrue.process_default pyinotify.ChainIfTrue-class.html#process_default pyinotify.ProcessEvent.__call__ pyinotify.ProcessEvent-class.html#__call__ pyinotify.ProcessEvent.__init__ pyinotify.ProcessEvent-class.html#__init__ pyinotify.Color pyinotify.Color-class.html pyinotify.Color.blue pyinotify.Color-class.html#blue pyinotify.Color.bold pyinotify.Color-class.html#bold pyinotify.Color.normal pyinotify.Color-class.html#normal pyinotify.Color.purple pyinotify.Color-class.html#purple pyinotify.Color.invert pyinotify.Color-class.html#invert pyinotify.Color.punctuation pyinotify.Color-class.html#punctuation pyinotify.Color.simple pyinotify.Color-class.html#simple pyinotify.Color.yellow pyinotify.Color-class.html#yellow pyinotify.Color.blink pyinotify.Color-class.html#blink pyinotify.Color.class_name pyinotify.Color-class.html#class_name pyinotify.Color.green pyinotify.Color-class.html#green pyinotify.Color.cyan pyinotify.Color-class.html#cyan pyinotify.Color.black pyinotify.Color-class.html#black pyinotify.Color.uline pyinotify.Color-class.html#uline pyinotify.Color.field_value pyinotify.Color-class.html#field_value pyinotify.Color.field_name pyinotify.Color-class.html#field_name pyinotify.Color.red pyinotify.Color-class.html#red pyinotify.Event pyinotify.Event-class.html pyinotify._Event.__repr__ pyinotify._Event-class.html#__repr__ pyinotify.Event.__init__ pyinotify.Event-class.html#__init__ pyinotify.EventsCodes pyinotify.EventsCodes-class.html pyinotify.EventsCodes.IN_MOVED_FROM pyinotify.EventsCodes-class.html#IN_MOVED_FROM pyinotify.EventsCodes.FLAG_COLLECTIONS pyinotify.EventsCodes-class.html#FLAG_COLLECTIONS pyinotify.EventsCodes.IN_CREATE pyinotify.EventsCodes-class.html#IN_CREATE pyinotify.EventsCodes.IN_MOVED_TO pyinotify.EventsCodes-class.html#IN_MOVED_TO pyinotify.EventsCodes.IN_MOVE_SELF pyinotify.EventsCodes-class.html#IN_MOVE_SELF pyinotify.EventsCodes.ALL_FLAGS pyinotify.EventsCodes-class.html#ALL_FLAGS pyinotify.EventsCodes.IN_UNMOUNT pyinotify.EventsCodes-class.html#IN_UNMOUNT pyinotify.EventsCodes.IN_ONESHOT pyinotify.EventsCodes-class.html#IN_ONESHOT pyinotify.EventsCodes.IN_ONLYDIR pyinotify.EventsCodes-class.html#IN_ONLYDIR pyinotify.EventsCodes.IN_Q_OVERFLOW pyinotify.EventsCodes-class.html#IN_Q_OVERFLOW pyinotify.EventsCodes.IN_IGNORED pyinotify.EventsCodes-class.html#IN_IGNORED pyinotify.EventsCodes.IN_DELETE pyinotify.EventsCodes-class.html#IN_DELETE pyinotify.EventsCodes.IN_DONT_FOLLOW pyinotify.EventsCodes-class.html#IN_DONT_FOLLOW pyinotify.EventsCodes.IN_CLOSE_WRITE pyinotify.EventsCodes-class.html#IN_CLOSE_WRITE pyinotify.EventsCodes.IN_ACCESS pyinotify.EventsCodes-class.html#IN_ACCESS pyinotify.EventsCodes.maskname pyinotify.EventsCodes-class.html#maskname pyinotify.EventsCodes.IN_MODIFY pyinotify.EventsCodes-class.html#IN_MODIFY pyinotify.EventsCodes.ALL_VALUES pyinotify.EventsCodes-class.html#ALL_VALUES pyinotify.EventsCodes.IN_MASK_ADD pyinotify.EventsCodes-class.html#IN_MASK_ADD pyinotify.EventsCodes.IN_CLOSE_NOWRITE pyinotify.EventsCodes-class.html#IN_CLOSE_NOWRITE pyinotify.EventsCodes.IN_ISDIR pyinotify.EventsCodes-class.html#IN_ISDIR pyinotify.EventsCodes.IN_DELETE_SELF pyinotify.EventsCodes-class.html#IN_DELETE_SELF pyinotify.EventsCodes.ALL_EVENTS pyinotify.EventsCodes-class.html#ALL_EVENTS pyinotify.EventsCodes.IN_OPEN pyinotify.EventsCodes-class.html#IN_OPEN pyinotify.EventsCodes.IN_ATTRIB pyinotify.EventsCodes-class.html#IN_ATTRIB pyinotify.ExcludeFilter pyinotify.ExcludeFilter-class.html pyinotify.ExcludeFilter.__call__ pyinotify.ExcludeFilter-class.html#__call__ pyinotify.ExcludeFilter._match pyinotify.ExcludeFilter-class.html#_match pyinotify.ExcludeFilter.__init__ pyinotify.ExcludeFilter-class.html#__init__ pyinotify.ExcludeFilter._load_patterns_from_file pyinotify.ExcludeFilter-class.html#_load_patterns_from_file pyinotify.Notifier pyinotify.Notifier-class.html pyinotify.Notifier.read_events pyinotify.Notifier-class.html#read_events pyinotify.Notifier.coalesce_events pyinotify.Notifier-class.html#coalesce_events pyinotify.Notifier.append_event pyinotify.Notifier-class.html#append_event pyinotify.Notifier.stop pyinotify.Notifier-class.html#stop pyinotify.Notifier.__daemonize pyinotify.Notifier-class.html#__daemonize pyinotify.Notifier.check_events pyinotify.Notifier-class.html#check_events pyinotify.Notifier.proc_fun pyinotify.Notifier-class.html#proc_fun pyinotify.Notifier.loop pyinotify.Notifier-class.html#loop pyinotify.Notifier._sleep pyinotify.Notifier-class.html#_sleep pyinotify.Notifier.__init__ pyinotify.Notifier-class.html#__init__ pyinotify.Notifier.process_events pyinotify.Notifier-class.html#process_events pyinotify.NotifierError pyinotify.NotifierError-class.html pyinotify.NotifierError.__init__ pyinotify.NotifierError-class.html#__init__ pyinotify.PrintAllEvents pyinotify.PrintAllEvents-class.html pyinotify.PrintAllEvents.my_init pyinotify.PrintAllEvents-class.html#my_init pyinotify.ProcessEvent.nested_pevent pyinotify.ProcessEvent-class.html#nested_pevent pyinotify.ProcessEvent.process_IN_Q_OVERFLOW pyinotify.ProcessEvent-class.html#process_IN_Q_OVERFLOW pyinotify.ProcessEvent.pevent pyinotify.ProcessEvent-class.html#pevent pyinotify._ProcessEvent.__repr__ pyinotify._ProcessEvent-class.html#__repr__ pyinotify.PrintAllEvents.process_default pyinotify.PrintAllEvents-class.html#process_default pyinotify.ProcessEvent.__call__ pyinotify.ProcessEvent-class.html#__call__ pyinotify.ProcessEvent.__init__ pyinotify.ProcessEvent-class.html#__init__ pyinotify.ProcessEvent pyinotify.ProcessEvent-class.html pyinotify.ProcessEvent.my_init pyinotify.ProcessEvent-class.html#my_init pyinotify.ProcessEvent.nested_pevent pyinotify.ProcessEvent-class.html#nested_pevent pyinotify.ProcessEvent.process_IN_Q_OVERFLOW pyinotify.ProcessEvent-class.html#process_IN_Q_OVERFLOW pyinotify.ProcessEvent.pevent pyinotify.ProcessEvent-class.html#pevent pyinotify._ProcessEvent.__repr__ pyinotify._ProcessEvent-class.html#__repr__ pyinotify.ProcessEvent.process_default pyinotify.ProcessEvent-class.html#process_default pyinotify.ProcessEvent.__call__ pyinotify.ProcessEvent-class.html#__call__ pyinotify.ProcessEvent.__init__ pyinotify.ProcessEvent-class.html#__init__ pyinotify.ProcessEventError pyinotify.ProcessEventError-class.html pyinotify.ProcessEventError.__init__ pyinotify.ProcessEventError-class.html#__init__ pyinotify.PyinotifyError pyinotify.PyinotifyError-class.html pyinotify.PyinotifyLogger pyinotify.PyinotifyLogger-class.html pyinotify.PyinotifyLogger.makeRecord pyinotify.PyinotifyLogger-class.html#makeRecord pyinotify.Stats pyinotify.Stats-class.html pyinotify.Stats.my_init pyinotify.Stats-class.html#my_init pyinotify.Stats.dump pyinotify.Stats-class.html#dump pyinotify.ProcessEvent.nested_pevent pyinotify.ProcessEvent-class.html#nested_pevent pyinotify.Stats.__str__ pyinotify.Stats-class.html#__str__ pyinotify.ProcessEvent.process_IN_Q_OVERFLOW pyinotify.ProcessEvent-class.html#process_IN_Q_OVERFLOW pyinotify.ProcessEvent.pevent pyinotify.ProcessEvent-class.html#pevent pyinotify.Stats._stats_copy pyinotify.Stats-class.html#_stats_copy pyinotify.Stats.__repr__ pyinotify.Stats-class.html#__repr__ pyinotify.Stats.process_default pyinotify.Stats-class.html#process_default pyinotify.ProcessEvent.__call__ pyinotify.ProcessEvent-class.html#__call__ pyinotify.ProcessEvent.__init__ pyinotify.ProcessEvent-class.html#__init__ pyinotify.SysCtlINotify pyinotify.SysCtlINotify-class.html pyinotify.SysCtlINotify.set_val pyinotify.SysCtlINotify-class.html#set_val pyinotify.SysCtlINotify.value pyinotify.SysCtlINotify-class.html#value pyinotify.SysCtlINotify.get_val pyinotify.SysCtlINotify-class.html#get_val pyinotify.SysCtlINotify.__repr__ pyinotify.SysCtlINotify-class.html#__repr__ pyinotify.SysCtlINotify.inotify_attrs pyinotify.SysCtlINotify-class.html#inotify_attrs pyinotify.SysCtlINotify.__init__ pyinotify.SysCtlINotify-class.html#__init__ pyinotify.ThreadedNotifier pyinotify.ThreadedNotifier-class.html pyinotify.Notifier.read_events pyinotify.Notifier-class.html#read_events pyinotify.Notifier.check_events pyinotify.Notifier-class.html#check_events pyinotify.Notifier.proc_fun pyinotify.Notifier-class.html#proc_fun pyinotify.Notifier._sleep pyinotify.Notifier-class.html#_sleep pyinotify.ThreadedNotifier.__init__ pyinotify.ThreadedNotifier-class.html#__init__ pyinotify.Notifier.process_events pyinotify.Notifier-class.html#process_events pyinotify.Notifier.coalesce_events pyinotify.Notifier-class.html#coalesce_events pyinotify.ThreadedNotifier.run pyinotify.ThreadedNotifier-class.html#run pyinotify.ThreadedNotifier.stop pyinotify.ThreadedNotifier-class.html#stop pyinotify.Notifier.append_event pyinotify.Notifier-class.html#append_event pyinotify.ThreadedNotifier.loop pyinotify.ThreadedNotifier-class.html#loop pyinotify.UnsupportedLibcVersionError pyinotify.UnsupportedLibcVersionError-class.html pyinotify.UnsupportedLibcVersionError.__init__ pyinotify.UnsupportedLibcVersionError-class.html#__init__ pyinotify.UnsupportedPythonVersionError pyinotify.UnsupportedPythonVersionError-class.html pyinotify.UnsupportedPythonVersionError.__init__ pyinotify.UnsupportedPythonVersionError-class.html#__init__ pyinotify.Watch pyinotify.Watch-class.html pyinotify.Watch.__repr__ pyinotify.Watch-class.html#__repr__ pyinotify.Watch.__init__ pyinotify.Watch-class.html#__init__ pyinotify.WatchManager pyinotify.WatchManager-class.html pyinotify.WatchManager.__walk_rec pyinotify.WatchManager-class.html#__walk_rec pyinotify.WatchManager.__glob pyinotify.WatchManager-class.html#__glob pyinotify.WatchManager.__get_sub_rec pyinotify.WatchManager-class.html#__get_sub_rec pyinotify.WatchManager.add_watch pyinotify.WatchManager-class.html#add_watch pyinotify.WatchManager.get_wd pyinotify.WatchManager-class.html#get_wd pyinotify.WatchManager.__format_param pyinotify.WatchManager-class.html#__format_param pyinotify.WatchManager.watches pyinotify.WatchManager-class.html#watches pyinotify.WatchManager.watch_transient_file pyinotify.WatchManager-class.html#watch_transient_file pyinotify.WatchManager.rm_watch pyinotify.WatchManager-class.html#rm_watch pyinotify.WatchManager.__add_watch pyinotify.WatchManager-class.html#__add_watch pyinotify.WatchManager.get_watch pyinotify.WatchManager-class.html#get_watch pyinotify.WatchManager.del_watch pyinotify.WatchManager-class.html#del_watch pyinotify.WatchManager.update_watch pyinotify.WatchManager-class.html#update_watch pyinotify.WatchManager.get_path pyinotify.WatchManager-class.html#get_path pyinotify.WatchManager.__format_path pyinotify.WatchManager-class.html#__format_path pyinotify.WatchManager.__init__ pyinotify.WatchManager-class.html#__init__ pyinotify.WatchManager.get_fd pyinotify.WatchManager-class.html#get_fd pyinotify.WatchManagerError pyinotify.WatchManagerError-class.html pyinotify.WatchManagerError.__init__ pyinotify.WatchManagerError-class.html#__init__ pyinotify._Event pyinotify._Event-class.html pyinotify._Event.__repr__ pyinotify._Event-class.html#__repr__ pyinotify._Event.__init__ pyinotify._Event-class.html#__init__ pyinotify._ProcessEvent pyinotify._ProcessEvent-class.html pyinotify._ProcessEvent.__call__ pyinotify._ProcessEvent-class.html#__call__ pyinotify._ProcessEvent.__repr__ pyinotify._ProcessEvent-class.html#__repr__ pyinotify._RawEvent pyinotify._RawEvent-class.html pyinotify._RawEvent.__str__ pyinotify._RawEvent-class.html#__str__ pyinotify._Event.__repr__ pyinotify._Event-class.html#__repr__ pyinotify._RawEvent.__init__ pyinotify._RawEvent-class.html#__init__ pyinotify._SysProcessEvent pyinotify._SysProcessEvent-class.html pyinotify._SysProcessEvent.process_IN_IGNORED pyinotify._SysProcessEvent-class.html#process_IN_IGNORED pyinotify._SysProcessEvent.process_default pyinotify._SysProcessEvent-class.html#process_default pyinotify._SysProcessEvent.process_IN_CREATE pyinotify._SysProcessEvent-class.html#process_IN_CREATE pyinotify._SysProcessEvent.process_IN_MOVE_SELF pyinotify._SysProcessEvent-class.html#process_IN_MOVE_SELF pyinotify._SysProcessEvent.process_IN_Q_OVERFLOW pyinotify._SysProcessEvent-class.html#process_IN_Q_OVERFLOW pyinotify._SysProcessEvent.process_IN_MOVED_FROM pyinotify._SysProcessEvent-class.html#process_IN_MOVED_FROM pyinotify._SysProcessEvent.cleanup pyinotify._SysProcessEvent-class.html#cleanup pyinotify._ProcessEvent.__repr__ pyinotify._ProcessEvent-class.html#__repr__ pyinotify._SysProcessEvent.process_IN_MOVED_TO pyinotify._SysProcessEvent-class.html#process_IN_MOVED_TO pyinotify._ProcessEvent.__call__ pyinotify._ProcessEvent-class.html#__call__ pyinotify._SysProcessEvent.__init__ pyinotify._SysProcessEvent-class.html#__init__ pyinotify/python3/docstrings/uml_class_diagram_for_pyinotif_12.gif0000644000175000017500000002155611402071465025154 0ustar ookoiookoiGIF87a|LBDĤBDĆ$"$Ԧd^\jdbddJDT.,| <2,ܶĖvtĴĞܪ|^TTJDlvllVL&$$D:4RT4&$Ԣj\ԮĞ64 \F<̦rdnd쾼~tL:4TB<4*$jl  rt~tL><~| Ԧ<24lVT$D:H|FȀ.R5#&Ԩ <5I, @m l&9V X*X#!震.u-Ѝ0%.|24IHf2(!PF)g"?$ci.B#ˋ@2 c\` 4>f#9:縑:rFBE!!H(r{ "*JKK!%=Jj#?PZd|)+Re! ,"e{̃čA|R URP0UCCjMihG=PȤh1ƜH+ PݢNZ2`ebrR|;D%]pU,ˤh-{\=4DϕuPqVB%PIHe[b>ĶHT"HYQS"d6-ͦmbhu,BMj-K#ʍ1*D86H=uTcT9UuTC V!d-ڐzleHhG׺׾ lѷ0 qaQXM4!$H0# x!#7c ccXظ6tCȑQ\'S/+Oi S1  %BD'&Ue". #f e(\zL.,6P_`._A& u١@VCs/aH0P( E qb-0&!cTtoSN+xy1<ڙc(Jś#@8< cśb$S0TM9SbE v"D\0{n)-您y͍k3A m5dϕ_2=9Αɋh2ђm2cz𝋟a ֶ3^`W]qe\nz(:KRT*B®[{7U.ȀJ\1%xJi:Z.T!ٲʔN}cAW͋}-jM9!A3 _}zt+CBP19lFՙ!΀_NFƒ0#&+1wzl ]8,>fɃAW+b1p@5čglcݸ7H-3Xk0~y<Ȟ9"\#q+IRUpʆ2`\juֵ[ul wG}g(w6|{Ft,{Bo׫@A4%MӬ ̻ڷ|N iz2anm&/4X.^w57lS٭I21D/C^ Cm-l6wvVNNGx.[ܷ|Z\ ʴ~9bop 6)g26gqp$qGqaq*aWrpr/01Wg>.b4UsqcA`Bc4V6bHmatu,Xyt' oad}kFS>U6S3eWGvba DvKWvLy׆nwp7thgj8o'hZV[HTB(SgZy׳iz#zhPL+7$4g{P+{l!|$bM'LJ'|.}ifڗ@8޷^(omnzn+-o_a-hP8Kuw8p PoB/ p'/Hq!QR"20q!xB)uOƂ=s|sc8Տ~4N71GCwp7utCs"'iJRWp1xAm1w YBP\#9xd܁,YwvNvMI%cUT)US\yxYfqyyed!A^dh%ej[7{5Dnޅ|U]}!B]&fuՖvV'܆^$)(~X_C=*eP7`pE&pQ숀1Vauiara$" 0i!x4%n1-S&+9DYvaT6ee\9xؒzJu *:e@䕟#pUޣod6#pA šy4YO*$χW!J ~n?Gzouoƍ<-蛉/w~`!)*i4#73c*"XR 87qi7Vv8nF}  1vz:g]i:pS g4f*TkJ {8Yvj*&hY_oaxxK%5qJĶ]](mFܚ"X*AR̺[d_Do!zx1Q`*SׯO:ah :hhRP2B ^3o38skSj7vs)۰Nx +q4p0 :B9vd<ٳת>D[ǠGʱQsqӴh\ AZXq9[wzK*?&l;$犪]Fr皵} ȮNmxqQkBoz(vp&;{BWQ w1s1|k8R+9+/(sZ L2㉰(*kH,;.?24 z>=9{e;VUٽkOZ cTVXU۫n[5:jTGՊ\1q{ַ \_I݅q1GR+ ǩ*XqŦspar8yh ̽Z\o26q3 [vkkںǫˀr%7 1Ti];'^%J|\o/^7~¬ ؏EIJ;9C~K+ɛp- q ;ț83aR3kAz#8ױ95KQ\mG+ iI|ra =zXO M8 ! &}(=.02=4]6}8ӄP>@5 P঳̟qi ..eC pZH~\@Q3%ءc㶘#$&( \D$@]>*)=S%7L?@6_BʏMF>"?PI"L (ۦk¤B[omKڤ ].52}[1.{ǥrQ f:-Lpb/tހ;~I-g^)f?n#3٦31JPoqݜpځ(K377{z50⃣/yEicU ?zJGn9>9N랠>| X~WtΠNn/  ? P$_Q!~=1\Yx/lqCC@Ĉ@U=~RH%M%J-]%id ΆOTǔ<]iFF"%ҍC^źD]~ !Xa Q"VmF%vWȭkśw,ܹ}X`U ^FYbw4d&~ZFZ5X],[lڵmƝ6tō&Q@O͝?2Ŧ"LDǞ]+Pڱ]x%5XeӑkTҪQzǟ!X:NaE?< U<dAN)`/P$J#N0 3)$A ED ABrgoD1GQ (Fs]:1QI'c'.J*J,lNK.tK0DLL2ϔL4״JM6M8IN:N0iYyУϬ{O R!|G?}g}E}?_q>׿/w$j d?F0Y-( ~aEH>#a UȾ^AEˢa r]P|CTC hDJYjTOE*zT.Ƞ"E.b!5),B pEHSANqJ $l!;&BEX"$HZ+@Y@6JLI$D)3IN~ĒT兖P+\–,@by!Vȗ<.3(a 1e.JMr&LU5dMmf)47Lq4340g<9OzӞ<%|ӟ=%Ԡq6ԡ0LԢhF5Qvԣ}G3Qt%hf!_)GQӲԣ@DOљԧ?,|JRtFsXթ;}jGqS4W-P*Ә0`U5S$ZUR &:@**Is Z{D-:JXW{ @°plxATRt_!0pE `W|ual, {ҷuvj=.\'ɾvݦf Ǯvm;V~wQUPbG|x7|%?yS>FywO U>zҗMzֻCQ}e?{^(}uS~'{^ǧ=27χ~/KF~}҈Ob|7 Ϳ$o+WR?(]}voH>̛Z;K8ջ@;RJX[=Jxs?-*)6胹Z:(7p8p:-T-s-- 7;3JKj./z2A8z&q+:.9{d !$.#.ʂ%0 ;2 ۨW?_@*(&sC(cDȂ1.#@D#(`CK3 )(ZsrDóX3?#Ð0NLC 3_5;[@C88CMK1BC,+TC0t/u+Ŏ c8j3B8`0$D )RĨ*6b{9Kƞ9t,p:2 nEl4H4գKds=>P«z֛1"@p*WӨ @ȋ$P 3Ȏ*ȑ)$ɔ(⾗ɘ API Documentation pyinotify/python3/docstrings/pyinotify.PyinotifyError-class.html0000644000175000017500000002102711402071465024745 0ustar ookoiookoi pyinotify.PyinotifyError
Module pyinotify :: Class PyinotifyError
[hide private]
[frames] | no frames]

Class PyinotifyError

source code


Indicates exceptions raised by a Pyinotify class.

Instance Methods [hide private]

Inherited from exceptions.Exception: __init__, __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__, __unicode__

Inherited from object: __format__, __hash__, __reduce_ex__, __sizeof__, __subclasshook__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

pyinotify/python3/docstrings/uml_class_diagram_for_pyinotif_6.gif0000644000175000017500000001601411402071465025070 0ustar ookoiookoiGIF87aLBDĤFDĢ$"$ĆdVTf\ܲnl<2, vt\NLԦ|\F<4*$$  nd쾼|L><̢̤,&$̒z|dRTĬRTܶ~t<24Ԧ|Ě\FDrlD:<$ zlܮ:<侼̞ԪL:HC}M]cJqEQ)buE,D CE/))H6nlA H:1M1cM> i Ld2 dB 0@$a$ = d ;"< !C0# D|ȥ@ "ΐ PH&)1 Bl88lj^z(:iZ(($ )x`=Oxʳ5'@yρFP5B2p}"*ѫQG(Ful  HGJҒ(MJWҕbhLgJӚtӞTh6ЀlӢON`:PTJժZMŋ%6ծvU*^*JֲժFPjG$ԳaSKrkSנ׾թi]_ ׼6t U {W*] Z .r@BV l@[g+@ Z`1hkaUZa&Xe cCVl5(X|5"hE8YXDS"Px0q?3Uձ5B[%BYPpZ 9~* х )9;xʏ P]ÅJJhةe>Є8uN5 *ct +>BMD#A4U-DS%ф&C*<ЉrV"xt_,h˷$QdS !hj$ʚֶ~MڂM IzHf;ɮȲMj[Ѧȴn:ٶM["T vMzη~G>ԂO­ r;=wD [ܭ/Uʥle9d#lO9ٸ^[2@5pmsnqm!: ]ⷼo};wyק3D0la k'NqYL\Ox/;i,r?^r)k9=ޭwNoo*`8[Ue&@8{ c9{ĉ{glF{vgMVXR;QgZ۟%KYqVaXL ,~ n|p7t |vLUXTUS_L:KK< ֥kye|l軃ZZZ s>Zj[tܻ5ʶk|9fc@]PU7Ywz9ּju+e9ȹ}7iwvKrKwR&,Lْ t~g>+W|'̓lgc-abؕl<9gT_lc®2{•/L?/_\h̭9Kļi9+} i{F{yMTBKyXfe5gu8=yfeeԌÐV^k[Vfydž[-nxQD#H#1XjXReĐ&pXSLF&ęS!C=}~G1$s%C1>ZѦN>, *59)&idK.q .M>i I$h@2zXD9tϗL . d6hX+9ZcB9ZZ(M"4l(+Z>kȑƛ$&QDMh(1F0FxC6SORԉA8r F:( 5Ƞ-,".M+0˂KqFMa.2l-;k3JEKJ$ `P[Z H "*OChL#N! a lENihՇh"]Yu (9X4Ynr4'H3A!Jq B93WˉD> ׹q+sN2;23Vx+ˈWwK%PY#jك%p* 2$1c2$5VnG$ 8`> @D&QeMGjb:e@6&mbicbxk!*@[T/Ζb zn=H^Tn>#.HD|nHr˕\/si?'t Y Ȑu_=vgvo=www^v2ÏG>ygy矇>z駧z #x{?|'|G?}g}߇?~秿~?`8@ЀD` @6Ё ;pyinotify/python3/docstrings/pyinotify.ExcludeFilter-class.html0000644000175000017500000002435511402071464024506 0ustar ookoiookoi pyinotify.ExcludeFilter
Module pyinotify :: Class ExcludeFilter
[hide private]
[frames] | no frames]

Class ExcludeFilter

source code

ExcludeFilter is an exclusion filter.

Instance Methods [hide private]
 
__init__(self, arg_lst)
Examples: ef1 = ExcludeFilter(["^/etc/rc.*", "^/etc/hostname"]) ef2 = ExcludeFilter("/my/path/exclude.lst") Where exclude.lst contains: ^/etc/rc.* ^/etc/hostname
source code
 
_load_patterns_from_file(self, filename) source code
 
_match(self, regex, path) source code
bool
__call__(self, path)
Returns: Return True if path has been matched and should be excluded, False otherwise.
source code
Method Details [hide private]

__init__(self, arg_lst)
(Constructor)

source code 

Examples:
  ef1 = ExcludeFilter(["^/etc/rc.*", "^/etc/hostname"])
  ef2 = ExcludeFilter("/my/path/exclude.lst")
  Where exclude.lst contains:
  ^/etc/rc.*
  ^/etc/hostname

@param arg_lst: is either a list of patterns or a filename from which
                patterns will be loaded.
@type arg_lst: list of str or str

__call__(self, path)
(Call operator)

source code 
Parameters:
  • path (str) - Path to match against provided regexps.
Returns: bool
Return True if path has been matched and should be excluded, False otherwise.

pyinotify/python3/docstrings/pyinotify.UnsupportedLibcVersionError-class.html0000644000175000017500000002635311402071465027452 0ustar ookoiookoi pyinotify.UnsupportedLibcVersionError
Module pyinotify :: Class UnsupportedLibcVersionError
[hide private]
[frames] | no frames]

Class UnsupportedLibcVersionError

source code


Raised on unsupported libc versions.

Instance Methods [hide private]
 
__init__(self, version)
x.__init__(...) initializes x; see x.__class__.__doc__ for signature
source code

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__, __unicode__

Inherited from object: __format__, __hash__, __reduce_ex__, __sizeof__, __subclasshook__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

Method Details [hide private]

__init__(self, version)
(Constructor)

source code 

x.__init__(...) initializes x; see x.__class__.__doc__ for signature

Parameters:
  • version (string) - Current Libc version
Overrides: object.__init__

pyinotify/python3/docstrings/uml_class_diagram_for_pyinotif_15.gif0000644000175000017500000000753711402071465025162 0ustar ookoiookoiGIF87aLBDĢFD$"$Ćf\lVTܲ<2,nl vt䴒\NLԦ|\FDD:4, 4&$fd$zl*,nl亼ԮTJDt^\̞L:4TB<̪d~|Ԧ ̢VT,"jd䲤D2,vldND|dJDĞ <.,|b\TF<  4*$,~|nd쾼|L><̢,&$̒z|dRTĄRTj\lZ\ܶ<24~tԪ|D:< $~t:<侼ܮtbd̞L:nTƒƙvPHu%a7` !!V]](bn<$ѯ׉t:1]s#6՚q5ˆ^7FS'#8 ڇtbQpOz3}zF4ږVow8C.۸y$^e#/7ּ AZ:=1/?> ,}L. o_@pPya,H>$t:<c(P1\p{x@ްrE @Qyy(b0vGBR/ᇡ+b !"p=48 X dHŐb` cTũ`/(#X4plt͈9-vc3<1`~c)]:$"7E>$8X̤&7Nz (;Ɂq`L*WN#,gIOA-w^>E\ IbL2f:)liLPӼ6Mn.0Ir3 n4a g?Ir3,B9PX`D$@%fяf@ ]PC - #iSJk#⬩NJC` @Q B2 İlA $B kAXӲ&ɩYת̧a+-!҉v!~ Rd$C!HC` `i\RQc'KVCq=,;/G5@Ȁ250m,e ٌHvl;LF "x'W?ȴ0L3d,n N&tfbJ6" x'T#a=aJ`QBz;Ҵ}u:1J8C$ Ҩ s 0,HX[P^DGL[$NCl⊠x۴&g4αub4&L"HN&;PC RͶW=bQ7l0B+o)|ZuY0Xc!ަ<S0}.i*yV{y1dkA^q^rۜ.gU53R)ڤ0 ,'Mb̋ft%a fA`oJB-D,3wC.!ɑ 6*]fK_݈N %Nq pyinotify.Event
Module pyinotify :: Class Event
[hide private]
[frames] | no frames]

Class Event

source code


This class contains all the useful informations about the observed event. However, the presence of each field is not guaranteed and depends on the type of event. In effect, some fields are irrelevant for some kind of event (for example 'cookie' is meaningless for IN_CREATE whereas it is mandatory for IN_MOVE_TO).

The possible fields are:

  • wd (int): Watch Descriptor.
  • mask (int): Mask.
  • maskname (str): Readable event name.
  • path (str): path of the file or directory being watched.
  • name (str): Basename of the file or directory against which the event was raised in case where the watched directory is the parent directory. None if the event was raised on the watched item itself. This field is always provided even if the string is ''.
  • pathname (str): Concatenation of 'path' and 'name'.
  • src_pathname (str): Only present for IN_MOVED_TO events and only in the case where IN_MOVED_FROM events are watched too. Holds the source pathname from where pathname was moved from.
  • cookie (int): Cookie.
  • dir (bool): True if the event was raised against a directory.
Instance Methods [hide private]
 
__init__(self, raw)
Concretely, this is the raw event plus inferred infos.
source code

Inherited from _Event: __repr__

Method Details [hide private]

__init__(self, raw)
(Constructor)

source code 

Concretely, this is the raw event plus inferred infos.

Parameters:
  • dict_ - Set of attributes.
Overrides: _Event.__init__

pyinotify/python3/docstrings/pyinotify._ProcessEvent-class.html0000644000175000017500000002032211402071465024515 0ustar ookoiookoi pyinotify._ProcessEvent
Module pyinotify :: Class _ProcessEvent
[hide private]
[frames] | no frames]

Class _ProcessEvent

source code

Abstract processing event class.

Instance Methods [hide private]
bool
__call__(self, event)
To behave like a functor the object must be callable.
source code
 
__repr__(self) source code
Method Details [hide private]

__call__(self, event)
(Call operator)

source code 

To behave like a functor the object must be callable. This method is a dispatch method. Its lookup order is:

  1. process_MASKNAME method
  2. process_FAMILY_NAME method
  3. otherwise calls process_default
Parameters:
  • event (Event object) - Event to be processed.
Returns: bool
By convention when used from the ProcessEvent class:
  • Returning False or None (default value) means keep on executing next chained functors (see chain.py example).
  • Returning True instead means do not execute next processing functions.
Raises:

pyinotify/python3/docstrings/pyinotify._Event-class.html0000644000175000017500000002013011402071465023153 0ustar ookoiookoi pyinotify._Event
Module pyinotify :: Class _Event
[hide private]
[frames] | no frames]

Class _Event

source code

Event structure, represent events raised by the system. This is the base class and should be subclassed.

Instance Methods [hide private]
 
__init__(self, dict_)
Attach attributes (contained in dict_) to self.
source code
str
__repr__(self)
Returns: Generic event string representation.
source code
Method Details [hide private]

__init__(self, dict_)
(Constructor)

source code 

Attach attributes (contained in dict_) to self.

Parameters:
  • dict_ (dictionary) - Set of attributes.

__repr__(self)
(Representation operator)

source code 
Returns: str
Generic event string representation.

pyinotify/python3/docstrings/toc.html0000644000175000017500000000235711402071464017376 0ustar ookoiookoi Table of Contents

Table of Contents


Everything

Modules

pyinotify

[hide private] pyinotify/python3/docstrings/uml_class_diagram_for_pyinotif_14.gif0000644000175000017500000001756411402071465025162 0ustar ookoiookoiGIF87a|LBDĤBDĆ$"$d^\Ԧjdbd|dJDT., <2,ܶĖvt|^TĞTJDܪtvl$j\RT4&$&$D:4ԢԮdRTĞ \F<̦rd64tZTnd쾼|fdԌ~tTB< Ԧ<24TJL$jdD:< \FD~|TBD\JLL:<,"$vt̞TFDdNL|b\zt4*,t^\lVT,W H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳC JѣH*]ʴӧPzڤիXjʵׯ`ÊK$SZ˶۷p c ݻCs-AvZ~W0!/h;bPkq+%*#Nlrdi97,.i J".kMOk!c#B4r:haB}i|"TҬM-WXY4wNmܫ}#W\UuG (ZnA|)(Mւ >xs-x_e_`xDMh@C0ʸ!UR_ Hd'j-jA tJe5ni_k]d&il%mBlG%ekY斃&Ii`hD iHPm':f+$^~ D`'몭 _om):[h]Wn[u([WXt1*JJmi,kQ1/mz,J mY-']fQ!t-k,jH 0*B#(/+@mܱ ,[|p 7!1>e&Q FA׈DVL.7I%qFP+IH\Qd^-C|G'tA-5Vct[sF k'dQ#2ywh_礗n][KTǮG#\/o|{`7ӈH4B+kpZ6ӵDqm5zϞ;SBƢ^^ԍcD@:iU \zƤU}_]dֶG׺xҳ6r4_ X> 5 [ÙD/Vebcf`X3cHڅfL#SI~4 --E?@1x@0 U3Pɰ)@}"G~ `Ks6hCF5t %lp S*6' h _*z٥Ůc0c3K &cayضa(fV+ۗD6 mPӼEm27ֲ %f(// X`4KЏ}tgnռͭQjVֹoҍ`E,&Rb> 4>7}iV-^M2̎ ׄhEBX Aox;F}o 񬻤iOz +S6riw- ,uײ54}BRxVq,23PMlQtznq%S#-rs1vyFd2s5F}>g8G>:G{kmcotM5>CEzv~dSttQgap 4u-8gGu.N9P3T8VhmgYo8wYքgW9y8{7JօZCxb~aixrKQC!M#jaysYkyL؆v1z$bMv$'zX${qQlDmNn(]'/{XVdB}BTCwnG-h~f\~%on!Q)oъ!hhsRP$0 /gg(ƀeWd7-VSJ4oqsHu9P4'%>'B,((0@35hS긎1}ItTu:Bȁ!~Hx Duǒ0?8-yI6<2Vv!YUvE9e:tIN)?VKUoQK[L0kW\ǥ$hz{e]M9Ȧ])ƊHt}x~}~!.Dn5Ռg'~ &>lAqaW3R1v<7#S*rvc<7+F )GGFY)Ld$)OFF;ɓOU Nٝ1Y99~QBY:BNtVT9JLSI9QSRd[W9'ɱ_Y4Ɵ)f$V'{ Zvl .^T rHIJc/vИ' Y37SvQrМt[|tdY/)醆FztH#Guՙ l;-rzkZF}p|* Dwj8f-* 9SʥVkwiv]KE~!ʎ!\6kkrIUi(ɦ㥙[ZBফHɘ}ιʘFQoiأՑpۈaHp-h!6b%ڑ8caqAӉd;wJxj [+wgJf&wY}ѨSjw^?ѩc5;*t!\D䖱zq걵 (]$J"}y^ӗkHv:E$mڀ_{ϊݲ.Bo$"o9Uȍ"u*ݚ##23ɯI8qqrX#K)sBtv$m<8\bj=#)ui@*k; ۝˓~б]u$J(Uٲ/1[UY[~AytQ{OQNORoqѵ˽onעuV;Djۍߺp!.{k7vl!л =7gzy+Vl'<) +̒-|*+- K:3˷99;ܼp񼣋f6ux#4W[:j?{A Ď+R%5x1Rh\Lۯ[LB[Т/]{`Ş Z9_^חxpѶmtL~[{m{}&33S`+mx7ocQ5{z@ |Ĩ*tiָܸӺMV° М/9.ID<\l>A@ \|,<]>cP_ 0]5T 1T U&UF Pp0}&P 01# 0L`B(`0I X0L$ @=` M]1Qm\IQGdLPV` je 0t]5 x]S0yׂ==؃]؆׈y، ׎eْՔ]V}٘ԚCٞӠ1=ڤڪڬڮڰۯ s-۶}۸}BpA%^P:k9CfݷŭpܤSv9HV9 ح8݂XU<@ aCg潕ѳe4m}ܝzJIRz! ,L=@dmn!aѤN/N%nݗ'S(-N`$jZ| -q!^܍}+cfCe{b[ENkM~*;N܍-n4/8>80^cV>-ε3ݢi ɇ6y %3%Ս^N0D,q3s.<3nh.mOOqJZ5S )*˝Q778\CkynܓcԣٍF01нz뺾uV./Ai-nˎ.۸ގ;>^.N>p12a,7m.&KD  }@ {?=faAOFK\śG 06yja Ap 3p{ ]f Jip޷(E[DEZK` } r468F}n*-nR^pb8l^`wZrL) ,[%rpr@3AS<0ʇs&n~o",>+_ϒ.ޝ@tO/>uR^S@@ (JB >Q"A-^ĘQF7* H%I RJ-]t0męSN Qh2DOEEЊSz$UԈ@¢) U]TҪQv|EV-BF)j\^ߨZ(}U@*:ERUnX䔘4PeΝWe(0a+VM+R j֡ 8"[^ml}o%~\9˝Sm\zӭ~]{۽]C,^շwo~|jǟ_~G^ @D0?`0B 'B /0C 7B%G$`D4@cD 0QDFbADDG @$RD'Q= dhGK@Fd+/$sD#L_FT 5FE14)1,L>̩1I.Ԑ$ lAKr.r?P!D0hADDb0J/TS>v1UW1t+\eKM)FS1X@&ca@HA"4LCZE%4$ QG< .PU.$sCb\s5MFx\EE<.5-jas .!&$Z0S%aZTaD9D.DIsS9!0VeeYDTd+%TD:: YJMA 5t.\΁ [$Q#F kmc%\y>huҕE%nT[SjjN_pїa.hY+'\)zKEeR\ss`F$R'$e*UhʜR +q֥-3 + 7+ūp %$K$JR0Wgv+T0 0N$d&c?b٬jeM%x0N_Kf &f1h!VYo9#&er; Wre.w_st=hB};pyinotify/python3/docstrings/uml_class_diagram_for_pyinotif_3.gif0000644000175000017500000000535411402071464025071 0ustar ookoiookoiGIF87a|LBDĊBD$"$Ԧd^\jd|<2, ܶbdT.,dJDĚvtܪ|b\\JDD:<Ԣt4&$$ĢzlԮ \FD̦&$j\TB<,$~t ̪24TBDZ\><䲤rdlVT rl侼̢tbdD64ԪNLnľL:<,"$vtTFD4*,̞, H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜIfA8sɳϟ@ b&EA*]ʴӧPJ@Q ʵׯ` KkhZ55[ov-ֶt[v/_vcf֯U!0lrV{U0̀y B P 7dF5 :sgkkd y=#hJɒ3O=̻z52\}?GWG[.nG []PcS0KЍN[U[MARV!sg RjHX"vH"K [8Ԍ4hP <@)Di֋LJ-6)%gKNiWORfҖ\2%J`'ݨl#V;)tIdUi%&g|䧙yV+Bi⟂@P 5z2@ĉy:=dfEitèB^=wƚk)q J[h2 qXjVXBjypYb<]{$\mۘz&XeF\Qqd/oz V]]yp| eZ D_j)˕JW 8aV܃ڋ#g!}y1hQPuW33a:g猅 F@F .MJҠtϧ=# a.N4$7 Wn! wFn pM(P%Ǿ/WC&FGA0D'PCH@P@-aS!2 H?=c4B</>AKplL`T0@ Am '⮄& Sh&.|Lb(Cа.!Y H"HL.Pb=6Y'ŝPqzH2b FDpc!8q#נ>qu(2wdGFDcă m^׾թmňTJu]]Btic] نHlc#QUqF?!T%#>VSk"ia.-Pvlg.qqM XBQ= z`D@IK2%c>sjCI4D-Qր( jp= z$K2@/*QKLip<¸-\aal3_̷~N ;pyinotify/python3/docstrings/pyinotify.Color-class.html0000644000175000017500000002733111402071464023022 0ustar ookoiookoi pyinotify.Color
Module pyinotify :: Class Color
[hide private]
[frames] | no frames]

Class Color

source code

Internal class. Provide fancy colors used by string representations.

Static Methods [hide private]
 
punctuation(s)
Punctuation color.
source code
 
field_value(s)
Field value color.
source code
 
field_name(s)
Field name color.
source code
 
class_name(s)
Class name color.
source code
 
simple(s, color) source code
Class Variables [hide private]
  normal = "\033[0m"
  black = "\033[30m"
  red = "\033[31m"
  green = "\033[32m"
  yellow = "\033[33m"
  blue = "\033[34m"
  purple = "\033[35m"
  cyan = "\033[36m"
  bold = "\033[1m"
  uline = "\033[4m"
  blink = "\033[5m"
  invert = "\033[7m"
pyinotify/python3/docstrings/toc-everything.html0000644000175000017500000001144611402071464021557 0ustar ookoiookoi Everything

Everything


All Classes

pyinotify.AsyncNotifier
pyinotify.ChainIfTrue
pyinotify.Color
pyinotify.Event
pyinotify.EventsCodes
pyinotify.ExcludeFilter
pyinotify.Notifier
pyinotify.NotifierError
pyinotify.PrintAllEvents
pyinotify.ProcessEvent
pyinotify.ProcessEventError
pyinotify.PyinotifyError
pyinotify.PyinotifyLogger
pyinotify.Stats
pyinotify.SysCtlINotify
pyinotify.ThreadedNotifier
pyinotify.UnsupportedLibcVersionError
pyinotify.UnsupportedPythonVersionError
pyinotify.Watch
pyinotify.WatchManager
pyinotify.WatchManagerError

All Functions

pyinotify.STRERRNO
pyinotify.command_line
pyinotify.compatibility_mode
pyinotify.logger_init

All Variables

pyinotify.ALL_EVENTS
pyinotify.COMPATIBILITY_MODE
pyinotify.LIBC
pyinotify.LIBC_VERSION
pyinotify.__author__
pyinotify.log

[hide private] pyinotify/python3/docstrings/pyinotify.NotifierError-class.html0000644000175000017500000002612211402071464024532 0ustar ookoiookoi pyinotify.NotifierError
Module pyinotify :: Class NotifierError
[hide private]
[frames] | no frames]

Class NotifierError

source code


Notifier Exception. Raised on Notifier error.

Instance Methods [hide private]
 
__init__(self, err)
x.__init__(...) initializes x; see x.__class__.__doc__ for signature
source code

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__, __unicode__

Inherited from object: __format__, __hash__, __reduce_ex__, __sizeof__, __subclasshook__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

Method Details [hide private]

__init__(self, err)
(Constructor)

source code 

x.__init__(...) initializes x; see x.__class__.__doc__ for signature

Parameters:
  • err (string) - Exception string's description.
Overrides: object.__init__

pyinotify/python3/docstrings/pyinotify.Watch-class.html0000644000175000017500000002205711402071465023013 0ustar ookoiookoi pyinotify.Watch
Module pyinotify :: Class Watch
[hide private]
[frames] | no frames]

Class Watch

source code

Represent a watch, i.e. a file or directory being watched.

Instance Methods [hide private]
 
__init__(self, wd, path, mask, proc_fun, auto_add, exclude_filter)
Initializations.
source code
str
__repr__(self)
Returns: String representation.
source code
Method Details [hide private]

__init__(self, wd, path, mask, proc_fun, auto_add, exclude_filter)
(Constructor)

source code 

Initializations.

Parameters:
  • wd (int) - Watch descriptor.
  • path (str) - Path of the file or directory being watched.
  • mask (int) - Mask.
  • proc_fun () - Processing callable object.
  • auto_add (bool) - Automatically add watches on new directories.
  • exclude_filter (callable object) - Boolean function, used to exclude new directories from being automatically watched. See WatchManager.__init__

__repr__(self)
(Representation operator)

source code 
Returns: str
String representation.

pyinotify/ACKS0000644000175000017500000000221311402071040012561 0ustar ookoiookoiAcknowledgements ---------------- Andrey Rahmatullin wrar@altlinux.org Colin Blackburn colin@ximenes.org.uk cruxic@gmail.com Darryl Dixon darryl.dixon@winterhouseconsulting.com Doug Fort dougfort@dougfort.com Facundo Batista facundo@canonical.com forest@alittletooquiet.net Frédéric Pica frederic.pica@gmail.com Guido Trotter ultrotter@quaqua.net Guillermo Gonzalez guillermo.gonzalez@canonical.com Hans Ulrich Niedermann debian@n-dimensional.de Henri Tuhola John Feuerstein john@feurix.com Jonathan Ballet jonathan.ballet@securactive.net knurxs@gmx.de Linda Octalina linda_octa@yahoo.com Mark Williamson mark.williamson@cl.cam.ac.uk Matt Brown deadguysfrom@gmail.com Matteo Lanza matteo.lanza@gmail.com Mattias Wadman mattias.wadman@gmail.com Matthew Webber Matthew.Webber@diamond.ac.uk Mikhail Gusarov dottedmag@dottedmag.net Mohamed Lrhazi lrhazi@gmail.com prologic@shortcircuit.net.au Radoslaw Stachowiak rstachowiak@gmail.com Robin Wittler r.wittler@buetow.org, robin.wittler@credativ.de stromnov@gmail.com Terje Røsten terje.rosten@ntnu.no Thomas Kiley tkiley@cs.uml.edu Will Muldrew will.muldrew@gmail.com And every anonymous or forgotten contributor pyinotify/README0000644000175000017500000000151311402071040012777 0ustar ookoiookoi==== Pyinotify ==== License: MIT License Project URL: http://trac.dbzteam.org/pyinotify/ ==== Dependencies ==== - Linux >= 2.6.13 - Python (CPython) >= 2.4 - Libc >= 2.4 - ctypes (already included with Python >= 2.5) - Epydoc (optional, needed to generate docstrings) ==== Install ==== -> Install from the distributed tarball # Choose your Python interpreter: either python, python2.6, python3.0,.. # Replacing XXX accordingly with your previous choice type: $ sudo pythonXXX setup.py install -> OR install with "Easy Install" (currently seems to work only for Python2) $ wget http://peak.telecommunity.com/dist/ez_setup.py $ sudo python ez_setup.py $ sudo easy_install pyinotify ==== Watch a directory ==== Install pyinotify and run this command from a shell: $ python -m pyinotify -v /my-dir-to-watch pyinotify/COPYING0000644000175000017500000000206711402071040013157 0ustar ookoiookoiCopyright (c) 2010 Sebastien Martini Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. pyinotify/python2/0000755000175000017500000000000011402071160013525 5ustar ookoiookoipyinotify/python2/examples/0000755000175000017500000000000011402071040015340 5ustar ookoiookoipyinotify/python2/examples/daemon.py0000644000175000017500000000306011402071040017154 0ustar ookoiookoi# Example: daemonize pyinotify's notifier. # # Requires Python >= 2.5 import functools import sys import pyinotify class Counter(object): """ Simple counter. """ def __init__(self): self.count = 0 def plusone(self): self.count += 1 def on_loop(notifier, counter): """ Dummy function called after each event loop, this method only ensures the child process eventually exits (after 5 iterations). """ if counter.count > 4: # Loops 5 times then exits. sys.stdout.write("Exit\n") notifier.stop() sys.exit(0) else: sys.stdout.write("Loop %d\n" % counter.count) counter.plusone() wm = pyinotify.WatchManager() notifier = pyinotify.Notifier(wm) wm.add_watch('/tmp', pyinotify.ALL_EVENTS) on_loop_func = functools.partial(on_loop, counter=Counter()) # Notifier instance spawns a new process when daemonize is set to True. This # child process' PID is written to /tmp/pyinotify.pid (it also automatically # deletes it when it exits normally). If no custom pid_file is provided it # would write it more traditionally under /var/run/. /tmp/stdout.txt is used # as stdout stream thus traces of events will be written in it, force_kill # means that if there is already an /tmp/pyinotify.pid with a corresponding # running process it will be killed first. callback is the above function # and will be called after each event loop. notifier.loop(daemonize=True, callback=on_loop_func, pid_file='/tmp/pyinotify.pid', force_kill=True, stdout='/tmp/stdout.txt') pyinotify/python2/examples/not_quiet.py0000644000175000017500000000150211402071040017717 0ustar ookoiookoi# Example: raise exceptions on errors. # # Overrides default behavior and raise exception on add_watch, update_watch # or rm_watch errors. import pyinotify wm = pyinotify.WatchManager() # default behavior, don't complain but keep trace of error in log and result r = wm.add_watch(['/tmp', '/tmp-do-not-exist'], pyinotify.ALL_EVENTS) print r # quiet=False raise exception try: wm.add_watch(['/tmp', '/tmp-do-not-exist'], pyinotify.ALL_EVENTS, quiet=False) except pyinotify.WatchManagerError, err: print err, err.wmd # quiet=False raise exception try: wm.update_watch(42, mask=0x42, quiet=False) except pyinotify.WatchManagerError, err: print err, err.wmd # quiet=False raise exception try: wm.rm_watch(42, quiet=False) except pyinotify.WatchManagerError, err: print err, err.wmd pyinotify/python2/examples/loop.py0000644000175000017500000000064611402071040016671 0ustar ookoiookoi# Example: loops monitoring events forever. # import pyinotify # Instanciate a new WatchManager (will be used to store watches). wm = pyinotify.WatchManager() # Associate this WatchManager with a Notifier (will be used to report and # process events). notifier = pyinotify.Notifier(wm) # Add a new watch on /tmp for ALL_EVENTS. wm.add_watch('/tmp', pyinotify.ALL_EVENTS) # Loop forever and handle events. notifier.loop() pyinotify/python2/examples/transient_file.py0000644000175000017500000000175111402071040020724 0ustar ookoiookoi# Example: monitors transient files. # # Run this code, then run transient_file.sh in another shell. import pyinotify class ProcessTransientFile(pyinotify.ProcessEvent): def process_IN_MODIFY(self, event): # We have explicitely registered for this kind of event. print '\t', event.pathname, ' -> written' def process_default(self, event): # Implicitely IN_CREATE and IN_DELATE are watched too. You can # ignore them and provide an empty process_default or you can # process them, either with process_default or their dedicated # method (process_IN_CREATE, process_IN_DELETE) which would # override process_default. print 'default: ', event.maskname wm = pyinotify.WatchManager() notifier = pyinotify.Notifier(wm) # In this case you must give the class object (ProcessTransientFile) # as last parameter not a class instance. wm.watch_transient_file('/tmp/test1234', pyinotify.IN_MODIFY, ProcessTransientFile) notifier.loop() pyinotify/python2/examples/stats.py0000644000175000017500000000141611402071040017052 0ustar ookoiookoi# Example: prints statistics. # import pyinotify class Identity(pyinotify.ProcessEvent): def process_default(self, event): # Does nothing, just to demonstrate how stuffs could trivially # be accomplished after having processed statistics. print 'Does nothing.' def on_loop(notifier): # notifier.proc_fun() is Identity's instance s_inst = notifier.proc_fun().nested_pevent() print repr(s_inst), '\n', s_inst, '\n' wm = pyinotify.WatchManager() # Stats is a subclass of ProcessEvent provided by pyinotify # for computing basics statistics. s = pyinotify.Stats() notifier = pyinotify.Notifier(wm, default_proc_fun=Identity(s), read_freq=5) wm.add_watch('/tmp/', pyinotify.ALL_EVENTS, rec=True, auto_add=True) notifier.loop(callback=on_loop) pyinotify/python2/examples/chain.py0000644000175000017500000000230011402071040016767 0ustar ookoiookoi# Example: monitors events and logs them into a log file. # import pyinotify class Log(pyinotify.ProcessEvent): def my_init(self, fileobj): """ Method automatically called from ProcessEvent.__init__(). Additional keyworded arguments passed to ProcessEvent.__init__() are then delegated to my_init(). This is the case for fileobj. """ self._fileobj = fileobj def process_default(self, event): self._fileobj.write(str(event) + '\n') self._fileobj.flush() class TrackModifications(pyinotify.ProcessEvent): def process_IN_MODIFY(self, event): print 'IN_MODIFY' class Empty(pyinotify.ProcessEvent): def my_init(self, msg): self._msg = msg def process_default(self, event): print self._msg # pyinotify.log.setLevel(10) fo = file('/var/log/pyinotify_log', 'w') try: wm = pyinotify.WatchManager() # It is important to pass named extra arguments like 'fileobj'. handler = Empty(TrackModifications(Log(fileobj=fo)), msg='Outer chained method') notifier = pyinotify.Notifier(wm, default_proc_fun=handler) wm.add_watch('/tmp', pyinotify.ALL_EVENTS) notifier.loop() finally: fo.close() pyinotify/python2/examples/exclude.py0000644000175000017500000000155211402071040017346 0ustar ookoiookoi# Example: exclude items from being monitored. # import os import pyinotify wm = pyinotify.WatchManager() notifier = pyinotify.Notifier(wm) ### Method 1: # Exclude patterns from file excl_file = os.path.join(os.getcwd(), 'exclude.lst') excl = pyinotify.ExcludeFilter(excl_file) # Add watches res = wm.add_watch(['/etc/hostname', '/etc/cups', '/etc/rc0.d'], pyinotify.ALL_EVENTS, rec=True, exclude_filter=excl) ### Method 2 (Equivalent) # Exclude patterns from list excl_lst = ['^/etc/apache[2]?/', '^/etc/rc.*', '^/etc/hostname', '^/etc/hosts', '^/etc/(fs|m)tab', '^/etc/cron\..*'] excl = pyinotify.ExcludeFilter(excl_lst) # Add watches res = wm.add_watch(['/etc/hostname', '/etc/cups', '/etc/rc0.d'], pyinotify.ALL_EVENTS, rec=True, exclude_filter=excl) #notifier.loop() pyinotify/python2/examples/tutorial_notifier.py0000644000175000017500000000106311402071040021454 0ustar ookoiookoi# Notifier example from tutorial # # See: http://trac.dbzteam.org/pyinotify/wiki/Tutorial # import pyinotify wm = pyinotify.WatchManager() # Watch Manager mask = pyinotify.IN_DELETE | pyinotify.IN_CREATE # watched events class EventHandler(pyinotify.ProcessEvent): def process_IN_CREATE(self, event): print "Creating:", event.pathname def process_IN_DELETE(self, event): print "Removing:", event.pathname handler = EventHandler() notifier = pyinotify.Notifier(wm, handler) wdd = wm.add_watch('/tmp', mask, rec=True) notifier.loop() pyinotify/python2/examples/tutorial_threadednotifier.py0000644000175000017500000000116011402071040023153 0ustar ookoiookoi# ThreadedNotifier example from tutorial # # See: http://trac.dbzteam.org/pyinotify/wiki/Tutorial # import pyinotify wm = pyinotify.WatchManager() # Watch Manager mask = pyinotify.IN_DELETE | pyinotify.IN_CREATE # watched events class EventHandler(pyinotify.ProcessEvent): def process_IN_CREATE(self, event): print "Creating:", event.pathname def process_IN_DELETE(self, event): print "Removing:", event.pathname #log.setLevel(10) notifier = pyinotify.ThreadedNotifier(wm, EventHandler()) notifier.start() wdd = wm.add_watch('/tmp', mask, rec=True) wm.rm_watch(wdd.values()) notifier.stop() pyinotify/python2/examples/stats_threaded.py0000644000175000017500000000252011402071040020707 0ustar ookoiookoi# Example: prints statistics (threaded version). # import time import pyinotify # Do the same thing than stats.py but with a ThreadedNotifier's # instance. # This example illustrates the use of this class but the recommanded # implementation is whom of stats.py class Identity(pyinotify.ProcessEvent): def process_default(self, event): # Does nothing, just to demonstrate how stuffs could be done # after having processed statistics. print 'Does nothing.' # Thread #1 wm1 = pyinotify.WatchManager() s1 = pyinotify.Stats() # Stats is a subclass of ProcessEvent notifier1 = pyinotify.ThreadedNotifier(wm1, default_proc_fun=Identity(s1)) notifier1.start() wm1.add_watch('/tmp/', pyinotify.ALL_EVENTS, rec=True, auto_add=True) # Thread #2 wm2 = pyinotify.WatchManager() s2 = pyinotify.Stats() # Stats is a subclass of ProcessEvent notifier2 = pyinotify.ThreadedNotifier(wm2, default_proc_fun=Identity(s2)) notifier2.start() wm2.add_watch('/var/log/', pyinotify.ALL_EVENTS, rec=False, auto_add=False) while True: try: print "Thread 1", repr(s1) print s1 print "Thread 2", repr(s2) print s2 print time.sleep(5) except KeyboardInterrupt: notifier1.stop() notifier2.stop() break except: notifier1.stop() notifier2.stop() raise pyinotify/python2/examples/coalesce.py0000644000175000017500000000363011402071040017472 0ustar ookoiookoi# Example: coalesce events. # import pyinotify # For instance when this example is run with this command: # cd /tmp && echo "test" > test && echo "test" >> test # # It will give the following result when notifier.coalesce_events(False) is called # (default behavior, same as if we had not called this method): # # # # # # # # # # And will give the following result when notifier.coalesce_events() is called: # # # # # wm = pyinotify.WatchManager() # Put an arbitrary large value (10 seconds) to aggregate together a larger # chunk of events. For instance if you repeat several times a given action # on the same file its events will be coalesced into a single event and only # one event of this type will be reported (for this period). notifier = pyinotify.Notifier(wm, read_freq=10) # Enable coalescing of events. notifier.coalesce_events() wm.add_watch('/tmp', pyinotify.ALL_EVENTS) notifier.loop() pyinotify/python2/examples/transient_file.sh0000755000175000017500000000020211402071040020677 0ustar ookoiookoi#!/bin/bash for a in 1 2 3 4 5 6 7 8 9 10 do touch /tmp/test1234; echo -ne "42" > /tmp/test1234; rm -f /tmp/test1234; done pyinotify/python2/examples/unicode.py0000644000175000017500000000065311402071040017344 0ustar ookoiookoi# -*- coding: utf-8 -*- import os import sys import pyinotify # create path #path = u'/tmp/test\u0444' path = '/tmp/testф' path = unicode(path, sys.getfilesystemencoding()) if not os.path.isdir(path): os.mkdir(path) pyinotify.log.setLevel(10) wm = pyinotify.WatchManager() notifier = pyinotify.Notifier(wm) wdd = wm.add_watch(path, pyinotify.IN_OPEN) wm.update_watch(wdd[path], pyinotify.ALL_EVENTS) notifier.loop() pyinotify/python2/examples/exclude.lst0000644000175000017500000000044411402071040017517 0ustar ookoiookoi# File associated to exclude.py # # List of patterns using regexps as defined into re standard module. # These regexps are matched against submitted paths with re.match(). # Put only one pattern by line. ^/etc/apache[2]?/ ^/etc/rc.* ^/etc/hostname ^/etc/hosts ^/etc/(fs|m)tab ^/etc/cron\..* pyinotify/python2/examples/tutorial_asyncnotifier.py0000644000175000017500000000107311402071040022513 0ustar ookoiookoi# AsyncNotifier example from tutorial # # See: http://trac.dbzteam.org/pyinotify/wiki/Tutorial # import asyncore import pyinotify wm = pyinotify.WatchManager() # Watch Manager mask = pyinotify.IN_DELETE | pyinotify.IN_CREATE # watched events class EventHandler(pyinotify.ProcessEvent): def process_IN_CREATE(self, event): print "Creating:", event.pathname def process_IN_DELETE(self, event): print "Removing:", event.pathname notifier = pyinotify.AsyncNotifier(wm, EventHandler()) wdd = wm.add_watch('/tmp', mask, rec=True) asyncore.loop() pyinotify/python2/examples/autocompile.py0000755000175000017500000000320411402071040020235 0ustar ookoiookoi#!/usr/bin/env python # # Usage: # ./autocompile.py path ext1,ext2,extn cmd # # Blocks monitoring |path| and its subdirectories for modifications on # files ending with suffix |extk|. Run |cmd| each time a modification # is detected. |cmd| is optional and defaults to 'make'. # # Example: # ./autocompile.py /my-latex-document-dir .tex,.bib "make pdf" # # Dependancies: # Linux, Python 2.6, Pyinotify # import subprocess import sys import pyinotify class OnWriteHandler(pyinotify.ProcessEvent): def my_init(self, cwd, extension, cmd): self.cwd = cwd self.extensions = extension.split(',') self.cmd = cmd def _run_cmd(self): print '==> Modification detected' subprocess.call(self.cmd.split(' '), cwd=self.cwd) def process_IN_MODIFY(self, event): if all(not event.pathname.endswith(ext) for ext in self.extensions): return self._run_cmd() def auto_compile(path, extension, cmd): wm = pyinotify.WatchManager() handler = OnWriteHandler(cwd=path, extension=extension, cmd=cmd) notifier = pyinotify.Notifier(wm, default_proc_fun=handler) wm.add_watch(path, pyinotify.ALL_EVENTS, rec=True, auto_add=True) print '==> Start monitoring %s (type c^c to exit)' % path notifier.loop() if __name__ == '__main__': if len(sys.argv) < 3: print >> sys.stderr, "Command line error: missing argument(s)." sys.exit(1) # Required arguments path = sys.argv[1] extension = sys.argv[2] # Optional argument cmd = 'make' if len(sys.argv) == 4: cmd = sys.argv[3] # Blocks monitoring auto_compile(path, extension, cmd) pyinotify/python2/Makefile0000644000175000017500000000037211402071040015164 0ustar ookoiookoiEPYDOC=epydoc DSTDOC=docstrings doc: clean-doc $(EPYDOC) --html --graph=all -v -o $(DSTDOC) pyinotify.py clean-doc: rm -rf $(DSTDOC) clean: clean-doc find . \( -name '*~' -or \ -name '*.pyc' -or \ -name '*.pyo' \) \ -print -exec rm {} \; pyinotify/python2/pyinotify.py0000755000175000017500000023506011402071040016137 0ustar ookoiookoi#!/usr/bin/env python # pyinotify.py - python interface to inotify # Copyright (c) 2010 Sebastien Martini # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. """ pyinotify @author: Sebastien Martini @license: MIT License @contact: seb@dbzteam.org """ class PyinotifyError(Exception): """Indicates exceptions raised by a Pyinotify class.""" pass class UnsupportedPythonVersionError(PyinotifyError): """ Raised on unsupported Python versions. """ def __init__(self, version): """ @param version: Current Python version @type version: string """ PyinotifyError.__init__(self, ('Python %s is unsupported, requires ' 'at least Python 2.4') % version) class UnsupportedLibcVersionError(PyinotifyError): """ Raised on unsupported libc versions. """ def __init__(self, version): """ @param version: Current Libc version @type version: string """ PyinotifyError.__init__(self, ('Libc %s is not supported, requires ' 'at least Libc 2.4') % version) # Check Python version import sys if sys.version < '2.4': raise UnsupportedPythonVersionError(sys.version) # Import directives import threading import os import select import struct import fcntl import errno import termios import array import logging import atexit from collections import deque from datetime import datetime, timedelta import time import fnmatch import re import ctypes import ctypes.util import asyncore import glob try: from functools import reduce except ImportError: pass # Will fail on Python 2.4 which has reduce() builtin anyway. __author__ = "seb@dbzteam.org (Sebastien Martini)" __version__ = "0.9.0" __metaclass__ = type # Use new-style classes by default # Compatibity mode: set to True to improve compatibility with # Pyinotify 0.7.1. Do not set this variable yourself, call the # function compatibility_mode() instead. COMPATIBILITY_MODE = False # Load libc LIBC = None STRERRNO = None if sys.version_info[0] >= 2 and sys.version_info[1] >= 6: LIBC = ctypes.CDLL(ctypes.util.find_library('c'), use_errno=True) def _strerrno(): code = ctypes.get_errno() return ' Errno=%s (%s)' % (os.strerror(code), errno.errorcode[code]) STRERRNO = _strerrno else: LIBC = ctypes.CDLL(ctypes.util.find_library('c')) STRERRNO = lambda : '' # The libc version > 2.4 check. # XXX: Maybe it is better to check if the libc has the needed functions inside? # Because there are inotify patches for libc 2.3.6. LIBC.gnu_get_libc_version.restype = ctypes.c_char_p LIBC_VERSION = LIBC.gnu_get_libc_version() if (int(LIBC_VERSION.split('.')[0]) < 2 or (int(LIBC_VERSION.split('.')[0]) == 2 and int(LIBC_VERSION.split('.')[1]) < 4)): raise UnsupportedLibcVersionError(LIBC_VERSION) class PyinotifyLogger(logging.Logger): """ Pyinotify logger used for logging unicode strings. """ def makeRecord(self, name, level, fn, lno, msg, args, exc_info, func=None, extra=None): rv = UnicodeLogRecord(name, level, fn, lno, msg, args, exc_info, func) if extra is not None: for key in extra: if (key in ["message", "asctime"]) or (key in rv.__dict__): raise KeyError("Attempt to overwrite %r in LogRecord" % key) rv.__dict__[key] = extra[key] return rv class UnicodeLogRecord(logging.LogRecord): def __init__(self, name, level, pathname, lineno, msg, args, exc_info, func=None): py_version = sys.version_info # func argument was added in Python 2.5, just ignore it otherwise. if py_version[0] >= 2 and py_version[1] >= 5: logging.LogRecord.__init__(self, name, level, pathname, lineno, msg, args, exc_info, func) else: logging.LogRecord.__init__(self, name, level, pathname, lineno, msg, args, exc_info) def getMessage(self): msg = self.msg if not isinstance(msg, (unicode, str)): try: msg = str(self.msg) except UnicodeError: pass if self.args: if isinstance(self.args, tuple): def str_to_unicode(s): """Return unicode string.""" if not isinstance(s, str): return s return unicode(s, sys.getfilesystemencoding()) args = tuple([str_to_unicode(m) for m in self.args]) else: args = self.args msg = msg % args if not isinstance(msg, unicode): msg = unicode(msg, sys.getfilesystemencoding()) return msg # Logging def logger_init(): """Initialize logger instance.""" logging.setLoggerClass(PyinotifyLogger) log = logging.getLogger("pyinotify") console_handler = logging.StreamHandler() console_handler.setFormatter( logging.Formatter("[Pyinotify %(levelname)s] %(message)s")) log.addHandler(console_handler) log.setLevel(20) return log log = logger_init() # inotify's variables class SysCtlINotify: """ Access (read, write) inotify's variables through sysctl. Usually it requires administrator rights to update them. Examples: - Read max_queued_events attribute: myvar = max_queued_events.value - Update max_queued_events attribute: max_queued_events.value = 42 """ inotify_attrs = {'max_user_instances': 1, 'max_user_watches': 2, 'max_queued_events': 3} def __init__(self, attrname): sino = ctypes.c_int * 3 self._attrname = attrname self._attr = sino(5, 20, SysCtlINotify.inotify_attrs[attrname]) def get_val(self): """ Gets attribute's value. @return: stored value. @rtype: int """ oldv = ctypes.c_int(0) size = ctypes.c_int(ctypes.sizeof(oldv)) LIBC.sysctl(self._attr, 3, ctypes.c_voidp(ctypes.addressof(oldv)), ctypes.addressof(size), None, 0) return oldv.value def set_val(self, nval): """ Sets new attribute's value. @param nval: replaces current value by nval. @type nval: int """ oldv = ctypes.c_int(0) sizeo = ctypes.c_int(ctypes.sizeof(oldv)) newv = ctypes.c_int(nval) sizen = ctypes.c_int(ctypes.sizeof(newv)) LIBC.sysctl(self._attr, 3, ctypes.c_voidp(ctypes.addressof(oldv)), ctypes.addressof(sizeo), ctypes.c_voidp(ctypes.addressof(newv)), ctypes.addressof(sizen)) value = property(get_val, set_val) def __repr__(self): return '<%s=%d>' % (self._attrname, self.get_val()) # Singleton instances # # read: myvar = max_queued_events.value # update: max_queued_events.value = 42 # for attrname in ('max_queued_events', 'max_user_instances', 'max_user_watches'): globals()[attrname] = SysCtlINotify(attrname) class EventsCodes: """ Set of codes corresponding to each kind of events. Some of these flags are used to communicate with inotify, whereas the others are sent to userspace by inotify notifying some events. @cvar IN_ACCESS: File was accessed. @type IN_ACCESS: int @cvar IN_MODIFY: File was modified. @type IN_MODIFY: int @cvar IN_ATTRIB: Metadata changed. @type IN_ATTRIB: int @cvar IN_CLOSE_WRITE: Writtable file was closed. @type IN_CLOSE_WRITE: int @cvar IN_CLOSE_NOWRITE: Unwrittable file closed. @type IN_CLOSE_NOWRITE: int @cvar IN_OPEN: File was opened. @type IN_OPEN: int @cvar IN_MOVED_FROM: File was moved from X. @type IN_MOVED_FROM: int @cvar IN_MOVED_TO: File was moved to Y. @type IN_MOVED_TO: int @cvar IN_CREATE: Subfile was created. @type IN_CREATE: int @cvar IN_DELETE: Subfile was deleted. @type IN_DELETE: int @cvar IN_DELETE_SELF: Self (watched item itself) was deleted. @type IN_DELETE_SELF: int @cvar IN_MOVE_SELF: Self (watched item itself) was moved. @type IN_MOVE_SELF: int @cvar IN_UNMOUNT: Backing fs was unmounted. @type IN_UNMOUNT: int @cvar IN_Q_OVERFLOW: Event queued overflowed. @type IN_Q_OVERFLOW: int @cvar IN_IGNORED: File was ignored. @type IN_IGNORED: int @cvar IN_ONLYDIR: only watch the path if it is a directory (new in kernel 2.6.15). @type IN_ONLYDIR: int @cvar IN_DONT_FOLLOW: don't follow a symlink (new in kernel 2.6.15). IN_ONLYDIR we can make sure that we don't watch the target of symlinks. @type IN_DONT_FOLLOW: int @cvar IN_MASK_ADD: add to the mask of an already existing watch (new in kernel 2.6.14). @type IN_MASK_ADD: int @cvar IN_ISDIR: Event occurred against dir. @type IN_ISDIR: int @cvar IN_ONESHOT: Only send event once. @type IN_ONESHOT: int @cvar ALL_EVENTS: Alias for considering all of the events. @type ALL_EVENTS: int """ # The idea here is 'configuration-as-code' - this way, we get our nice class # constants, but we also get nice human-friendly text mappings to do lookups # against as well, for free: FLAG_COLLECTIONS = {'OP_FLAGS': { 'IN_ACCESS' : 0x00000001, # File was accessed 'IN_MODIFY' : 0x00000002, # File was modified 'IN_ATTRIB' : 0x00000004, # Metadata changed 'IN_CLOSE_WRITE' : 0x00000008, # Writable file was closed 'IN_CLOSE_NOWRITE' : 0x00000010, # Unwritable file closed 'IN_OPEN' : 0x00000020, # File was opened 'IN_MOVED_FROM' : 0x00000040, # File was moved from X 'IN_MOVED_TO' : 0x00000080, # File was moved to Y 'IN_CREATE' : 0x00000100, # Subfile was created 'IN_DELETE' : 0x00000200, # Subfile was deleted 'IN_DELETE_SELF' : 0x00000400, # Self (watched item itself) # was deleted 'IN_MOVE_SELF' : 0x00000800, # Self (watched item itself) was moved }, 'EVENT_FLAGS': { 'IN_UNMOUNT' : 0x00002000, # Backing fs was unmounted 'IN_Q_OVERFLOW' : 0x00004000, # Event queued overflowed 'IN_IGNORED' : 0x00008000, # File was ignored }, 'SPECIAL_FLAGS': { 'IN_ONLYDIR' : 0x01000000, # only watch the path if it is a # directory 'IN_DONT_FOLLOW' : 0x02000000, # don't follow a symlink '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 }, } def maskname(mask): """ Returns the event name associated to mask. IN_ISDIR is appended to the result when appropriate. Note: only one event is returned, because only one event can be raised at a given time. @param mask: mask. @type mask: int @return: event name. @rtype: str """ ms = mask name = '%s' if mask & IN_ISDIR: ms = mask - IN_ISDIR name = '%s|IN_ISDIR' return name % EventsCodes.ALL_VALUES[ms] maskname = staticmethod(maskname) # So let's now turn the configuration into code EventsCodes.ALL_FLAGS = {} EventsCodes.ALL_VALUES = {} for flagc, valc in EventsCodes.FLAG_COLLECTIONS.items(): # Make the collections' members directly accessible through the # class dictionary setattr(EventsCodes, flagc, valc) # Collect all the flags under a common umbrella EventsCodes.ALL_FLAGS.update(valc) # Make the individual masks accessible as 'constants' at globals() scope # and masknames accessible by values. for name, val in valc.items(): globals()[name] = val EventsCodes.ALL_VALUES[val] = name # all 'normal' events ALL_EVENTS = reduce(lambda x, y: x | y, EventsCodes.OP_FLAGS.values()) EventsCodes.ALL_FLAGS['ALL_EVENTS'] = ALL_EVENTS EventsCodes.ALL_VALUES[ALL_EVENTS] = 'ALL_EVENTS' class _Event: """ Event structure, represent events raised by the system. This is the base class and should be subclassed. """ def __init__(self, dict_): """ Attach attributes (contained in dict_) to self. @param dict_: Set of attributes. @type dict_: dictionary """ for tpl in dict_.items(): setattr(self, *tpl) def __repr__(self): """ @return: Generic event string representation. @rtype: str """ s = '' for attr, value in sorted(self.__dict__.items(), key=lambda x: x[0]): if attr.startswith('_'): continue if attr == 'mask': value = hex(getattr(self, attr)) elif isinstance(value, basestring) and not value: value = "''" s += ' %s%s%s' % (Color.field_name(attr), Color.punctuation('='), Color.field_value(value)) s = '%s%s%s %s' % (Color.punctuation('<'), Color.class_name(self.__class__.__name__), s, Color.punctuation('>')) return s class _RawEvent(_Event): """ Raw event, it contains only the informations provided by the system. It doesn't infer anything. """ def __init__(self, wd, mask, cookie, name): """ @param wd: Watch Descriptor. @type wd: int @param mask: Bitmask of events. @type mask: int @param cookie: Cookie. @type cookie: int @param name: Basename of the file or directory against which the event was raised in case where the watched directory is the parent directory. None if the event was raised on the watched item itself. @type name: string or None """ # name: remove trailing '\0' _Event.__init__(self, {'wd': wd, 'mask': mask, 'cookie': cookie, 'name': name.rstrip('\0')}) log.debug(repr(self)) # Use this variable to cache the result of str(self) self._str = None def __str__(self): if self._str is None: self._str = '%s %s %s %s' % (str(self.wd), str(self.mask), str(self.cookie), self.name) return self._str class Event(_Event): """ This class contains all the useful informations about the observed event. However, the presence of each field is not guaranteed and depends on the type of event. In effect, some fields are irrelevant for some kind of event (for example 'cookie' is meaningless for IN_CREATE whereas it is mandatory for IN_MOVE_TO). The possible fields are: - wd (int): Watch Descriptor. - mask (int): Mask. - maskname (str): Readable event name. - path (str): path of the file or directory being watched. - name (str): Basename of the file or directory against which the event was raised in case where the watched directory is the parent directory. None if the event was raised on the watched item itself. This field is always provided even if the string is ''. - pathname (str): Concatenation of 'path' and 'name'. - src_pathname (str): Only present for IN_MOVED_TO events and only in the case where IN_MOVED_FROM events are watched too. Holds the source pathname from where pathname was moved from. - cookie (int): Cookie. - dir (bool): True if the event was raised against a directory. """ def __init__(self, raw): """ Concretely, this is the raw event plus inferred infos. """ _Event.__init__(self, raw) self.maskname = EventsCodes.maskname(self.mask) if COMPATIBILITY_MODE: self.event_name = self.maskname try: if self.name: self.pathname = os.path.abspath(os.path.join(self.path, self.name)) else: self.pathname = os.path.abspath(self.path) except AttributeError, err: # Usually it is not an error some events are perfectly valids # despite the lack of these attributes. log.debug(err) class ProcessEventError(PyinotifyError): """ ProcessEventError Exception. Raised on ProcessEvent error. """ def __init__(self, err): """ @param err: Exception error description. @type err: string """ PyinotifyError.__init__(self, err) class _ProcessEvent: """ Abstract processing event class. """ def __call__(self, event): """ To behave like a functor the object must be callable. This method is a dispatch method. Its lookup order is: 1. process_MASKNAME method 2. process_FAMILY_NAME method 3. otherwise calls process_default @param event: Event to be processed. @type event: Event object @return: By convention when used from the ProcessEvent class: - Returning False or None (default value) means keep on executing next chained functors (see chain.py example). - Returning True instead means do not execute next processing functions. @rtype: bool @raise ProcessEventError: Event object undispatchable, unknown event. """ stripped_mask = event.mask - (event.mask & IN_ISDIR) maskname = EventsCodes.ALL_VALUES.get(stripped_mask) if maskname is None: raise ProcessEventError("Unknown mask 0x%08x" % stripped_mask) # 1- look for process_MASKNAME meth = getattr(self, 'process_' + maskname, None) if meth is not None: return meth(event) # 2- look for process_FAMILY_NAME meth = getattr(self, 'process_IN_' + maskname.split('_')[1], None) if meth is not None: return meth(event) # 3- default call method process_default return self.process_default(event) def __repr__(self): return '<%s>' % self.__class__.__name__ class _SysProcessEvent(_ProcessEvent): """ There is three kind of processing according to each event: 1. special handling (deletion from internal container, bug, ...). 2. default treatment: which is applied to the majority of events. 3. IN_ISDIR is never sent alone, he is piggybacked with a standard event, he is not processed as the others events, instead, its value is captured and appropriately aggregated to dst event. """ def __init__(self, wm, notifier): """ @param wm: Watch Manager. @type wm: WatchManager instance @param notifier: Notifier. @type notifier: Notifier instance """ self._watch_manager = wm # watch manager self._notifier = notifier # notifier self._mv_cookie = {} # {cookie(int): (src_path(str), date), ...} self._mv = {} # {src_path(str): (dst_path(str), date), ...} def cleanup(self): """ Cleanup (delete) old (>1mn) records contained in self._mv_cookie and self._mv. """ date_cur_ = datetime.now() for seq in [self._mv_cookie, self._mv]: for k in seq.keys(): if (date_cur_ - seq[k][1]) > timedelta(minutes=1): log.debug('Cleanup: deleting entry %s', seq[k][0]) del seq[k] def process_IN_CREATE(self, raw_event): """ If the event affects a directory and the auto_add flag of the targetted watch is set to True, a new watch is added on this new directory, with the same attribute values than those of this watch. """ if raw_event.mask & IN_ISDIR: watch_ = self._watch_manager.get_watch(raw_event.wd) created_dir = os.path.join(watch_.path, raw_event.name) if watch_.auto_add and not watch_.exclude_filter(created_dir): addw = self._watch_manager.add_watch # The newly monitored directory inherits attributes from its # parent directory. addw_ret = addw(created_dir, watch_.mask, proc_fun=watch_.proc_fun, rec=False, auto_add=watch_.auto_add, exclude_filter=watch_.exclude_filter) # Trick to handle mkdir -p /t1/t2/t3 where t1 is watched and # t2 and t3 are created. # Since the directory is new, then everything inside it # must also be new. created_dir_wd = addw_ret.get(created_dir) if (created_dir_wd is not None) and created_dir_wd > 0: for name in os.listdir(created_dir): inner = os.path.join(created_dir, name) if (os.path.isdir(inner) and self._watch_manager.get_wd(inner) is None): # Generate (simulate) creation event for sub # directories. rawevent = _RawEvent(created_dir_wd, IN_CREATE | IN_ISDIR, 0, name) self._notifier.append_event(rawevent) return self.process_default(raw_event) def process_IN_MOVED_FROM(self, raw_event): """ Map the cookie with the source path (+ date for cleaning). """ watch_ = self._watch_manager.get_watch(raw_event.wd) path_ = watch_.path src_path = os.path.normpath(os.path.join(path_, raw_event.name)) self._mv_cookie[raw_event.cookie] = (src_path, datetime.now()) return self.process_default(raw_event, {'cookie': raw_event.cookie}) def process_IN_MOVED_TO(self, raw_event): """ Map the source path with the destination path (+ date for cleaning). """ watch_ = self._watch_manager.get_watch(raw_event.wd) path_ = watch_.path dst_path = os.path.normpath(os.path.join(path_, raw_event.name)) mv_ = self._mv_cookie.get(raw_event.cookie) to_append = {'cookie': raw_event.cookie} if mv_ is not None: self._mv[mv_[0]] = (dst_path, datetime.now()) # Let's assume that IN_MOVED_FROM event is always queued before # that its associated (they share a common cookie) IN_MOVED_TO # event is queued itself. It is then possible in that scenario # to provide as additional information to the IN_MOVED_TO event # the original pathname of the moved file/directory. to_append['src_pathname'] = mv_[0] elif (raw_event.mask & IN_ISDIR and watch_.auto_add and not watch_.exclude_filter(dst_path)): # We got a diretory that's "moved in" from an unknown source and # auto_add is enabled. Manually add watches to the inner subtrees. # The newly monitored directory inherits attributes from its # parent directory. self._watch_manager.add_watch(dst_path, watch_.mask, proc_fun=watch_.proc_fun, rec=True, auto_add=True, exclude_filter=watch_.exclude_filter) return self.process_default(raw_event, to_append) def process_IN_MOVE_SELF(self, raw_event): """ STATUS: the following bug has been fixed in recent kernels (FIXME: which version ?). Now it raises IN_DELETE_SELF instead. Old kernels were bugged, this event raised when the watched item were moved, so we had to update its path, but under some circumstances it was impossible: if its parent directory and its destination directory wasn't watched. The kernel (see include/linux/fsnotify.h) doesn't bring us enough informations like the destination path of moved items. """ watch_ = self._watch_manager.get_watch(raw_event.wd) src_path = watch_.path mv_ = self._mv.get(src_path) if mv_: dest_path = mv_[0] watch_.path = dest_path # add the separator to the source path to avoid overlapping # path issue when testing with startswith() src_path += os.path.sep src_path_len = len(src_path) # The next loop renames all watches with src_path as base path. # It seems that IN_MOVE_SELF does not provide IN_ISDIR information # therefore the next loop is iterated even if raw_event is a file. for w in self._watch_manager.watches.values(): if w.path.startswith(src_path): # Note that dest_path is a normalized path. w.path = os.path.join(dest_path, w.path[src_path_len:]) else: log.error("The pathname '%s' of this watch %s has probably changed " "and couldn't be updated, so it cannot be trusted " "anymore. To fix this error move directories/files only " "between watched parents directories, in this case e.g. " "put a watch on '%s'.", watch_.path, watch_, os.path.normpath(os.path.join(watch_.path, os.path.pardir))) if not watch_.path.endswith('-unknown-path'): watch_.path += '-unknown-path' return self.process_default(raw_event) def process_IN_Q_OVERFLOW(self, raw_event): """ Only signal an overflow, most of the common flags are irrelevant for this event (path, wd, name). """ return Event({'mask': raw_event.mask}) def process_IN_IGNORED(self, raw_event): """ The watch descriptor raised by this event is now ignored (forever), it can be safely deleted from the watch manager dictionary. After this event we can be sure that neither the event queue nor the system will raise an event associated to this wd again. """ event_ = self.process_default(raw_event) self._watch_manager.del_watch(raw_event.wd) return event_ def process_default(self, raw_event, to_append=None): """ Commons handling for the followings events: IN_ACCESS, IN_MODIFY, IN_ATTRIB, IN_CLOSE_WRITE, IN_CLOSE_NOWRITE, IN_OPEN, IN_DELETE, IN_DELETE_SELF, IN_UNMOUNT. """ watch_ = self._watch_manager.get_watch(raw_event.wd) if raw_event.mask & (IN_DELETE_SELF | IN_MOVE_SELF): # Unfornulately this information is not provided by the kernel dir_ = watch_.dir else: dir_ = bool(raw_event.mask & IN_ISDIR) dict_ = {'wd': raw_event.wd, 'mask': raw_event.mask, 'path': watch_.path, 'name': raw_event.name, 'dir': dir_} if COMPATIBILITY_MODE: dict_['is_dir'] = dir_ if to_append is not None: dict_.update(to_append) return Event(dict_) class ProcessEvent(_ProcessEvent): """ Process events objects, can be specialized via subclassing, thus its behavior can be overriden: Note: you should not override __init__ in your subclass instead define a my_init() method, this method will be called automatically from the constructor of this class with its optionals parameters. 1. Provide specialized individual methods, e.g. process_IN_DELETE for processing a precise type of event (e.g. IN_DELETE in this case). 2. Or/and provide methods for processing events by 'family', e.g. process_IN_CLOSE method will process both IN_CLOSE_WRITE and IN_CLOSE_NOWRITE events (if process_IN_CLOSE_WRITE and process_IN_CLOSE_NOWRITE aren't defined though). 3. Or/and override process_default for catching and processing all the remaining types of events. """ pevent = None def __init__(self, pevent=None, **kargs): """ Enable chaining of ProcessEvent instances. @param pevent: Optional callable object, will be called on event processing (before self). @type pevent: callable @param kargs: This constructor is implemented as a template method delegating its optionals keyworded arguments to the method my_init(). @type kargs: dict """ self.pevent = pevent self.my_init(**kargs) def my_init(self, **kargs): """ This method is called from ProcessEvent.__init__(). This method is empty here and must be redefined to be useful. In effect, if you need to specifically initialize your subclass' instance then you just have to override this method in your subclass. Then all the keyworded arguments passed to ProcessEvent.__init__() will be transmitted as parameters to this method. Beware you MUST pass keyword arguments though. @param kargs: optional delegated arguments from __init__(). @type kargs: dict """ pass def __call__(self, event): stop_chaining = False if self.pevent is not None: # By default methods return None so we set as guideline # that methods asking for stop chaining must explicitely # return non None or non False values, otherwise the default # behavior will be to accept chain call to the corresponding # local method. stop_chaining = self.pevent(event) if not stop_chaining: return _ProcessEvent.__call__(self, event) def nested_pevent(self): return self.pevent def process_IN_Q_OVERFLOW(self, event): """ By default this method only reports warning messages, you can overredide it by subclassing ProcessEvent and implement your own process_IN_Q_OVERFLOW method. The actions you can take on receiving this event is either to update the variable max_queued_events in order to handle more simultaneous events or to modify your code in order to accomplish a better filtering diminishing the number of raised events. Because this method is defined, IN_Q_OVERFLOW will never get transmitted as arguments to process_default calls. @param event: IN_Q_OVERFLOW event. @type event: dict """ log.warning('Event queue overflowed.') def process_default(self, event): """ Default processing event method. By default does nothing. Subclass ProcessEvent and redefine this method in order to modify its behavior. @param event: Event to be processed. Can be of any type of events but IN_Q_OVERFLOW events (see method process_IN_Q_OVERFLOW). @type event: Event instance """ pass class PrintAllEvents(ProcessEvent): """ Dummy class used to print events strings representations. For instance this class is used from command line to print all received events to stdout. """ def my_init(self, out=None): """ @param out: Where events will be written. @type out: Object providing a valid file object interface. """ if out is None: out = sys.stdout self._out = out def process_default(self, event): """ Writes event string representation to file object provided to my_init(). @param event: Event to be processed. Can be of any type of events but IN_Q_OVERFLOW events (see method process_IN_Q_OVERFLOW). @type event: Event instance """ self._out.write(repr(event)) self._out.write('\n') class ChainIfTrue(ProcessEvent): """ Makes conditional chaining depending on the result of the nested processing instance. """ def my_init(self, func): """ Method automatically called from base class constructor. """ self._func = func def process_default(self, event): return not self._func(event) class Stats(ProcessEvent): """ Compute and display trivial statistics about processed events. """ def my_init(self): """ Method automatically called from base class constructor. """ self._start_time = time.time() self._stats = {} self._stats_lock = threading.Lock() def process_default(self, event): """ Processes |event|. """ self._stats_lock.acquire() try: events = event.maskname.split('|') for event_name in events: count = self._stats.get(event_name, 0) self._stats[event_name] = count + 1 finally: self._stats_lock.release() def _stats_copy(self): self._stats_lock.acquire() try: return self._stats.copy() finally: self._stats_lock.release() def __repr__(self): stats = self._stats_copy() elapsed = int(time.time() - self._start_time) elapsed_str = '' if elapsed < 60: elapsed_str = str(elapsed) + 'sec' elif 60 <= elapsed < 3600: elapsed_str = '%dmn%dsec' % (elapsed / 60, elapsed % 60) elif 3600 <= elapsed < 86400: elapsed_str = '%dh%dmn' % (elapsed / 3600, (elapsed % 3600) / 60) elif elapsed >= 86400: elapsed_str = '%dd%dh' % (elapsed / 86400, (elapsed % 86400) / 3600) stats['ElapsedTime'] = elapsed_str l = [] for ev, value in sorted(stats.items(), key=lambda x: x[0]): l.append(' %s=%s' % (Color.field_name(ev), Color.field_value(value))) s = '<%s%s >' % (Color.class_name(self.__class__.__name__), ''.join(l)) return s def dump(self, filename): """ Dumps statistics to file |filename|. @param filename: pathname. @type filename: string """ file_obj = file(filename, 'wb') try: file_obj.write(str(self)) finally: file_obj.close() def __str__(self, scale=45): stats = self._stats_copy() if not stats: return '' m = max(stats.values()) unity = float(scale) / m fmt = '%%-26s%%-%ds%%s' % (len(Color.field_value('@' * scale)) + 1) def func(x): return fmt % (Color.field_name(x[0]), Color.field_value('@' * int(x[1] * unity)), Color.simple('%d' % x[1], 'yellow')) s = '\n'.join(map(func, sorted(stats.items(), key=lambda x: x[0]))) return s class NotifierError(PyinotifyError): """ Notifier Exception. Raised on Notifier error. """ def __init__(self, err): """ @param err: Exception string's description. @type err: string """ PyinotifyError.__init__(self, err) class Notifier: """ Read notifications, process events. """ def __init__(self, watch_manager, default_proc_fun=None, read_freq=0, threshold=0, timeout=None): """ Initialization. read_freq, threshold and timeout parameters are used when looping. @param watch_manager: Watch Manager. @type watch_manager: WatchManager instance @param default_proc_fun: Default processing method. If None, a new instance of PrintAllEvents will be assigned. @type default_proc_fun: instance of ProcessEvent @param read_freq: if read_freq == 0, events are read asap, if read_freq is > 0, this thread sleeps max(0, read_freq - timeout) seconds. But if timeout is None it may be different because poll is blocking waiting for something to read. @type read_freq: int @param threshold: File descriptor will be read only if the accumulated size to read becomes >= threshold. If != 0, you likely want to use it in combination with an appropriate value for read_freq because without that you would keep looping without really reading anything and that until the amount of events to read is >= threshold. At least with read_freq set you might sleep. @type threshold: int @param timeout: http://docs.python.org/lib/poll-objects.html#poll-objects @type timeout: int """ # Watch Manager instance self._watch_manager = watch_manager # File descriptor self._fd = self._watch_manager.get_fd() # Poll object and registration self._pollobj = select.poll() self._pollobj.register(self._fd, select.POLLIN) # This pipe is correctely initialized and used by ThreadedNotifier self._pipe = (-1, -1) # Event queue self._eventq = deque() # System processing functor, common to all events self._sys_proc_fun = _SysProcessEvent(self._watch_manager, self) # Default processing method self._default_proc_fun = default_proc_fun if default_proc_fun is None: self._default_proc_fun = PrintAllEvents() # Loop parameters self._read_freq = read_freq self._threshold = threshold self._timeout = timeout # Coalesce events option self._coalesce = False # set of str(raw_event), only used when coalesce option is True self._eventset = set() def append_event(self, event): """ Append a raw event to the event queue. @param event: An event. @type event: _RawEvent instance. """ self._eventq.append(event) def proc_fun(self): return self._default_proc_fun def coalesce_events(self, coalesce=True): """ Coalescing events. Events are usually processed by batchs, their size depend on various factors. Thus, before processing them, events received from inotify are aggregated in a fifo queue. If this coalescing option is enabled events are filtered based on their unicity, only unique events are enqueued, doublons are discarded. An event is unique when the combination of its fields (wd, mask, cookie, name) is unique among events of a same batch. After a batch of events is processed any events is accepted again. By default this option is disabled, you have to explictly call this function to turn it on. @param coalesce: Optional new coalescing value. True by default. @type coalesce: Bool """ self._coalesce = coalesce if not coalesce: self._eventset.clear() def check_events(self, timeout=None): """ Check for new events available to read, blocks up to timeout milliseconds. @param timeout: If specified it overrides the corresponding instance attribute _timeout. @type timeout: int @return: New events to read. @rtype: bool """ while True: try: # blocks up to 'timeout' milliseconds if timeout is None: timeout = self._timeout ret = self._pollobj.poll(timeout) except select.error, err: if err[0] == errno.EINTR: continue # interrupted, retry else: raise else: break if not ret or (self._pipe[0] == ret[0][0]): return False # only one fd is polled return ret[0][1] & select.POLLIN def read_events(self): """ Read events from device, build _RawEvents, and enqueue them. """ buf_ = array.array('i', [0]) # get event queue size if fcntl.ioctl(self._fd, termios.FIONREAD, buf_, 1) == -1: return queue_size = buf_[0] if queue_size < self._threshold: log.debug('(fd: %d) %d bytes available to read but threshold is ' 'fixed to %d bytes', self._fd, queue_size, self._threshold) return try: # Read content from file r = os.read(self._fd, queue_size) except Exception, msg: raise NotifierError(msg) log.debug('Event queue size: %d', queue_size) rsum = 0 # counter while rsum < queue_size: s_size = 16 # Retrieve wd, mask, cookie and fname_len wd, mask, cookie, fname_len = struct.unpack('iIII', r[rsum:rsum+s_size]) # Retrieve name fname, = struct.unpack('%ds' % fname_len, r[rsum + s_size:rsum + s_size + fname_len]) rawevent = _RawEvent(wd, mask, cookie, fname) if self._coalesce: # Only enqueue new (unique) events. raweventstr = str(rawevent) if raweventstr not in self._eventset: self._eventset.add(raweventstr) self._eventq.append(rawevent) else: self._eventq.append(rawevent) rsum += s_size + fname_len def process_events(self): """ Routine for processing events from queue by calling their associated proccessing method (an instance of ProcessEvent). It also does internal processings, to keep the system updated. """ while self._eventq: raw_event = self._eventq.popleft() # pop next event watch_ = self._watch_manager.get_watch(raw_event.wd) if watch_ is None: # Not really sure how we ended up here, nor how we should # handle these types of events and if it is appropriate to # completly skip them (like we are doing here). log.warning("Unable to retrieve Watch object associated to %s", repr(raw_event)) continue revent = self._sys_proc_fun(raw_event) # system processings if watch_ and watch_.proc_fun: watch_.proc_fun(revent) # user processings else: self._default_proc_fun(revent) self._sys_proc_fun.cleanup() # remove olds MOVED_* events records if self._coalesce: self._eventset.clear() def __daemonize(self, pid_file=None, force_kill=False, stdin=os.devnull, stdout=os.devnull, stderr=os.devnull): """ pid_file: file to which the pid will be written. force_kill: if True kill the process associated to pid_file. stdin, stdout, stderr: files associated to common streams. """ if pid_file is None: dirname = '/var/run/' basename = os.path.basename(sys.argv[0]) or 'pyinotify' pid_file = os.path.join(dirname, basename + '.pid') if os.path.exists(pid_file): fo = file(pid_file, 'rb') try: try: pid = int(fo.read()) except ValueError: pid = None if pid is not None: try: os.kill(pid, 0) except OSError, err: if err.errno == errno.ESRCH: log.debug(err) else: log.error(err) else: if not force_kill: s = 'There is already a pid file %s with pid %d' raise NotifierError(s % (pid_file, pid)) else: os.kill(pid, 9) finally: fo.close() def fork_daemon(): # Adapted from Chad J. Schroeder's recipe # @see http://code.activestate.com/recipes/278731/ pid = os.fork() if (pid == 0): # parent 2 os.setsid() pid = os.fork() if (pid == 0): # child os.chdir('/') os.umask(0) else: # parent 2 os._exit(0) else: # parent 1 os._exit(0) fd_inp = os.open(stdin, os.O_RDONLY) os.dup2(fd_inp, 0) fd_out = os.open(stdout, os.O_WRONLY|os.O_CREAT) os.dup2(fd_out, 1) fd_err = os.open(stderr, os.O_WRONLY|os.O_CREAT) os.dup2(fd_err, 2) # Detach task fork_daemon() # Write pid file_obj = file(pid_file, 'wb') try: file_obj.write(str(os.getpid()) + '\n') finally: file_obj.close() atexit.register(lambda : os.unlink(pid_file)) def _sleep(self, ref_time): # Only consider sleeping if read_freq is > 0 if self._read_freq > 0: cur_time = time.time() sleep_amount = self._read_freq - (cur_time - ref_time) if sleep_amount > 0: log.debug('Now sleeping %d seconds', sleep_amount) time.sleep(sleep_amount) def loop(self, callback=None, daemonize=False, **args): """ Events are read only one time every min(read_freq, timeout) seconds at best and only if the size to read is >= threshold. After this method returns it must not be called again for the same instance. @param callback: Functor called after each event processing iteration. Expects to receive the notifier object (self) as first parameter. If this function returns True the loop is immediately terminated otherwise the loop method keeps looping. @type callback: callable object or function @param daemonize: This thread is daemonized if set to True. @type daemonize: boolean @param args: Optional and relevant only if daemonize is True. Remaining keyworded arguments are directly passed to daemonize see __daemonize() method. @type args: various """ if daemonize: self.__daemonize(**args) # Read and process events forever while 1: try: self.process_events() if (callback is not None) and (callback(self) is True): break ref_time = time.time() # check_events is blocking if self.check_events(): self._sleep(ref_time) self.read_events() except KeyboardInterrupt: # Stop monitoring if sigint is caught (Control-C). log.debug('Pyinotify stops monitoring.') break # Close internals self.stop() def stop(self): """ Close inotify's instance (close its file descriptor). It destroys all existing watches, pending events,... This method is automatically called at the end of loop(). """ self._pollobj.unregister(self._fd) os.close(self._fd) class ThreadedNotifier(threading.Thread, Notifier): """ This notifier inherits from threading.Thread for instanciating a separate thread, and also inherits from Notifier, because it is a threaded notifier. Note that every functionality provided by this class is also provided through Notifier class. Moreover Notifier should be considered first because it is not threaded and could be easily daemonized. """ def __init__(self, watch_manager, default_proc_fun=None, read_freq=0, threshold=0, timeout=None): """ Initialization, initialize base classes. read_freq, threshold and timeout parameters are used when looping. @param watch_manager: Watch Manager. @type watch_manager: WatchManager instance @param default_proc_fun: Default processing method. See base class. @type default_proc_fun: instance of ProcessEvent @param read_freq: if read_freq == 0, events are read asap, if read_freq is > 0, this thread sleeps max(0, read_freq - timeout) seconds. @type read_freq: int @param threshold: File descriptor will be read only if the accumulated size to read becomes >= threshold. If != 0, you likely want to use it in combination with an appropriate value set for read_freq because without that you would keep looping without really reading anything and that until the amount of events to read is >= threshold. At least with read_freq you might sleep. @type threshold: int @param timeout: see http://docs.python.org/lib/poll-objects.html#poll-objects @type timeout: int """ # Init threading base class threading.Thread.__init__(self) # Stop condition self._stop_event = threading.Event() # Init Notifier base class Notifier.__init__(self, watch_manager, default_proc_fun, read_freq, threshold, timeout) # Create a new pipe used for thread termination self._pipe = os.pipe() self._pollobj.register(self._pipe[0], select.POLLIN) def stop(self): """ Stop notifier's loop. Stop notification. Join the thread. """ self._stop_event.set() os.write(self._pipe[1], 'stop') threading.Thread.join(self) Notifier.stop(self) self._pollobj.unregister(self._pipe[0]) os.close(self._pipe[0]) os.close(self._pipe[1]) def loop(self): """ Thread's main loop. Don't meant to be called by user directly. Call inherited start() method instead. Events are read only once time every min(read_freq, timeout) seconds at best and only if the size of events to read is >= threshold. """ # When the loop must be terminated .stop() is called, 'stop' # is written to pipe fd so poll() returns and .check_events() # returns False which make evaluate the While's stop condition # ._stop_event.isSet() wich put an end to the thread's execution. while not self._stop_event.isSet(): self.process_events() ref_time = time.time() if self.check_events(): self._sleep(ref_time) self.read_events() def run(self): """ Start thread's loop: read and process events until the method stop() is called. Never call this method directly, instead call the start() method inherited from threading.Thread, which then will call run() in its turn. """ self.loop() class AsyncNotifier(asyncore.file_dispatcher, Notifier): """ This notifier inherits from asyncore.file_dispatcher in order to be able to use pyinotify along with the asyncore framework. """ def __init__(self, watch_manager, default_proc_fun=None, read_freq=0, threshold=0, timeout=None, channel_map=None): """ Initializes the async notifier. The only additional parameter is 'channel_map' which is the optional asyncore private map. See Notifier class for the meaning of the others parameters. """ Notifier.__init__(self, watch_manager, default_proc_fun, read_freq, threshold, timeout) asyncore.file_dispatcher.__init__(self, self._fd, channel_map) def handle_read(self): """ When asyncore tells us we can read from the fd, we proceed processing events. This method can be overridden for handling a notification differently. """ self.read_events() self.process_events() class Watch: """ Represent a watch, i.e. a file or directory being watched. """ def __init__(self, wd, path, mask, proc_fun, auto_add, exclude_filter): """ Initializations. @param wd: Watch descriptor. @type wd: int @param path: Path of the file or directory being watched. @type path: str @param mask: Mask. @type mask: int @param proc_fun: Processing callable object. @type proc_fun: @param auto_add: Automatically add watches on new directories. @type auto_add: bool @param exclude_filter: Boolean function, used to exclude new directories from being automatically watched. See WatchManager.__init__ @type exclude_filter: callable object """ self.wd = wd self.path = path self.mask = mask self.proc_fun = proc_fun self.auto_add = auto_add self.exclude_filter = exclude_filter self.dir = os.path.isdir(self.path) def __repr__(self): """ @return: String representation. @rtype: str """ s = ' '.join(['%s%s%s' % (Color.field_name(attr), Color.punctuation('='), Color.field_value(getattr(self, attr))) \ for attr in self.__dict__ if not attr.startswith('_')]) s = '%s%s %s %s' % (Color.punctuation('<'), Color.class_name(self.__class__.__name__), s, Color.punctuation('>')) return s class ExcludeFilter: """ ExcludeFilter is an exclusion filter. """ def __init__(self, arg_lst): """ Examples: ef1 = ExcludeFilter(["^/etc/rc.*", "^/etc/hostname"]) ef2 = ExcludeFilter("/my/path/exclude.lst") Where exclude.lst contains: ^/etc/rc.* ^/etc/hostname @param arg_lst: is either a list of patterns or a filename from which patterns will be loaded. @type arg_lst: list of str or str """ if isinstance(arg_lst, str): lst = self._load_patterns_from_file(arg_lst) elif isinstance(arg_lst, list): lst = arg_lst else: raise TypeError self._lregex = [] for regex in lst: self._lregex.append(re.compile(regex, re.UNICODE)) def _load_patterns_from_file(self, filename): lst = [] file_obj = file(filename, 'r') try: for line in file_obj.readlines(): # Trim leading an trailing whitespaces pattern = line.strip() if not pattern or pattern.startswith('#'): continue lst.append(pattern) finally: file_obj.close() return lst def _match(self, regex, path): return regex.match(path) is not None def __call__(self, path): """ @param path: Path to match against provided regexps. @type path: str @return: Return True if path has been matched and should be excluded, False otherwise. @rtype: bool """ for regex in self._lregex: if self._match(regex, path): return True return False class WatchManagerError(Exception): """ WatchManager Exception. Raised on error encountered on watches operations. """ def __init__(self, msg, wmd): """ @param msg: Exception string's description. @type msg: string @param wmd: This dictionary contains the wd assigned to paths of the same call for which watches were successfully added. @type wmd: dict """ self.wmd = wmd Exception.__init__(self, msg) class WatchManager: """ Provide operations for watching files and directories. Its internal dictionary is used to reference watched items. When used inside threaded code, one must instanciate as many WatchManager instances as there are ThreadedNotifier instances. """ def __init__(self, exclude_filter=lambda path: False): """ Initialization: init inotify, init watch manager dictionary. Raise OSError if initialization fails. @param exclude_filter: boolean function, returns True if current path must be excluded from being watched. Convenient for providing a common exclusion filter for every call to add_watch. @type exclude_filter: callable object """ self._exclude_filter = exclude_filter self._wmd = {} # watch dict key: watch descriptor, value: watch self._fd = LIBC.inotify_init() # inotify's init, file descriptor if self._fd < 0: err = 'Cannot initialize new instance of inotify%s' % STRERRNO() raise OSError(err) def get_fd(self): """ Return assigned inotify's file descriptor. @return: File descriptor. @rtype: int """ return self._fd def get_watch(self, wd): """ Get watch from provided watch descriptor wd. @param wd: Watch descriptor. @type wd: int """ return self._wmd.get(wd) def del_watch(self, wd): """ Remove watch entry associated to watch descriptor wd. @param wd: Watch descriptor. @type wd: int """ try: del self._wmd[wd] except KeyError, err: log.error(str(err)) @property def watches(self): """ Get a reference on the internal watch manager dictionary. @return: Internal watch manager dictionary. @rtype: dict """ return self._wmd def __format_path(self, path): """ Format path to its internal (stored in watch manager) representation. """ # Unicode strings are converted to byte strings, it seems to be # required because LIBC.inotify_add_watch does not work well when # it receives an ctypes.create_unicode_buffer instance as argument. # Therefore even wd are indexed with bytes string and not with # unicode paths. if isinstance(path, unicode): path = path.encode(sys.getfilesystemencoding()) return os.path.normpath(path) def __add_watch(self, path, mask, proc_fun, auto_add, exclude_filter): """ Add a watch on path, build a Watch object and insert it in the watch manager dictionary. Return the wd value. """ byte_path = self.__format_path(path) wd_ = LIBC.inotify_add_watch(self._fd, ctypes.create_string_buffer(byte_path), mask) if wd_ < 0: return wd_ watch_ = Watch(wd=wd_, path=byte_path, mask=mask, proc_fun=proc_fun, auto_add=auto_add, exclude_filter=exclude_filter) self._wmd[wd_] = watch_ log.debug('New %s', watch_) return wd_ def __glob(self, path, do_glob): if do_glob: return glob.iglob(path) else: return [path] def add_watch(self, path, mask, proc_fun=None, rec=False, auto_add=False, do_glob=False, quiet=True, exclude_filter=None): """ Add watch(s) on the provided |path|(s) with associated |mask| flag value and optionally with a processing |proc_fun| function and recursive flag |rec| set to True. Ideally |path| components should not be unicode objects. Note that although unicode paths are accepted there are converted to byte strings before a watch is put on that path. The encoding used for converting the unicode object is given by sys.getfilesystemencoding(). If |path| si already watched it is ignored, but if it is called with option rec=True a watch is put on each one of its not-watched subdirectory. @param path: Path to watch, the path can either be a file or a directory. Also accepts a sequence (list) of paths. @type path: string or list of strings @param mask: Bitmask of events. @type mask: int @param proc_fun: Processing object. @type proc_fun: function or ProcessEvent instance or instance of one of its subclasses or callable object. @param rec: Recursively add watches from path on all its subdirectories, set to False by default (doesn't follows symlinks in any case). @type rec: bool @param auto_add: Automatically add watches on newly created directories in watched parent |path| directory. @type auto_add: bool @param do_glob: Do globbing on pathname (see standard globbing module for more informations). @type do_glob: bool @param quiet: if False raises a WatchManagerError exception on error. See example not_quiet.py. @type quiet: bool @param exclude_filter: predicate (boolean function), which returns True if the current path must be excluded from being watched. This argument has precedence over exclude_filter passed to the class' constructor. @type exclude_filter: callable object @return: dict of paths associated to watch descriptors. A wd value is positive if the watch was added sucessfully, otherwise the value is negative. If the path was invalid or was already watched it is not included into this returned dictionary. @rtype: dict of {str: int} """ ret_ = {} # return {path: wd, ...} if exclude_filter is None: exclude_filter = self._exclude_filter # normalize args as list elements for npath in self.__format_param(path): # unix pathname pattern expansion for apath in self.__glob(npath, do_glob): # recursively list subdirs according to rec param for rpath in self.__walk_rec(apath, rec): if self.get_wd(rpath) is not None: # We decide to ignore paths already inserted into # the watch manager. Need to be removed with rm_watch() # first. Or simply call update_watch() to update it. continue if not exclude_filter(rpath): wd = ret_[rpath] = self.__add_watch(rpath, mask, proc_fun, auto_add, exclude_filter) if wd < 0: err = 'add_watch: cannot watch %s WD=%d%s' err = err % (rpath, wd, STRERRNO()) if quiet: log.error(err) else: raise WatchManagerError(err, ret_) else: # Let's say -2 means 'explicitely excluded # from watching'. ret_[rpath] = -2 return ret_ def __get_sub_rec(self, lpath): """ Get every wd from self._wmd if its path is under the path of one (at least) of those in lpath. Doesn't follow symlinks. @param lpath: list of watch descriptor @type lpath: list of int @return: list of watch descriptor @rtype: list of int """ for d in lpath: root = self.get_path(d) if root is not None: # always keep root yield d else: # if invalid continue # nothing else to expect if not os.path.isdir(root): continue # normalization root = os.path.normpath(root) # recursion lend = len(root) for iwd in self._wmd.items(): cur = iwd[1].path pref = os.path.commonprefix([root, cur]) if root == os.sep or (len(pref) == lend and \ len(cur) > lend and \ cur[lend] == os.sep): yield iwd[1].wd def update_watch(self, wd, mask=None, proc_fun=None, rec=False, auto_add=False, quiet=True): """ Update existing watch descriptors |wd|. The |mask| value, the processing object |proc_fun|, the recursive param |rec| and the |auto_add| and |quiet| flags can all be updated. @param wd: Watch Descriptor to update. Also accepts a list of watch descriptors. @type wd: int or list of int @param mask: Optional new bitmask of events. @type mask: int @param proc_fun: Optional new processing function. @type proc_fun: function or ProcessEvent instance or instance of one of its subclasses or callable object. @param rec: Optionally adds watches recursively on all subdirectories contained into |wd| directory. @type rec: bool @param auto_add: Automatically adds watches on newly created directories in the watch's path corresponding to |wd|. @type auto_add: bool @param quiet: If False raises a WatchManagerError exception on error. See example not_quiet.py @type quiet: bool @return: dict of watch descriptors associated to booleans values. True if the corresponding wd has been successfully updated, False otherwise. @rtype: dict of {int: bool} """ lwd = self.__format_param(wd) if rec: lwd = self.__get_sub_rec(lwd) ret_ = {} # return {wd: bool, ...} for awd in lwd: apath = self.get_path(awd) if not apath or awd < 0: err = 'update_watch: invalid WD=%d' % awd if quiet: log.error(err) continue raise WatchManagerError(err, ret_) if mask: addw = LIBC.inotify_add_watch wd_ = addw(self._fd, ctypes.create_string_buffer(apath), mask) if wd_ < 0: ret_[awd] = False err = 'update_watch: cannot update %s WD=%d%s' err = err % (apath, wd_, STRERRNO()) if quiet: log.error(err) continue raise WatchManagerError(err, ret_) assert(awd == wd_) if proc_fun or auto_add: watch_ = self._wmd[awd] if proc_fun: watch_.proc_fun = proc_fun if auto_add: watch_.auto_add = auto_add ret_[awd] = True log.debug('Updated watch - %s', self._wmd[awd]) return ret_ def __format_param(self, param): """ @param param: Parameter. @type param: string or int @return: wrap param. @rtype: list of type(param) """ if isinstance(param, list): for p_ in param: yield p_ else: yield param def get_wd(self, path): """ Returns the watch descriptor associated to path. This method presents a prohibitive cost, always prefer to keep the WD returned by add_watch(). If the path is unknown it returns None. @param path: Path. @type path: str @return: WD or None. @rtype: int or None """ path = self.__format_path(path) for iwd in self._wmd.items(): if iwd[1].path == path: return iwd[0] def get_path(self, wd): """ Returns the path associated to WD, if WD is unknown it returns None. @param wd: Watch descriptor. @type wd: int @return: Path or None. @rtype: string or None """ watch_ = self._wmd.get(wd) if watch_ is not None: return watch_.path def __walk_rec(self, top, rec): """ Yields each subdirectories of top, doesn't follow symlinks. If rec is false, only yield top. @param top: root directory. @type top: string @param rec: recursive flag. @type rec: bool @return: path of one subdirectory. @rtype: string """ if not rec or os.path.islink(top) or not os.path.isdir(top): yield top else: for root, dirs, files in os.walk(top): yield root def rm_watch(self, wd, rec=False, quiet=True): """ Removes watch(s). @param wd: Watch Descriptor of the file or directory to unwatch. Also accepts a list of WDs. @type wd: int or list of int. @param rec: Recursively removes watches on every already watched subdirectories and subfiles. @type rec: bool @param quiet: If False raises a WatchManagerError exception on error. See example not_quiet.py @type quiet: bool @return: dict of watch descriptors associated to booleans values. True if the corresponding wd has been successfully removed, False otherwise. @rtype: dict of {int: bool} """ lwd = self.__format_param(wd) if rec: lwd = self.__get_sub_rec(lwd) ret_ = {} # return {wd: bool, ...} for awd in lwd: # remove watch wd_ = LIBC.inotify_rm_watch(self._fd, awd) if wd_ < 0: ret_[awd] = False err = 'rm_watch: cannot remove WD=%d%s' % (awd, STRERRNO()) if quiet: log.error(err) continue raise WatchManagerError(err, ret_) ret_[awd] = True log.debug('Watch WD=%d (%s) removed', awd, self.get_path(awd)) return ret_ def watch_transient_file(self, filename, mask, proc_class): """ Watch a transient file, which will be created and deleted frequently over time (e.g. pid file). @attention: Currently under the call to this function it is not possible to correctly watch the events triggered into the same base directory than the directory where is located this watched transient file. For instance it would be wrong to make these two successive calls: wm.watch_transient_file('/var/run/foo.pid', ...) and wm.add_watch('/var/run/', ...) @param filename: Filename. @type filename: string @param mask: Bitmask of events, should contain IN_CREATE and IN_DELETE. @type mask: int @param proc_class: ProcessEvent (or of one of its subclass), beware of accepting a ProcessEvent's instance as argument into __init__, see transient_file.py example for more details. @type proc_class: ProcessEvent's instance or of one of its subclasses. @return: Same as add_watch(). @rtype: Same as add_watch(). """ dirname = os.path.dirname(filename) if dirname == '': return {} # Maintains coherence with add_watch() basename = os.path.basename(filename) # Assuming we are watching at least for IN_CREATE and IN_DELETE mask |= IN_CREATE | IN_DELETE def cmp_name(event): if getattr(event, 'name') is None: return False return basename == event.name return self.add_watch(dirname, mask, proc_fun=proc_class(ChainIfTrue(func=cmp_name)), rec=False, auto_add=False, do_glob=False, exclude_filter=lambda path: False) class Color: """ Internal class. Provide fancy colors used by string representations. """ normal = "\033[0m" black = "\033[30m" red = "\033[31m" green = "\033[32m" yellow = "\033[33m" blue = "\033[34m" purple = "\033[35m" cyan = "\033[36m" bold = "\033[1m" uline = "\033[4m" blink = "\033[5m" invert = "\033[7m" @staticmethod def punctuation(s): """Punctuation color.""" return Color.normal + s + Color.normal @staticmethod def field_value(s): """Field value color.""" if not isinstance(s, basestring): s = str(s) return Color.purple + s + Color.normal @staticmethod def field_name(s): """Field name color.""" return Color.blue + s + Color.normal @staticmethod def class_name(s): """Class name color.""" return Color.red + Color.bold + s + Color.normal @staticmethod def simple(s, color): if not isinstance(s, basestring): s = str(s) try: color_attr = getattr(Color, color) except AttributeError: return s return color_attr + s + Color.normal def compatibility_mode(): """ Use this function to turn on the compatibility mode. The compatibility mode is used to improve compatibility with Pyinotify 0.7.1 (or older) programs. The compatibility mode provides additional variables 'is_dir', 'event_name', 'EventsCodes.IN_*' and 'EventsCodes.ALL_EVENTS' as Pyinotify 0.7.1 provided. Do not call this function from new programs!! Especially if there are developped for Pyinotify >= 0.8.x. """ setattr(EventsCodes, 'ALL_EVENTS', ALL_EVENTS) for evname in globals(): if evname.startswith('IN_'): setattr(EventsCodes, evname, globals()[evname]) global COMPATIBILITY_MODE COMPATIBILITY_MODE = True def command_line(): """ By default the watched path is '/tmp' and all types of events are monitored. Events monitoring serves forever, type c^c to stop it. """ from optparse import OptionParser usage = "usage: %prog [options] [path1] [path2] [pathn]" parser = OptionParser(usage=usage) parser.add_option("-v", "--verbose", action="store_true", dest="verbose", help="Verbose mode") parser.add_option("-r", "--recursive", action="store_true", dest="recursive", help="Add watches recursively on paths") parser.add_option("-a", "--auto_add", action="store_true", dest="auto_add", help="Automatically add watches on new directories") parser.add_option("-e", "--events-list", metavar="EVENT[,...]", dest="events_list", help=("A comma-separated list of events to watch for - " "see the documentation for valid options (defaults" " to everything)")) parser.add_option("-s", "--stats", action="store_true", dest="stats", help="Display dummy statistics") (options, args) = parser.parse_args() if options.verbose: log.setLevel(10) if len(args) < 1: path = '/tmp' # default watched path else: path = args # watch manager instance wm = WatchManager() # notifier instance and init if options.stats: notifier = Notifier(wm, default_proc_fun=Stats(), read_freq=5) else: notifier = Notifier(wm, default_proc_fun=PrintAllEvents()) # What mask to apply mask = 0 if options.events_list: events_list = options.events_list.split(',') for ev in events_list: evcode = EventsCodes.ALL_FLAGS.get(ev, 0) if evcode: mask |= evcode else: parser.error("The event '%s' specified with option -e" " is not valid" % ev) else: mask = ALL_EVENTS # stats cb_fun = None if options.stats: def cb(s): print('%s\n%s\n' % (repr(s.proc_fun()), s.proc_fun())) cb_fun = cb log.debug('Start monitoring %s, (press c^c to halt pyinotify)' % path) wm.add_watch(path, mask, rec=options.recursive, auto_add=options.auto_add) # Loop forever (until sigint signal get caught) notifier.loop(callback=cb_fun) if __name__ == '__main__': command_line() pyinotify/python2/docstrings/0000755000175000017500000000000011402071147015711 5ustar ookoiookoipyinotify/python2/docstrings/uml_class_diagram_for_pyinotif_4.gif0000644000175000017500000000535411402071146025066 0ustar ookoiookoiGIF87a|LBDĊBD$"$Ԧd^\jd|<2, ܶbdT.,dJDĚvtܪ|b\\JDD:<Ԣt4&$$ĢzlԮ \FD̦&$j\TB<,$~t ̪24TBDZ\><䲤rdlVT rl侼̢tbdD64ԪNLnľL:<,"$vtTFD4*,̞, H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜIfA8sɳϟ@ b&EA*]ʴӧPJ@Q ʵׯ` KkhZ55[ov-ֶt[v/_vcf֯U!0lrV{U0̀y B P 7dF5 :sgkkd y=#hJɒ3O=̻z52\}?GWG[.nG []PcS0KЍN[U[MARV!sg RjHX"vH"K [8Ԍ4hP <@)Di֋LJ-6)%gKNiWORfҖ\2%J`'ݨl#V;)tIdUi%&g|䧙yV+Bi⟂@P 5z2@ĉy:=dfEitèB^=wƚk)q J[h2 qXjVXBjypYb<]{$\mۘz&XeF\Qqd/oz V]]yp| eZ D_j)˕JW 8aV܃ڋ#g!}y1hQPuW33a:g猅 F@F .MJҠtϧ=# a.N4$7 Wn! wFn pM(P%Ǿ/WC&FGA0D'PCH@P@-aS!2 H?=c4B</>AKplL`T0@ Am '⮄& Sh&.|Lb(Cа.!Y H"HL.Pb=6Y'ŝPqzH2b FDpc!8q#נ>qu(2wdGFDcă m^׾թmňTJu]]Btic] نHlc#QUqF?!T%#>VSk"ia.-Pvlg.qqM XBQ= z`D@IK2%c>sjCI4D-Qր( jp= z$K2@/*QKLip<¸-\aal3_̷~N ;pyinotify/python2/docstrings/pyinotify.UnsupportedPythonVersionError-class.html0000644000175000017500000002640511402071146030053 0ustar ookoiookoi pyinotify.UnsupportedPythonVersionError
Module pyinotify :: Class UnsupportedPythonVersionError
[hide private]
[frames] | no frames]

Class UnsupportedPythonVersionError

source code


Raised on unsupported Python versions.

Instance Methods [hide private]
 
__init__(self, version)
x.__init__(...) initializes x; see x.__class__.__doc__ for signature
source code

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__, __unicode__

Inherited from object: __format__, __hash__, __reduce_ex__, __sizeof__, __subclasshook__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

Method Details [hide private]

__init__(self, version)
(Constructor)

source code 

x.__init__(...) initializes x; see x.__class__.__doc__ for signature

Parameters:
  • version (string) - Current Python version
Overrides: object.__init__

pyinotify/python2/docstrings/pyinotify.EventsCodes-class.html0000644000175000017500000010751411402071146024164 0ustar ookoiookoi pyinotify.EventsCodes
Module pyinotify :: Class EventsCodes
[hide private]
[frames] | no frames]

Class EventsCodes

source code


Set of codes corresponding to each kind of events. Some of these flags are used to communicate with inotify, whereas the others are sent to userspace by inotify notifying some events.

Instance Methods [hide private]

Inherited from object: __delattr__, __format__, __getattribute__, __hash__, __init__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __sizeof__, __str__, __subclasshook__

Static Methods [hide private]
str
maskname(mask)
Returns the event name associated to mask.
source code
Class Variables [hide private]
  FLAG_COLLECTIONS = {'EVENT_FLAGS': {'IN_IGNORED': 32768, 'IN_Q...
  ALL_FLAGS = {'ALL_EVENTS': 4095, 'IN_ACCESS': 1, 'IN_ATTRIB': ...
  ALL_VALUES = {1: 'IN_ACCESS', 2: 'IN_MODIFY', 4: 'IN_ATTRIB', ...
int ALL_EVENTS
Alias for considering all of the events.
  EVENT_FLAGS = {'IN_IGNORED': 32768, 'IN_Q_OVERFLOW': 16384, 'I...
int IN_ACCESS
File was accessed.
int IN_ATTRIB
Metadata changed.
int IN_CLOSE_NOWRITE
Unwrittable file closed.
int IN_CLOSE_WRITE
Writtable file was closed.
int IN_CREATE
Subfile was created.
int IN_DELETE
Subfile was deleted.
int IN_DELETE_SELF
Self (watched item itself) was deleted.
int IN_DONT_FOLLOW
don't follow a symlink (new in kernel 2.6.15).
int IN_IGNORED
File was ignored.
int IN_ISDIR
Event occurred against dir.
int IN_MASK_ADD
add to the mask of an already existing watch (new in kernel 2.6.14).
int IN_MODIFY
File was modified.
int IN_MOVED_FROM
File was moved from X.
int IN_MOVED_TO
File was moved to Y.
int IN_MOVE_SELF
Self (watched item itself) was moved.
int IN_ONESHOT
Only send event once.
int IN_ONLYDIR
only watch the path if it is a directory (new in kernel 2.6.15).
int IN_OPEN
File was opened.
int IN_Q_OVERFLOW
Event queued overflowed.
int IN_UNMOUNT
Backing fs was unmounted.
  OP_FLAGS = {'IN_ACCESS': 1, 'IN_ATTRIB': 4, 'IN_CLOSE_NOWRITE'...
  SPECIAL_FLAGS = {'IN_DONT_FOLLOW': 33554432, 'IN_ISDIR': 10737...
Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

maskname(mask)
Static Method

source code 

Returns the event name associated to mask. IN_ISDIR is appended to the result when appropriate. Note: only one event is returned, because only one event can be raised at a given time.

Parameters:
  • mask (int) - mask.
Returns: str
event name.

Class Variable Details [hide private]

FLAG_COLLECTIONS

Value:
{'EVENT_FLAGS': {'IN_IGNORED': 32768,
                 'IN_Q_OVERFLOW': 16384,
                 'IN_UNMOUNT': 8192},
 'OP_FLAGS': {'IN_ACCESS': 1,
              'IN_ATTRIB': 4,
              'IN_CLOSE_NOWRITE': 16,
              'IN_CLOSE_WRITE': 8,
              'IN_CREATE': 256,
...

ALL_FLAGS

Value:
{'ALL_EVENTS': 4095,
 'IN_ACCESS': 1,
 'IN_ATTRIB': 4,
 'IN_CLOSE_NOWRITE': 16,
 'IN_CLOSE_WRITE': 8,
 'IN_CREATE': 256,
 'IN_DELETE': 512,
 'IN_DELETE_SELF': 1024,
...

ALL_VALUES

Value:
{1: 'IN_ACCESS',
 2: 'IN_MODIFY',
 4: 'IN_ATTRIB',
 8: 'IN_CLOSE_WRITE',
 16: 'IN_CLOSE_NOWRITE',
 32: 'IN_OPEN',
 64: 'IN_MOVED_FROM',
 128: 'IN_MOVED_TO',
...

EVENT_FLAGS

Value:
{'IN_IGNORED': 32768, 'IN_Q_OVERFLOW': 16384, 'IN_UNMOUNT': 8192}

IN_DONT_FOLLOW

don't follow a symlink (new in kernel 2.6.15). IN_ONLYDIR we can make sure that we don't watch the target of symlinks.
Type:
int

OP_FLAGS

Value:
{'IN_ACCESS': 1,
 'IN_ATTRIB': 4,
 'IN_CLOSE_NOWRITE': 16,
 'IN_CLOSE_WRITE': 8,
 'IN_CREATE': 256,
 'IN_DELETE': 512,
 'IN_DELETE_SELF': 1024,
 'IN_MODIFY': 2,
...

SPECIAL_FLAGS

Value:
{'IN_DONT_FOLLOW': 33554432,
 'IN_ISDIR': 1073741824,
 'IN_MASK_ADD': 536870912,
 'IN_ONESHOT': 2147483648,
 'IN_ONLYDIR': 16777216}

pyinotify/python2/docstrings/pyinotify.AsyncNotifier-class.html0000644000175000017500000005000111402071146024503 0ustar ookoiookoi pyinotify.AsyncNotifier
Module pyinotify :: Class AsyncNotifier
[hide private]
[frames] | no frames]

Class AsyncNotifier

source code


This notifier inherits from asyncore.file_dispatcher in order to be able to use pyinotify along with the asyncore framework.

Instance Methods [hide private]
 
__init__(self, watch_manager, default_proc_fun=None, read_freq=0, threshold=0, timeout=None, channel_map=None)
Initializes the async notifier.
source code
 
handle_read(self)
When asyncore tells us we can read from the fd, we proceed processing events.
source code

Inherited from asyncore.file_dispatcher: set_file

Inherited from asyncore.dispatcher: __getattr__, __repr__, accept, add_channel, bind, close, connect, create_socket, del_channel, handle_accept, handle_close, handle_connect, handle_connect_event, handle_error, handle_expt, handle_expt_event, handle_read_event, handle_write, handle_write_event, listen, log, log_info, readable, recv, send, set_reuse_addr, set_socket, writable

Inherited from Notifier: append_event, check_events, coalesce_events, loop, proc_fun, process_events, read_events, stop

Inherited from Notifier (private): _sleep

Inherited from object: __delattr__, __format__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __setattr__, __sizeof__, __str__, __subclasshook__

Class Variables [hide private]

Inherited from asyncore.dispatcher: accepting, addr, closing, connected, debug, ignore_log_types

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, watch_manager, default_proc_fun=None, read_freq=0, threshold=0, timeout=None, channel_map=None)
(Constructor)

source code 

Initializes the async notifier. The only additional parameter is 'channel_map' which is the optional asyncore private map. See Notifier class for the meaning of the others parameters.

Parameters:
  • watch_manager - Watch Manager.
  • default_proc_fun - Default processing method. If None, a new instance of PrintAllEvents will be assigned.
  • read_freq - if read_freq == 0, events are read asap, if read_freq is > 0, this thread sleeps max(0, read_freq - timeout) seconds. But if timeout is None it may be different because poll is blocking waiting for something to read.
  • threshold - File descriptor will be read only if the accumulated size to read becomes >= threshold. If != 0, you likely want to use it in combination with an appropriate value for read_freq because without that you would keep looping without really reading anything and that until the amount of events to read is >= threshold. At least with read_freq set you might sleep.
  • timeout - http://docs.python.org/lib/poll-objects.html#poll-objects
Overrides: object.__init__

handle_read(self)

source code 

When asyncore tells us we can read from the fd, we proceed processing events. This method can be overridden for handling a notification differently.

Overrides: asyncore.dispatcher.handle_read

pyinotify/python2/docstrings/pyinotify.Notifier-class.html0000644000175000017500000007173311402071146023524 0ustar ookoiookoi pyinotify.Notifier
Module pyinotify :: Class Notifier
[hide private]
[frames] | no frames]

Class Notifier

source code


Read notifications, process events.

Instance Methods [hide private]
 
__init__(self, watch_manager, default_proc_fun=None, read_freq=0, threshold=0, timeout=None)
Initialization.
source code
 
append_event(self, event)
Append a raw event to the event queue.
source code
 
proc_fun(self) source code
 
coalesce_events(self, coalesce=True)
Coalescing events.
source code
bool
check_events(self, timeout=None)
Check for new events available to read, blocks up to timeout milliseconds.
source code
 
read_events(self)
Read events from device, build _RawEvents, and enqueue them.
source code
 
process_events(self)
Routine for processing events from queue by calling their associated proccessing method (an instance of ProcessEvent).
source code
 
__daemonize(self, pid_file=None, force_kill=False, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null')
pid_file: file to which the pid will be written.
source code
 
_sleep(self, ref_time) source code
 
loop(self, callback=None, daemonize=False, **args)
Events are read only one time every min(read_freq, timeout) seconds at best and only if the size to read is >= threshold.
source code
 
stop(self)
Close inotify's instance (close its file descriptor).
source code

Inherited from object: __delattr__, __format__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __sizeof__, __str__, __subclasshook__

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, watch_manager, default_proc_fun=None, read_freq=0, threshold=0, timeout=None)
(Constructor)

source code 

Initialization. read_freq, threshold and timeout parameters are used when looping.

Parameters:
  • watch_manager (WatchManager instance) - Watch Manager.
  • default_proc_fun (instance of ProcessEvent) - Default processing method. If None, a new instance of PrintAllEvents will be assigned.
  • read_freq (int) - if read_freq == 0, events are read asap, if read_freq is > 0, this thread sleeps max(0, read_freq - timeout) seconds. But if timeout is None it may be different because poll is blocking waiting for something to read.
  • threshold (int) - File descriptor will be read only if the accumulated size to read becomes >= threshold. If != 0, you likely want to use it in combination with an appropriate value for read_freq because without that you would keep looping without really reading anything and that until the amount of events to read is >= threshold. At least with read_freq set you might sleep.
  • timeout (int) - http://docs.python.org/lib/poll-objects.html#poll-objects
Overrides: object.__init__

append_event(self, event)

source code 

Append a raw event to the event queue.

Parameters:
  • event (_RawEvent instance.) - An event.

coalesce_events(self, coalesce=True)

source code 

Coalescing events. Events are usually processed by batchs, their size depend on various factors. Thus, before processing them, events received from inotify are aggregated in a fifo queue. If this coalescing option is enabled events are filtered based on their unicity, only unique events are enqueued, doublons are discarded. An event is unique when the combination of its fields (wd, mask, cookie, name) is unique among events of a same batch. After a batch of events is processed any events is accepted again. By default this option is disabled, you have to explictly call this function to turn it on.

Parameters:
  • coalesce (Bool) - Optional new coalescing value. True by default.

check_events(self, timeout=None)

source code 

Check for new events available to read, blocks up to timeout milliseconds.

Parameters:
  • timeout (int) - If specified it overrides the corresponding instance attribute _timeout.
Returns: bool
New events to read.

process_events(self)

source code 

Routine for processing events from queue by calling their associated proccessing method (an instance of ProcessEvent). It also does internal processings, to keep the system updated.

__daemonize(self, pid_file=None, force_kill=False, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null')

source code 

pid_file: file to which the pid will be written. force_kill: if True kill the process associated to pid_file. stdin, stdout, stderr: files associated to common streams.

loop(self, callback=None, daemonize=False, **args)

source code 

Events are read only one time every min(read_freq, timeout) seconds at best and only if the size to read is >= threshold. After this method returns it must not be called again for the same instance.

Parameters:
  • callback (callable object or function) - Functor called after each event processing iteration. Expects to receive the notifier object (self) as first parameter. If this function returns True the loop is immediately terminated otherwise the loop method keeps looping.
  • daemonize (boolean) - This thread is daemonized if set to True.
  • args (various) - Optional and relevant only if daemonize is True. Remaining keyworded arguments are directly passed to daemonize see __daemonize() method.

stop(self)

source code 

Close inotify's instance (close its file descriptor). It destroys all existing watches, pending events,... This method is automatically called at the end of loop().


pyinotify/python2/docstrings/uml_class_diagram_for_pyinotif_19.gif0000644000175000017500000002211511402071146025146 0ustar ookoiookoiGIF87a|LBDĤBDĆ,"d^\Ԧjdbd|dJDT., <2,ܶĖvt|^TĞܪTJDlvllVL&$$D:4j\RTԢ,*$ԮĞ64 \F<̦rdnd쾼|fd~tL:4TB<~| ̤,"$Ԧ<24lVT$D:嚇.M~S壧|n/V.nS>s/o'i9џ.^gӄX3}/ELDŽzwֽYxLPף 64/x_FN'H%.zqAl["(HXrÕXe*V* [wEo]b!\"c\3 jhԝ,e)24DCrB,_/E`-)(`KǗ?h[BFp~H5[v2@>q%x GrK!SrDr(i#HapX2IEV{$"!yI24)O)Tu:[|q>1Kg=峜r2$ ,` 'Pa3LJ䑏":I}/GӪêW)ԏ6Ԉ =A-fII.xh`nرs-F I-|29tlߜ8Wdt)g\q3u(evޞ'繘.aԪ6ʫ[D9xzMmoLiK|J9!V1ى+>g=5 S6PEn\ U/P/hW2=y-lC.l! 3N6hCK~,SRA[{?U oD`S{/<,G߬w26 `(!vI쳒Wghv`إyaXK&[$P k;>A8%c E5/rh#'yb*GLʜ/4zl$!<.ϵیv|𹿽v#鼇f?a*AgЧ[_JOҪiV;y6ͨ_!H]up)ۑ%-mi_l&  a*no>(٩*6aLgBSdɶ!dHhD2{~.绫n6 1ŗ6h?/NW7g--~ S_`FRpC T `p`F`q~|A0G}gR"fr/s1$3 #CMqv郀 z@st?G7;Wt4ZvbIpuhsAucuW@rd'|$w\7Uutt-i(9WU{:jv1`Lngxp&dyr=t8SvxG|X:~TL5fUw!i9%yAi9878z1zSz zW0L,:T!5{V82vww(ŇlP,٤"$rmuJ!ȈNjFx^"vh([VVqwEn0o-"lQ 5%QBrr/ocR/Rq,r$ځR"51#r!s(Ȍ}"[.(vS687c7uSO587y󃠗A9vv1"9jP(hU8AX8ZE)4Bfw?H >ً(:{ѕ `IHWXEuAjFlXi4:Fbd {|5:(FZrGkKp{\Qԗaᅌօ]!r}*vU?n6~UO')A%BaMi* |p5pu13!h v׏aqsa.,7 0 1{cqt$cG*'7!?6aO7d mڃѓݩQĞt RjQeSy]FInIt9:J#*%' )+ڢe8yNS2*EQ9?9P?5xAGJpT6RBm^0DJrAn"ܸ~DEzW(tbzg )qэmZa7C(| y!)hJp_ٟ8闓ْC(S|fj: z j:*F Qj8Xv *Q*zxz5Z{i3*'|i!vѣ 7AChjkӁ\M\9R:9]ƥ!}HIF%kx:CvuZ9xq5pNǝ@r2[ut|'w$I=6c6t - ht{ʴhr;+:Rv*eLì`Kx.;8f hl+rJ:Ap{X-; @{;qv7qѮHz?#K* +$N״lݕD9ٞ<xrYT(Ӱkzaٸe[F(vX$`TRzgyՀi((&a'w0K iRR2;$kV ?ޛ>K6_]CA;L;F+yR1v+D_x7۳[ֵd%HZl[Cil l"LYx{hu¤ KU.pKUJ5}6V5MC,;G}^Uò*:dkrGpȼTR Ƚ4c kb3}`n;7<78>reƐcpx\0ܾX[eŊ <™y̼dw;y[8쨁;wܽ,t Lw9h b6tc \Zvq{ZĪ'%: 1W]훳̿i2\r/^g~i+ zvokoQ/2ɀٻ<l4a RUatHg&7l8 ;׿),>LI-4 #|!! *NPR=T]V}W\^Rm>Pf}hjlnք`t]v}k=z]g`׀` ؈@`D0ؐ= 0 9=9`0=9  V@ڬ]@{P ]/{` +a }]M ۾M}mo`}am]1 ^A. ^}>Q ">$^&~(n-`)..N׽W4n$0P4~3x$ >:}|yjύV9M.Z-h KS#f(\^[ K8d fNXRN$)Qb"ZP@%:M#$X 21bq-h✻&h-A!i.fKb'l-(`6h5[H,gtzr*nR>ئr/hrr^R虨 36/9㮾9c=c+1oRNZ55Z#r.Eo()TR8aCR9U=_=9ӖsCG$?&*?ePX2?4X3:wO/IAC+-EGIKM1_XZ;7<`O>/ZT=tiYQ(s ʢWHpx+ *,5~؀Ҷt1#d Kn R /˳1]_{.``; p}~.c0٧Lܷ KmʲſO!,)m `[L  H4;8Y_/بo7`-sb_OKs8,J@ DPB 1QDXEE:cE{%xdF3EZd2)8PN=y>YQ!<.q$"-H c!R1?ʤL ؈8}E!DD1sHb d(v+DHApɡ%*K֬ZʕmYs:+9"d'[Fz!fѭV-鈬b3V[w+|5}GdrCLι[zj̭_.9tjg^<]qͿ_=s=3w_A0@ D@D0cB0B 'B />C?G$Q CWdETĈNLpFoT(NTAFNJhN2I%LZ)e&pJ/TK VD3ͅR1`!5SN OO459 A OCA C HRR 0RMo|Ja!AٴTTUoD5U_eUXg%QVZoV\wNW^W`LXbEXdIYfUYh-HZjiv@7\q%\ssew v^{7_}_`xUzᏕ ʘ s-F`"B66 ;1X%Eq:ZQLcͨɆP jdڈ(MP7֙g7J+V 9UȖ5^HF i$H #QU2m ,PoC➻nzfѲ^hɐ6$hQx j% ˡ s0<ղy^hH&I~Yr/#*Wn:_,0ᮏ)@&|I ^qw$ J6џ!? 'zEZط/x10 J4g/ d hvNp )}d8 U*tCЇ?b8D"(aCpXD&6щOȐp5@h`1",Q! b3SdceF,wcu(E:Ďzd >rtcGD2Idd#HFR -yIdrdN _ JV+`,ȷ5KZe..X E/_K-J0OT S$r'g> NFhTGj+CiD:`:v;"HPQO: T?$Ozĝ(`,`¡5 &W`ʢD-.MGA $G%5RR0-rKWSj5Mq 4W7iz ,GEjRT6թOjT: LIժWjV@$ȫ_WI0լgEoz9`o}[:Wծw+]!׹8@׸ծlʇUucZڕXk[vV_ᚈE -g `uj=Y-mkVpE/Y> n- ؚ۸[k  zU}+W Mzw]W[oߚ-Cj1Yb Mz "xG`\c\ ̷q}jv{{z@A,bS b$bo݄f87?~ y,h 6?,|ȅ~q#s(1!I^r\klE<&!;d&u͛+e:'|ScuoE 7jC"VqLozHDQ PxWQL7Ak9a}CQze`9zk#=JԢkKd;{ף.Q^(Bz\lw\c; @uK\{/] $3"#΁mnt5q_mo|Vۖq%(WQkh*21H䛮p&gZf? \n#|pxeb\`)] 40J > j.4]\an\J]lW?>U{ouxO G6ꔉh bL$` ob ~z!R@ wa ݲDR`ⲽ+ ߸: a}oEҏ{q|_^-g.dB G_u@?_ُ7*5$ۿTd@<@# Af܀Rdtʬ{HA;Ac!$$T3@%(&ԉ'+BԈ@/01$C 4AHT5d6D8C†9C%C<Å+"Ί`,.a]? DDB:LXDAL8Jm BDbJ謼J9ĄDk+1J8r/+=/z]+8 F  Zŷ2F3fRĸSDG1{-P6I26dCǻGI<~|܌ ,"$Ԧ<24$lVTD:lI:h3x |RЬE@-[XkX>w~mܫ}#W\UuGq $Zp|)'Kւ >sC-ԡ_d_&`xDKl0ʸ!UR_ Hd'j-jA tHdni_k][dil)`myBlG%ekY斃&gyi`hDU iHPm':f!,(^{B`'몭 _om):[h]Wn[u([WXt1@)JJmm,k06mz,J mY-']f@Pqx,k,nH 0*B'/++ @mܱ ,[|p 7!1>e&Q EJAD&-7I%(iFP+y\!d^-C|G'tA-5Vct[sF k'dQ#2ywh_礗n][KTǮG%L/o<``7ӈH4B+kpZ6ӵDqm5zϞ;SBƢ^^ԍcD@:iU \zƤU}_=dֶG׺xҳ6r4_ X> 5 [ÙH/Vebcfp\3cHڅfALSI~> --u?0@0 U3xPɰ)@}"G~q WKs6hCF5tc Elp S*6' h _*z٥Ůc0c3K Fcayضa fV+E6 mJӼEm27ֲ % f(// `4KЏ}tgnռͭQjVֹoA`e,&Ra> 4>7}iV-^M2̎ gh쒆EaX Aox;F}o𬻠iOz +S6riw- ,uײ)D}BRxVq,2SPMlQtznq%S#-rs1vyFdf2s5F}>g8G>:G{kmcotM5>C@$v~dSttQg_ 4u-8gGu.N9P3T8VhmgYo8wYքgW9y8{7JօZCxb~aixrKQC!M#jaysYkyL؆v1z$bMv$'zX${qQlDmNn(]'/{XVdB}BTCwnG-h~f\~%on!Q)oъ!hhsRP$0 /gg(ƀeWd7-VSˈJ4oqsxu9P4'%>'r,((0@35hS긎1}ItTu:BȁQ{Hx Duǒ0?8-yI6<2Vv!YUvE9e:tIN)?VKUoQK[L0kW\ǥ$hz{e]M9Ȧ])ƊHt}x~}~!.Dn5Ռg'~ &>lAqaW3R1v<7#S*rvc<7+F )GGFY)Ld$)OFF;ɓOU Nٝ1Y99~QBY:BNtVT9JLSI9QSRd[W9'ɱ_Y4Ɵ)f$V'{ Zvl .^T rHIJc/vИ' Y37SvQrgМt[|tdY/)醆FztH#Guՙ l;-rzkZF}p|* Dwj8f-* 9SʥVkwiv]KE~!ʎ!\6kkrIUi(ɦ㥙[ZBফHɘ}ιʘFQoiأՑpۈaHp-h!6b%gڑ8caqAӉd;wJxj [+wgJf&wY}ѨSjw^?ѩc5;*t!\D䖱zq걵 (]$J"}y^ӗkHv:E$mڀ_{ϊݲ.Bo$"o9Uȍ"u*ݪ##23ɯI8qqrX#K)sBtv$m<8\bj=#)ui@*k; ۝˓~gб]u$z(Uٲ/1[UY[~AytQ{OQNORoqѵ˽onעuV;Djۍߺp!.{k7vl!л =7gzy+Vl'<) +̒-|*+- K:3˷99;ܼp񼣋f6ux#4W[:j?{A Ď+R%5x1Rh\Lۯ[LB[Т/]{`Ş Z9_^חxpѶmt|~[{m{}&33S`+mx7ocQ5{z@ |Ĩ*tiָܸӺMV° М/9/IB<\l=A@ \|L<]>bP] 0]5QO 1Op T&TCp Pp0}(P 1# 0J@B)@0GX0L'@< M]1Qm\IQGdJPU` je 0t]5 x]Q0yׂ==؃]؆׈y، ׎eْՔ]V}٘ԚCٞӠ1=ڤlڪڬڮڰۯs-۶}۸}7pA !uP:k9CfݷŭpܤSv9HV9 ح8݂XU<@ aCg潕ѳe4m}ܝzJIRz! ,L=@dmn!aѤN/N%nݗ'S(-N`$jZ| -q!^܍}g+cfCe{b[ENkM~*;N܍-n4/8>80^cV>-ε3ݢi ɇ6y %3%Ս^N0D,q3s.<3nh.mOOqJZ5S )*˝Q778\CkynܓcԣٍF01 z뺾uV./Ai-nˎ.۸ގ;>^.N>p12a,7m.&KBP x {?=f_ANFK\św g04yk@@a iP Sp{ ]fP Hhp޷(E[BZI0 } E468F}n*-nR^pab8l^`wZA@rL) ,[%EpEpSAS:0ʇs&n~o",>+_ϒ.ޝ@tO/>sR^S@@ qJB >Q"C6-^ĘQF7*H%IޘRJ-]t(0męSN SDOEERx$UԈ~DU]T)Pt|EV-DC@)j\^ZX}UUB*8EPTfzX䔘4PeΝOe(0TM+Rj֟ 8o#W^mul}o%~\9˝Sm\zӭ~]{۽]C,^շwo~|ǟ_~kx?R !dA0B 'B< lG$OD _F4 4(!ŃR1E;20"=1@4[RK,HMp3:4VYMEs ZC4$8# -.`5 "W`bդ3vDEoU+lX$=>\-esVnO6E)"D(MvEݷhKZlޅEq LW]XAUPzϐbYܖ[O43UP d;LyeT 5J5&[w ($ZšEqH@zIzId:/~v2kFF{uRކ;n离n;oa;p'|nݴGf<r/OzǼs!)?rGGtD'=p_Yw;vo{vQW}tw/x/'~=㏏޼->1D>GA D+1 X%pM4+.Àr 3S<@0 \ S" T'%- N @XapN@) BR06&DOFh(UDX54xM8A#f>M)N/Uo`sF12ge 5:gt#+1 cG>я#$^HBҐ{,wHF6ґ HJVPd+bINvғ&AIN:b1tR~ e,c Lz'$%S MD&-3LPޡte4Ljβ۹%5 _TC&ч 4fhZpE9[ x38YOf*Ӗg `o C+QPy6Ԙ?r1bʀ,E3J΃&t5̀@0h(,x_6ԡ-0PbҥMsIƀ5? iƠy12T-S˥6uHZ4O]ԔƼ*U9֖YV@h+.QL&@h. \ kZ)ԑuԃ1vnR{kC'0!l 6[Y⒱Zul5UZ֪qMmke;[ӑkmu۷.,__¸Enr\6׹υnt >(ҒnvA6o9o+܆׼.yc{^6)o{׾/|{_2@q;`6.u]7n};akz>_ /,݊MEQS8հr82(j0ͺZKqITȪ 2 96aԥcNvl%IKx9whÒ%ld^ E/"=AcX&!*Q{hE/QBC j1 c^$ɘ~neg rtW8tc=VF/֬Llb8u57iU2ٴ%+2maMJ"Ŏ_`;EQ;j}E&XWAo`%:XLRۂ m [fҘr/6W ʢYg,[1EA̸lXTbܸ |0g6a0 JJj1@q\#'9{Moܼ+7΃e>s9duscЅ>tGGzҕt;pyinotify/python2/docstrings/identifier-index.html0000644000175000017500000013603411402071145022033 0ustar ookoiookoi Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

A

B

C

D

E

F

G

H

I

L

M

N

O

P

R

S

T

U

V

W

Y

_



pyinotify/python2/docstrings/uml_class_diagram_for_pyinotif_9.gif0000644000175000017500000001716111402071146025072 0ustar ookoiookoiGIF87a0LBDĤFDĢ$"$|lZ\f\nlvtĺ <2,dJDԦlfdfdĖTJDvl$D:4,t4&$Ć|bTnl T><ܲdRLԮ\F<Ğ|亼ĴtbdԦL:4TB4TFLh\`hޔk;ZO,Ъt7 !4$7MfCMv8E0SD_ F YzeN=-YxF]4ڈ#u~22!uazU]wHfOBE^1*Wf|-TndMB9](2".ڵD}v'}p&)kmyY]ه3AH}5C (][!2t) r)uޢ5 Wo@@HA [45*+XTtk,9G29j+.`v㦫n`嚻Xc+ܺ{oտ,Uz@T$ 7G,hKƨRs,2eT#W&0rl_,<7A ,DW4SL7=G'suOSSWu;jf $w0BfTj!E䦭65kW&Lw(!q1n& H݅t| H uO1X(\&x`~7*PH$3RzeXu@~SI7xbeV"JR^8~k]hv)uT0BG ĮT߫T~jFk&i*f%K<*֑0*L/^_w$xa\^@B-52`XzW B;!\EC}M]cJqEQ)buE,DE/)2H6n H:QM1cM> i LdrdB 1,@$#d$ ?  !A "A!EDc# Hȥ@bUH&Y1 Blhh8lj^z(:iZ1(d )x`=Oxʳ5'@yρFP5B2p}"*ѫQG(Ful6 HGJҒ(MJWҕҠ4hLgJӚt ӞTh?~ӢONKEE/= TBSH&ZWuե5_) X³Yݪ[ץ&7o3`);L(+2:_i+G YB=T}v+dgYr*]Uv\e_;GƃSVT&8/GP# `[i[jdF0|n>L. u ]87#-DS8Duj'/۝p@I^MmvRT(!3&::y:YjXVrx+`Ze&egZ' 8α|@~+e ȔE|&; J*[Xβ.S 'J2hNsS8q'QLgy"s{g^Tݳ9Ntd"slt` 6q{a,;c%MjI[h+Z (=Ug\Fޟ~[ )F3RiMP!n2M.K}'/+CVҦvC,2ZUЍXfAUP/,ouq + ./+D CKIx׺yA.W|lȔL8Lr.(?de]-:YSm~tzQUK渺Ě=:ZжΚ W_Ȃjis˶og; P E2(>ռwpWV/|54Pb9_8r4b;=z4VWuۀ$7Vq=v03pWa-d+,LIW} N.2Gm"F T ;wA%5~<<< kkv\\#t!$"$5AJj7%Fz)˳#s7G]Uz$f%^.vaT-Hm<N.6AN7 &ʖ]gyr&v8oAXmVpmFƆV7loj012_E@u= f=kX?6agVv$*Qa99vn vVx`2։G:[2Y=FbtC|w%AbroגAocFcaJy+2FbLb3}|q,,%DVU..w:֎"lg1U.=tF"v`=#~?X8EtDq@ DxkDP&xFYtgg}}$ o!ih# g.Yl0)296 Nu"CU]5y7I`GfǓv"z'+Yi-.g|Ӌ;(]uAy92WAȧ|gy%z#zXgnS} ZUy~W}c]Ȗv[}9i8X$f[ƙ%=5XvY== =El26`xK_tAt~mqr8(qu &b)Bhaha ؉nmay+,荲ID,f$)-foh/4.19V.(2虞HDŐ萕DP3ipס $q&z/)F1u(uvFY6^*.b6CvIi17Tɓ73Wxt8yXi9QjoiiqiOJzq&vI&JeE ut!@禉Y;Ҧ"@n@٤x\ &ȅ{ktk?k5`:@im]-Gl19&vș=]Rφ$ڇLL@tXsȫHXƩm`h*T7@T0DH3yѝwjʢFpGbHhA (h&8+by$ YUY(.JU z{aDHd.I* p% "h!{Ė*;k,ETRuh| 5{2@Л|ADJTU~8 *W˒ F>1@yuUD%n7W*V0S$ F;0{Jz(zpN`XO2imju[P `tظ#躵$p&k3Tbx`[S`|~t[s1]v*OvAbsX`LБJ2 rzԁ"{!aY3XSZ`W{,Wk[0A ujw7$XV@1Bzuoi t[q7r:o~Ej1-Gp[>Wva?YS@ L ~){ kl} ;|ʁ'[tAz,$o~1 o(L {-NAIGN`\LYjűY_uº> _|Y_j}\yBjA`*`IРUlţwOܠ3K20ɺmVil&@?`i靳LBC`p1bF$0CXPIº}-aqu1ZJ|!؉ջ &HbQˏN aP@6 0_\|$ºC<;F0qyt%Âoo֟t1ZZd +./ N- 17RJ(smdZ#z֊Ƶ|,tn 'FDpG؎ؐm$G]ٖ}٘F٠ڢ=ڤHTڨڪڃHI5dI}5ItG3JtJ 4J-#KdKdKtL144L4M.dMrQ(4NdN&NNM+Ur߰1~\  I~>EQ>AW">$^&~(*"nd,2>4^03{rjTCi8]0D^F~HG0K`PBW.JC\`-a~`~]\` hF^ V>Y\xg>ANjM h>+@ @ + vnndn2f^x>,vvMAo]BF%%]0~~XNꦎW~ qp0{e>jp vN ^Q ] M `מnc1_x ,`w>䈐DUn^: ] :d@ v$I C^ PQ Dež겾dq p@̮+^3,]P C^1_ _J^*vN]@ p`"@ On 0fh0M ^oB_0DYM O, MZ'0d-m9?? 솿//o/_@.??[#p ʿ?_؟r03EE&O_2o?/oE@ $` >QD-^B=~RH%M TQJ-]>L5męSN=}T(Or^E%M>UTU^ŚUVX)(V,C'͞EVځ)Ǿ,[u-6^X0]} v#Œ$r8:R³~t-|Xă!dq.59:sm6zhaK^吣=~R::DxwoG/ǃRJnԥ(peS  M.s38Գ=Pj@Q:/=Ѝ.Cs1rQN)SDc?hhb-Ҥ&@q R&,QE,h#HLq1!Toq 5 jc?(8# ӏRXd J`#;£6d DO.%҉Xdo P~ÆVāhzxݏ>{-@<7z"t ,BoEA( ~D$C8וU-F6&PW,JDHYa?G>@ZcVdC:Qꂜ45! s/V&F;ᩎ/:x3dS$E-N/!JYrŽUIT%SUIvpC)+Y%ST$V-e 'Ii[%|˗ #!JQAuhIY%VIxi qAqYB1˅=@d)+4g\%bw2|E3@T~@ @ůsJq+cIz0ɪ^eU IQ# e:r8dBd ׉8"3Y\3e9 : K .LP?SlJRHb TB)ҷ,uwr4j`vm3+:8oi[Yqկw^Y׿V1!lKkX*gCd%;YVֲlf5Yvֳf،tŴEmjUZ"mle;[ֶmnu[ַnp;\׸Enr+;pyinotify/python2/docstrings/uml_class_diagram_for_pyinotif_17.gif0000644000175000017500000001253611402071146025152 0ustar ookoiookoiGIF87aLBDĤBDĢ$"$lZ\Ċjdܲ<2, bddJD䴒T.,Ԧ|fdvt|D:4TJDvl4&$$Ԫ̖t|bTܾ dRTL:4\FD&$nlTB4:<4*$$Ԫ|bd亼  |j\~t̢̤,&$t^\z|\NLĄĎndܶ<24fd\64Ԧ|D:c6z]9Gs a0 Uwi։=!t5`F+e* exaAjzMX@xxr,Cd-^I`x$G (!j&GSI >EDfMHJm:W@qDpq1 M:AQ;;- #,Ѕucĥ0KMR9 097rL A\f17OfMS#g9wNQ:ģ>~s@JP}eІ:D#`ͨF#ЎdGG6o J2 vXL@P"LpLw'0!@Ӣ@:u(/ @@`G<=!!1"aX kNI ZkւլkK VhrͫJ@PS|ᯀ- Jؓ MbZƖdudOL#,f7r,hG[ђ1-jWղq-lgK js򶷣-p2"Mr:ЍtKZ؝z xK"x KzK5^GP ALN;Xp pAJUFxHJL؄udR8,iTZf]\b8Wdj%flr8tzv!8XxAD脐8XhPb؇8W qcW`a f `jlf7`X`tZ}(a f."```_g&v`֋Hb/&è'BӘ a4Mfc׍`H #`ѨtPfgfh`j hy|}V&|dVup 5h Iajs  }a to`( |"O0dff%y)ck. 54 $y NhSْ/ɔɑtFhfQ aVivnI`2g` f|(_Yi=ag>7 s0|&Lypx`fjn Q'nƓy&&&p7a6lRvk))ٚӶg7&_y9t1p a)8Ĺn۩©zfliٙ_Ȧl@6 avlɶlڨZv pijFlVcj:{cמ_ a pnp +_Faro5*qY q6j l HdP&}n98֣ +8e'eX2_pඣYol_h:tjJ`'w]*|*j` zʥՐ Rz(vM@n ,j@=FJ7x 3w`Lr)@j&JtzsJt;Jab'sRsʩRs: ɜ:j}}8BjJ`Ўp qnnjLYp juh_|@pʤ2_x@x[c _*qgo@DZj`kt0 mwʭ jWgk['Ke'i^~;pyinotify/python2/docstrings/uml_class_diagram_for_pyinotif_28.gif0000644000175000017500000002650711402071147025160 0ustar ookoiookoiGIF87aK5|LBDĤBDĆd^\$"$ԦjddJDfd|<2,ܪ vtnlĚ&$TJD|bTdVT|vlRT4&$ĺD:4ܶ$Ğ|jl,tԮ \F<̦Ԣnd~t̞TB<,&$z|jlĤFDĊ|vt䲤̖*,̒rtfdlRL<.,Ģ̪D64ԪtbdlZ\亼䬊|ܮVTNL~|>< |fd^\̤Ԧ<24TJL|b\D:<$ \FDnl~|̞TBD\JLtZ\L:<,"$vtjdTFDdNLzt4*,,K5K H*\ȰÇ#JHŋ3LǏ CIdF&S\ɲ˗ QœI͛7eɳϟ uJQB*]ʴ¤NJ*իXׯٳhӪ]˶۷pʝ{؋b6,߿ LÈ+~ް+b#˘3_FKH͠CּvhI;1/kS`U !s=: ʍ_1̴-cbq9pȏ'5ơ J^9L,ÈςkI@HP9Y$Ͽ] X0Bz\vf6u YavqJ.}5 5T&*h \l%Hz&h0B[~6K*1ȩۍ{FI[| HD`GQاD؊@ `bQ2z"L&E+jtģ(H+tq< 򍂹fA"J`e/04DRԦ$`76 *>Bz)V*Q L ADjRY)ގ{ 0cEB1h~Wx̪ju? <8Y΂ Q7H!%-jY 餹%.ry\A+ȥ52+×Xd e1_!5aC *VVTlZR5h:SͥM3e"vJ˞R80vaHAu^op?-(U jP!T8 C&R(EwfQ`4*'xqhd>ꔐz z$UXR&Ϟ tt8Mx4@ B ׉REOnj̊jX Rj>"j1aU)8.JN0+55|$^ȥ"v0RtOԐT }F1l`1+ZfLB22$ȵ2(~O4V#OiScX"#Ǜ]̗#O2LӺKW5MjL 1 ߔӺ?: +*v ͑gt.ť` ҎwqR{T5cQaR9-'0'lBrX7{ ;|$b(NE\R'+8:,A%P(7Bl PTBJ{JlÒy)dGD) aKX9'_' M|aI` Ai/ X P9äV6R/5a? @KN ~0 $J ȄG +4-eQZ&"PU/duu\:տ^bdddٟ6@ljl 6-m{ܐAFέ#~wu}x;B}NO;\N'N[7: GN(OW0gNxCp6@ЇNHOqP y0}Ι^T`X7Z)p`;qs\hOڇދYT+bXUG:c)}@7E,Ot|\׻.D!Amh.|>%:O`#ކ lx+ >}ې|^lhBw~Іc9;y/E($H wh.s>e~PW ` >wevp` pw[' w7ЀHu`|WEyF~&Ig @w mPsPx?p}A  <t uC 8I9=8tR` m` RKMHuwǂ,OydG9s  ssC | ·Cgy u Bthx8wcs: s݇$jXy*8Qh ns t:@ NsDFsrtPzH@7>Wg@mALJ$gGMwo>s#hst0@> R` ?>G>(H@w08HuCPX)sg&8 `/ks }t7s} | y|`*s ɐ(m ^X19m ȏ'v0YS5:yx4d8 @Y@)$guE L9ňTZhg@0dYfyhjlٖnpr9tYvyxiea9Yyٖ{ٗ \דÈy^4Fy(dCٚYY YH򗉹ٛٛ9~ yșʹ9ؙҹvɚyعw9Й{IiJguY'yX詇g tywu~Y?d?}ZtwIt%tאd*t|Jtb}"Yw7uz|g|a8D }w xtYy(G}|G|2j{!)x ((S @ȁȌ\*tg@ m@pPv@Zu!8Hhwd m0"JfW& WIA8Q؅_Yy PuPW 3Exh>Gg+XWzt\ڧYׇX#iZtFYPnP}WȒ} ج Uʙ:vΪG RȊ A o,Ɏ||ګv7yz#z%j8u8䨪EGYy oHwK kyZ -I' ))|ȪzK* ȱ' hnjj ] C[I+h_vsvYk~PP}D{TJm u:`+9lTr{LIix۷:ʷ~;$*jhxɞɇk k}/ࠕkn+Twyᘾ|8|{] | -} -ڢ|KʫRʺ:}w 7wm`KϷ;LX?' zP*Ps ھ:+:y #[Zzux ̫+|\ يA P*PWbXІm($<|ਇ[xXgm}: bs ҹXiϷ(Y `ĭHuj*Ah(<>|@kӉ(tG+vNKWW੻ʤjs;: \TgRY DM 'ksup8 נbˏ'J, ls8>W͋8 Ϩ˞ +P{{|+ͷ|}Tg zyZ& m yIkm:'tNz},E˛{rʀzRG y_0ȬS@甦9{c{(כwimJt-*yͽujUͿʊQH^Xsmzh 7X=x_p *t> LͅցحZwʩt|Y}jyl\IJŝ{|",tm0D {ި ui扫^HJ u:ȃ$;К{. Ö׮'¨Hn[myPpDG?W^kyw̶XZϢMt2sZ߫u?g(wjJtt'n\ϼky؍( $mYpW;tа@G|D֫ ˰E>玹L ؗi,?ٳm,!9t{PA9(ja ڊ RwŬۜo̲FL`,| )E>g(/=~bǴ:m߁τ+X[ ˏu>v0ʘЎʲ~~흜Ku\>w ^k  υ>׈Dh!gy.m@Ƽ<@̔yܞb(ͪރp@w Ptpu@?K|@a?w΋z>Π}.wz !䴎Z?0>Lߩs޸Я{ =|A[0ƚ Mm|gA-J x>ݗ?>/|==+ ӫ7Ӻ7;:tcM}ϣKԦNyG- KO-Q8t_wV},|/z| ډm,%ߋ՟GAguimo;=ثm@jʦ?{}=cIT7ͅ}ۥ]F6lcRA RFm"h@Sv^y cņ$!_nUx1F%RDEWu P'M3BMB(mC[ \Z ̊*eVZJ7nuҹEFF E2%KcVĊ()ۈ5$V k`NZ^M<0'1kxċ .v<TJG n*LPsB ٨Jk/n];M~WL.p՜F6AKPk[0JFj$:*A$ZP;HA@+E)H Q!UސꑨҲ:x%EVHX#25̃<$B/%0CŔS)^C@ : 1Fҥh*RĎz RH*#&baM z63=+sΊ^!\ebC>ZE3l7+HXbeLEZL(t w\$ejh7]M2Xe^F$g i vc]ֶx}k%}=d_9fgnUb>fRId۟F:i۰XzgGjڼ.;5[ )(1IQz<ӦnNjۮm` 5 Va#?,r 7d+ )H `*0d*gmLQ?Rlb(R  BdB77Cԟ~w feUa:vR6:hZΰ>`i,3i33:R"<A`v$y&yu)B,I|x{%,(z11LcíL{f:4m0 XL4KP:FJS1rh)ҡu#H;-< $C=} ~Jt(A H R04T;-(j_ d4F2QldBhV ;Qf16 pgA)uKm^j郖ENv“'QTPZ`GݲjjCxCy TLLU]k 2+w4g!RYr6-W~?a|K]i^Q ޗ@&0mF;abC6&YcH222$]c3g-|e4ik*ekv&[֖$lk2چνWr7V_3Id/gܘle4͐rf:׹nj3g>s )ܴ!HnwQ&" >!]Yٺϗ|p堷Q.΀3={!ng>h}i[ӋYT{Oψ Vā@D 6DhI`)ӹ.a;=PڧvgXq|!h~D҈id"DS<1)@fq] Q(/Șrc6챏, نB<,T#ikʻ<59iOJDD'3a)t W<-CP%*KXB?0i`,3e׭jZf, ΆӹN4w1ʊV{*=uR$jBrT,T*(Dq9" 0Wцh|Z#R-)7B)JR[|cLcy4VnT3mxjT.gaSjDaʆGJ́(B\AX.&/(D )*|,,ɼCӔBd:@0uESC[, @CwȰZ|+ >86D3 ADkt%1HtDDK,MRr̲mN|PXp-j9EIEYQUُeYEMŕP/E&٘Ŕm٣3Te7SɦZ{ګ++Z#Z-$G4/X|CzGyd 4Ș,9ȄܱU?HZ1X`!$a|I6ͩ,[hDI\8̝4.ʘʝDʕ7*K};~k#Tˀ㖷>2>ݥ"]LL:L39LЌ|=ӕ=KMcMPMM쌥=:`N4N1%k_;Pko;);٢;; _E| Er؊X1 " $ , +#ESK)1` NjO7T8u:CAC;MT04T9 T@Ѳ T@@4a4U((+QUUqUW6!,e\6!bePDQBf.lV1Vj'$/h=PUVMcL`B C"3l035ܼ#ZWf|yC} >mIf^XU;D[D+HeՍ^]Z Y1AYzF-U\Zٝu-g&f̙*pvag6i>镾f>?^ZN5ʛFP v6 AHiM蟘ܧT͜@} 7h6Hj!iHU!N jX!9zK77C]]ץ;P7;D]Ԉ^̒M9LF$Є](Lk̎) F^Ͼl֐xv ߜ[MCTdFx9m#`%?n-.ϴ[F'd`|VNmFގ &nΚߊ6D,$`V= Eeh*p,%h;)&PQ`So `{JQgoF6pOKڔ❚ܫQ= b-6 -=!E@K.?/rJƽ¨Q2nX+bo6I95ܙ_y lPB,DRELuMHT5^SDE^/BG7tP}6ySDkvMFUOƭUUAZegE34I@ZF[F6<Y WOdBV/'(dAVV\ߎYIYB XoP-g'PuS`y1e/-PN_1frqvs Eȅ8D8O˂;J u}rxtXigsDJlJ/,j~p/qxRwvOhvrHnOin3 yib\?k4[!hy)y1hhxa褁薖 ڙ6tFzDNy[z^'7GW?1'/|CHyQgwLJȗɧʷ|OVg7GW'wׇؗ}oٷ'7~WgO~O;pyinotify/python2/docstrings/uml_class_diagram_for_pyinotif_27.gif0000644000175000017500000000753711402071147025161 0ustar ookoiookoiGIF87aLBDĢFD$"$Ćf\lVTܲ<2,nl vt䴒\NLԦ|\FDD:4, 4&$fd$zl*,nl亼ԮTJDt^\̞L:4TB<̪d~|Ԧ ̢VT,"jd䲤D2,vldND|dJDĞ <.,|b\TF<  4*$,~|nd쾼|L><̢,&$̒z|dRTĄRTj\lZ\ܶ<24~tԪ|D:< $~t:<侼ܮtbd̞L:nTƒƙvPHu%a7` !!V]](bn<$ѯ׉t:1]s#6՚q5ˆ^7FS'#8 ڇtbQpOz3}zF4ږVow8C.۸y$^e#/7ּ AZ:=1/?> ,}L. o_@pPya,H>$t:<c(P1\p{x@ްrE @Qyy(b0vGBR/ᇡ+b !"p=48 X dHŐb` cTũ`/(#X4plt͈9-vc3<1`~c)]:$"7E>$8X̤&7Nz (;Ɂq`L*WN#,gIOA-w^>E\ IbL2f:)liLPӼ6Mn.0Ir3 n4a g?Ir3,B9PX`D$@%fяf@ ]PC - #iSJk#⬩NJC` @Q B2 İlA $B kAXӲ&ɩYת̧a+-!҉v!~ Rd$C!HC` `i\RQc'KVCq=,;/G5@Ȁ250m,e ٌHvl;LF "x'W?ȴ0L3d,n N&tfbJ6" x'T#a=aJ`QBz;Ҵ}u:1J8C$ Ҩ s 0,HX[P^DGL[$NCl⊠x۴&g4αub4&L"HN&;PC RͶW=bQ7l0B+o)|ZuY0Xc!ަ<S0}.i*yV{y1dkA^q^rۜ.gU53R)ڤ0 ,'Mb̋ft%a fA`oJB-D,3wC.!ɑ 6*]fK_݈N %Nq pyinotify

Module pyinotify


Classes

AsyncNotifier
ChainIfTrue
Color
Event
EventsCodes
ExcludeFilter
Notifier
NotifierError
PrintAllEvents
ProcessEvent
ProcessEventError
PyinotifyError
PyinotifyLogger
Stats
SysCtlINotify
ThreadedNotifier
UnicodeLogRecord
UnsupportedLibcVersionError
UnsupportedPythonVersionError
Watch
WatchManager
WatchManagerError

Functions

STRERRNO
command_line
compatibility_mode
logger_init

Variables

ALL_EVENTS
COMPATIBILITY_MODE
IN_ACCESS
IN_ATTRIB
IN_CLOSE_NOWRITE
IN_CLOSE_WRITE
IN_CREATE
IN_DELETE
IN_DELETE_SELF
IN_DONT_FOLLOW
IN_IGNORED
IN_ISDIR
IN_MASK_ADD
IN_MODIFY
IN_MOVED_FROM
IN_MOVED_TO
IN_MOVE_SELF
IN_ONESHOT
IN_ONLYDIR
IN_OPEN
IN_Q_OVERFLOW
IN_UNMOUNT
LIBC
LIBC_VERSION
__author__
__package__
attrname
flagc
log
max_queued_events
max_user_instances
max_user_watches
name
val
valc

[hide private] pyinotify/python2/docstrings/uml_class_diagram_for_pyinotif_2.gif0000644000175000017500000001666111402071146025067 0ustar ookoiookoiGIF87a0LBDĤFDĢ$"$|lVLf\nlvtĺ <2,dJDlfdԦĖfdTJDvl$D:4,tĆnl T><4&$ܲԮ\F4TF< |lZ\j\dNDԪrd\JDzl$|̒  *,4*$|f\쾼̼lRLVT̢̞,&$z|rtĬRTlVT~t<24tbdԦĚ$D:<:<^\ܮ䶴Ğ̒ԪD64\NLܶ侼|fd rd̦ \FDt^\|b\dRTL:Kh\`htk;z ,*t5 !4$MeCMv8E0SD_ F YzeN=`-DYxF]4ڈ#u~32!uazU]wHfOBEa*Wf|-TndMB9](.".ڕD}v'}p&)kmyY]ه4AH~EC 1][2t)'r)uޢ5 Wo@@GA[45*+XTtk,9G29j+.`v㦫n`嚻Xc+ܺ{oտ,UzT$ 7G,hKƨRs,2eT#W&0rl_,<7A ,DW4SL7=G'suOSSWu<jf $w0BfTjE䦭65kJJLw I!q1n H݅t| H uO1X)\&x`~7*PH$3RzeXu|@~SI7xbeV"JR^8~k]hv)uT0BG ĮT߫ķT~jFk&i*f%K<*֑0 *L/^_w.a\a@B-52`XzW B;!\EC}M]cJqEQ)buE,DE/)3H6n H:qM1cM> i LdrdB0,@$#d$ pC  !A "!E@!c# Hȥ@`bUH&Y1 Blhh8lj^z(:iZ2( )x`=Oxʳ5'@yρFP5B2p}"*ѫQG(Ful: HGJҒ(MJWҕ֠5hLgJӚtӞTh?~ӢONMEE/= TBSH&ZWuե5_) X³Yݪ[ץ&7o3`);K(+.:_i+G YB=T}v+dgYr*]Uv\e_;GƃSVT&8/GP# `[i[jdF0|n>L. u ]87#-DS8Duj'/۝p@I^MmvRT(!3&::y:YjXVrx+`Ze&egZ' 8α|@~+e ȔE|&;y J*[Xβ.S H'J2hNsS:q'QLgy"s{g^Tݳ9Ntd"slt` 6q{a,;c%MjI[h+Z (=Ug\Fޟ~[ )F3RiMP!n2M.K}'+CVҦvC,2ZUЍXf9AUP/,ouq + ./+D CKIx׺yA.W|lȔL8Lr.(?de]-:Ycm~tzQUK渺Ě=:ZжΚ W_Ȃjis˶og; $PE2a(>ռwpWV/|54Pb9_8r4b;=z4VWuـ$7Vq=v0s/pWa%d+,LIW} N.2Gi"F T ;wA%5~<<< kkv\\#t1$"$5AHj7%F{)˳#s7G]Uz$f%^.vaT-Hl<N.6AN80&ʖ]gyr&v8oAXmVpmFƆV7lo 012_E uf e=kX?6agVv$*Qa99vn vVpx`2։G:[BY= FbtC|w%AbroגAocFcaHy+2FbKb3~|q,,%DVU..w:֎"lg1U.ftF"v`f#~?X8EtDqP DxkDP&xFYtgg}}$ o!ih# g.Yl0)296 Nu"CU]5y7I`GfǓv"z'+Yi-.g|Ӌ;(]uAy92WAȧ|gy%z#zXgnS} ZUy~W}c]Ȗv[}9i8X$f[ƙ%=5XvY== =El26`xI_tAt~mqr8(qu &b)Bhaha ؉nmay+,荲ID,f$)-foh/4.19V.(2虞HDŐ萕DP3ipס $q&z/)F1u(uvFY6^*.b6CvIi17Tɓ73Wxt8yXi9QjoJiiqiOJzq&vI&JeE ut(@禉Y;Ҧ"@n@٤x\ &ȅ{ktk?k5`:@im]-Gl19&vș=]Rφ$ڇLK@tXsȫHXĹƩm`h*T8@T0DH3yѝwjʢFpGbHhQ (h&8+by$ YUY(.JU z{aDHd.I* p% "h!{Ė*;k,ETRuh|05{3@Л|ADJTU~8 *W˒ F>1@yuUD%n7W*V@S" F<@{Hz({N`XOBim u[P tظ#躵$p&k3Tbx`[S`|~at[s1]v*OvAbsX`KБJ2 rzԁ"{!aY3XSZ`W{,Wk[0A ujw7$XV@1Bzuoi t[q7r:o~Ej1-G[>Wva?YS@ K ~){ kl} ;|ʁ'[tAz,$o~A oK{-NAIGN`\KYjűY_uº> _|Y_j}\yB AL`\РUlţwOܠ4+30ɺmVil&@?`i靳LBC`pAbF"0CXPIº}-a!u1ZJ|!؉ջ &HbQˏN _'@6 0_\|$ºC<;Fpyt%Âoo֟t1ZZd +./ N- 17RJ(smdZ#z֊Ƶ|,tn 'FDpG؎ؐm$G]ٖ}٘F٠ڢ=ڤHTڨڪڃHI5dI}5ItG3JtJ 4J-#KdKdKtL144L4M.dMrQ(4NdN&NNM+Ur߰1~\  I~>EQ>AW">$^&~(*"~t,2>4^03}rjTCi8]0D^F~HJ%P @BC>H>RA\^R-`^f@P UnF>p Mp~x &CyF. @0vSn]fA荾$Pu耐s>k pP `鋾M!E @ nrpr cn@WCN  , 쯮nS P纞_ pD^~>PcP ~1~^eN %@d>c ,; |K.DP. /SNe~($j~ ~ uNs0P-*_0,K m S ! Ym0c-lLOI/K_j(lrn.p?x`^rz|-qp?_33>_T?_/O+~_(O&$!ȟʿ?>د!޿/?P: _p IE>Ѩ@ S2la-^Ę#>g<~RH%MD2e]l]Zƌ&AGvڐJEEeAm["u!A6ڴ 61g93X邕+W9(m4MXbKa g)[jV*ɋK+ 4yeFMD ]ih<[ j6/2%bōw,wL&X)HmƭM;.LYD1b_iW.dDǏ4M1[D<Ȱοh<$ʮ@DKϠ0'Ò3<=*)ZD eq 9*k@̰G60 AP4!(KX$e7iM%% ǖTѡ L 8{$NH5#D.) Mк p6JJ /mR,33LsMK/#Izð<<֘R /E5L/"cIzdz3KTw-jU2cEJSp;ds=WgQuYiVg]jT]h%\ qe]MW]mݥރu]tuv_z=  >,8 .5t _y_:ƂFcKc *8݌v^h&iSm#PG/z Zki, : QZBX8* M $amtł츶 +ժfo/Lb{q)OiKQDvl*CE5պh<5< j\JL*,LtĊ䶴Ԫz|$rt<.,Ԧܺ|jl̢D6,$lVL,&$\NLĢĤFD̖ndfd&$ԌĴ64vtdVTܮ侼 Ě^\ nlĆ><~|VTNL.,Ԯ<24̞D:< ~|L:ݽ|Г-:/]1sD3}uko]bz(G P1 0^t$t/kW -z @ N *F*3@'TQD RD:`CA,Rv'&0T}`"wF@"18T4q!9D`*7IŐP(":Y$(Ii=l%Dh% kdPR JH؂ϣ`cà$ yD1'$llAzҼTi HIHCQʣ` `ttRHGgI9h GoPQy9Zv4:RFX4 FH{tHNU2h9G֔0iX*r0T<}GOeZ (6K9aGzJMP6ihPغڕG(-XcT/1H4ȉNvruq 404@3ԌA![p 1SKF`y1GX+zԤ4*Rcq WN'츀FZqz&z5-͟ HiZSlT>_jt H*MöN6v[ÿTѹ#0 KUO<TV#]63)VU6NpOCVŪdAlEZDcd[ȂtEC ARMc@c^J0t Imw:r02pC>a:-ī힧[k_頖 {k#U:薀CIu1ȅ8 R+E\fW…:ԯ(ط;;`w !^8UZe[bGu}3\b81[ ? Vϛ>C!~ӊGUqS3Do%c3xAY,[~!&|x,y|* mfOhx:EfDZZЛ1LhglttTLGߘ4j`Y;tO% bF:½fsw V!^.)NY:80<1RY:` Xr=Nw͍nu3H v=Z վo{Gͽ&"a^Xz6JM?t4:&: ;:FvƱe/Y};dŋEsĒ\:0Fu GFH J\tNC- `Dt,B=:/qOd7;KPF@¥f {h~GBFP£"i Bn֚&WۧXkeźX.z>: ` |'~gM~FgHLXN|A'Oh0(e #,_V+a! SBgݡG,~=|B }ct]#b 0EW*[ F`8Aʒ/rmԥ`~L !|%1Fo8LC,EC CҶ?x??،h0xXd3Rָȋؘ.؍8䘎C08 HC<???븏Qq@TBҎ!:6E9hE ⏦7IlKKQDDLp4H/IDOnG G(J3M>YMRqȑJ(}YGW}$RWEYUevZ9 ynRESE\֕#9\}K9zҔ5BmEa1V^vbG`>&ɓ b;uu@F_eiY(Fh`Yi\F&v%}Cj*IfjfiPF@ a{R^fF,隰j-m97-tpgp2p(o>G| М(61mCӉy=[t™hpz)xq39x'hŇ>+`j4ua{wTKr")nDX!h~~/yk( (g!:#/ "w4b7EX!A@",7Z9LzX©\s`: )dzhhݨl=AfGzZø7ziFR/ڲ4k /+"F*JZ< ;m9+RT*VڳH+8}*N.rR[.Q;VKWR\ĸ!Y"?a(EdkCg%&RB4 #&7f1~ b!ŤfM$KOsړD/)@blFOF>KQRKG+"$h5[0^TZ\VF5Vo[UXNnohn[Sn)akXX[uwuѵ;a%haI/^ڬ#Gsf+& }Y`1yi_h嘈)aKtbOſ鿩e۸LޚslltfHҚ)^l³¸曽"&WkjHk<0^*ssցq.9JĿ s2W2lJ\]W|5qi,Jw{y'}Iwr+UsgڟGx:[u<7|w\wg{ǖDŽ̾z p|Yjֱh06XS*ѡ6)"!xT [<)+J˻LG˜.+P Z[01K+3] ͤl09;H+;^9mYpɄmn&'>=&kdhoKڕ)nE-JyE#|L-]õyøy1yr`oVG͝go¯{ \>8e: ,A㴜7ʓ㭼"&LNH-Q,'Z^>42Qq:.?[FH`LϵNW7"h0ΊR;T#ҏ>8NT!d7N@RNjݩH][SCU>G~[MKn~ـ%ٴ  {MY} ؐ?;baFs>-I,c7:irlJO,$.ܛRnf^j" R\` .ك Ggn J{T7o잏F@ DPB ><@.-Z,sQK`dL(bejVB L~ @A8uLHӦ@nzdI2 gP"M9ҥ@VXe͞EVZmݾ+qƌs5vWoYLW`… FXb||[Z0v5˝=Zhr#S{d]Y >c #[n޽} 6}:iֿG\rzGxsխ_ǞO^xs.xݿ1粗_~ ҧK5@Dp95odKdZjL)‚0!r˹:067,kTLA/j.(;˄D('_2lDPtܔı,bb1!F-I24l Ь2DͭyɸSS̈́TfpN¦-ˊjH @4EK `EKd5 HJdBCk2% KZl(MuV[*hb+MTEJ OWR-YJUV]Ӓ &A%bEV*`;eŶu+L3єSeEFHh{=iKF™ T EEM ui%i8㍷rE\ȚD_D l^MȅGVDf1"-h dAHFcFfj!Ԉ5.IQ,tfrDYhy歲Kh)1z+x >zlLHlJy喓%T1UfY8sNb0Qs4>/Qhh#͈hQ+&̒DtrǽJFE'}+P}vhGvf܏\yxn4OX7#i!z- p0Q Xhpߏ@xzF&*ю}A mEKE W\ @5iL4Ħ$ƫ[H34:k(*de)hCus A {[ BqĀWJ1Ƒbc.sBXrE#Ύx ?1Ed WPD¸Q!ؓ*<ΑPl1Y7>h ol(9B6ah 18˶l%v 2c"&7%d ʅ l@"`j^bД&Su4 dX/sr |t3d8hQf̘顃س5njzŠuC#@O!meFb& @"#Q*RI ;F(ZH/RX JH@3Z)Q\,2IV⦡$bJZ)'QjMTtuCb-b^i+Y8B }1W@-bAWrhXHj?udϲA@f Y 6= hY$ƞrҶ6"h];[0sU l[ְ[׸mz\6%p;]ґnu^;*"!!S/nzջ2HDtT^ Ko~- ]+'i/dQJ&UKa:SD5wk}(mj ȈfAnpyۚрơMrK1I0Tֽ~2ߍdxPMbC23X+2^ʺgFK5rft#Y5a2M;J3sV8%E H*U40:Z)[i'ڋ@*^2XN:ƥvƊEzQ-\PdbamuYOl׿vg`؍rm_F^X咝LpGxp# tC%>qtD5qw#&1'GyUr<vr{ws ${ \C|/v/wy  A@DE?z7G}E@NTd H=I@YPb{Ƕw B g'0xc@~OozW/b OXhE$ ?7 Q/1[  : EX@`8d9Gɟʠʡ$J$DʤIpIlPʨʞ<ʩʫJlhʭ<`˹˺˻Tcca@L?.:@F5d,_V[v{舖h;pyinotify/python2/docstrings/uml_class_diagram_for_pyinotif_16.gif0000644000175000017500000003766411402071146025162 0ustar ookoiookoiGIF87aS|LB<ĤBD\Ătd^\$"$Ģb\bdT><|dJDĺ<2,rd |^TvlԦLJL̒D:4|jl$"$dVTܲԪ24 ĬRT4&$~|$Ěܺ\F4̚TF<Ԫt lfd|lND&$z|Ğtbd̢lZ\䶴f\lRLd,<.,fd  4*$$vl\NLD6,,&$lĤFDfd|̖ܶ64VTĞܾvt.,̤NLĎܮ ndnl Ԧ&$><^\侼~|̞nlĆvtԮ܌̦LBD<24ԦD:< $\FD~|rlL:<̞TBD\JLtZ\t^\jd,"$lVT~|L>}{ʼnul 9HmY34f%d܈Ҡ coTn37a!ppr(m{Vh!n^FL_t$n\x \mt.0"nxH58q͊m%]U  Nm;sK6;-pZ"9]b$n5X#YErI+gWm[L#еX'bhJ)nv]H$ *+pIRdȮ5wgA`"n|Ԋa-w F9 ՎXb:=KƛײzGyB :8m\ݫ]ǣFH̰\,n-pۺyA܂$q9N-7f2*3{蠅-Sspa(5;އmXCEJK64;g;Ҡpt1^g [%| '9w_1ՈfEōGzR'nXKx&l8A;NJ^n:X^6Xn8ƞnVˮر/o' SWogw@ϗTznFߒ _H 6:17 ł E'dD“D|0 gHo-!H4>ǃy("^H&Hbtw?'Z#PbX&^Y r8E} #2hcB: C IBL"E\$'y% p\ы eH [BV(W"Ԃ0F*YI˚h!( J1Z%, ‰2 3D2IMD00jz#E`Š 0:K` @:U\`I~R0."ӟ\Іj0(B'T쒡 C RQ3{ Ғ&D4JR-Kazt*)?qӚ=N RzEK:QLESuը~q9Uju`4JֲhMZֶUp\J׺,_+W@ `KMb&0x+l:?ۼMrJ"b98mlf(y@M"TЁv,y-VHz%]k5ZVT-F2R2-D*q?46Χ n\ iC(zW*.D%+aQJD&(MMc (5 zb0aLeڭ *_tF%kSٖzAj[ζn{mȎs6v^[n${V]zxY]^O8}}~&WM?-p\-߸u81.+88 ,i#uɥrrD  Lg{m^<;J}S8ŸᑵL ?]Qԩ9EC/&{Y^*y^hk潓1}XGw("ᵈx]& ^\"y| ]Qzm]%_+{o"W>募ȼ1umD֧9KD%2~՚SWDenX.o0B1t`:#`htF}6QAw*rbg A Awd7v OAwRwW&8p}GAwG"3>с6xt7!yuv?6N&L}NpP7=!W8YMX_a(F8!HԆnpr8tXvXI2qhlUq>AG{8XE'{}hr?FngaY$ѳzÅ<~uPrYQ~#z[؈#s!d(è71Oi-q45yR#ge(vXiwc]gv}=;!(}a!c8"ǎ!\.\s3Ws7?s&"8yMH5eB'_`tHtMCI#=KW$|AgRS3q{1a^7[/Yb(')I{74i35*dhgd#ؐ$(hgii˜!\-h0b`w/؊+b+Gb71鉆|+-}4)Ii{!\Fjr(l%5uy2~/TCʹٜ ⓇWI$tٝBXyY319  ȞGYy9 %zڠgqyh(ߨ"$Z&z iz?(02:3)'귝@*?9zZz h3$w3|;ʤGQ@PXן\:N n~q D2{Y[^cb d*ا!3w^*~%8yR f7@"$w*7 {y{*a9b Ҋ+׸tN("jj{l?P0rJ3'wIdYa1P#+zlTl zr#^lݵ:.z:©I/V..>6z9tjZʓAG_ 6MЩ*(twB: _D_!{Ҫ2 <Pѭq1ں5@I*Ðت*!Ӫb!^J$R+z:,im+o[$s:f&NsUKj{l=vv},N@{da lgcYӱ#취v g#W>p7*Z{n=:uSӋ5%IS0ԋb1ӛ[;]X{ er8Ko{Cs4[/;8 (d"\ L#@óQ ̃ ڎ9 |[3r*L%-J5b 82L6\/Kx[?qll@<"ɺ;9N>{.^qHB 3`\uYdl[ YĶ&ň:%m[X;,pb<,XZi'X0Țl\ᧀUJ<fЊġAcez QɰȘ|b豬zvʓ|,;<9ʿ!\V:$寖* 닼Z˫˿H!6˫8;*;a\L1ɐWmaz `\m`  f' +$C yVd?|d.5#%{v!i3 Ԉ1bP,5c̜T5͋wk+˽[$Y+}lz" c4:1Ha+tK5ո#"2+ ̸*nlk~mM<͐ Ti>4#ԍ8{\Kޱ:,-8Y3F֜ôe/yK6?<_m֤+!iM\8{Ҏ.nIlp ` Q$0hk‚ɞzǭ:,̻7!`ܼ$Вwک=Ĭ[}Ȫʌs _߲ HDa c,H;!A޾ I3.p024}㱖Dh@pBnwƾͷ̕C?6Tڀ+-[9\٧ZC˰cY_f߱?&{mvM?< ݑ̉lVlje~gZoN "y\-먹1.?$"s4gssؒxʨ6ڨzSΫ*1DYQ.;طtTmA'wg#It(]HxΝZq3%}ҳ.2 ,!$m0mb~Ӛk."6Z/8Q3b)TުZ,bTuuq-]r. HKԸ3:౵#w|Ҝ[sw )3 =#ܑ4?Ў c#0H)|B 7tsAB &酌X+-5 l@kŒ˰‹2I4+C8A>ā@9CɹIEDDD:b%i)9P~r|E)RX?$AE!D:^(q#ƦE`Z1X T*TO )϶ _,(b  @`A ,M<hWH@bQ3%B">7&>]b8$ rea8=^.>Dc؅ X`E.@qD,@96/=P07 MSAT1]?bI^!A",eׂU9T^Ff  3NzQ{!V3DcYdA@ Zfj]"^tZ0bЂHfXyV~}nxgQ`Fhf]eNnhzUTh.XGVbXhmh項璦Zfq~jwFdhT \hiOiN钦[siQX Li؝MHYh6F@힩EGb警UH `-g~ "9[}vkr!hgyГSJ$LˍIfP" "a жBa̐ ~Ndᅍf{$0b`$N%(홮h.Ff{sp[p>Vc*̯>eѰItg" fiC5;TdLe|Q޶5j/`dn+n fձi!gR@6pJ$kCj9qr)ON l,(|agqMq2f fh]Z6o:XfS=s@gYh&=FtsE`i ?cC?IKrnqItPw#ORS_UOg*ZP䄥 _N# O6ZO}1$-9G^ b kta[muImG^f˚@N;,ʾݨ9:~w$ʆ$lv7miFgV^x퟈_m ڦMv?0uufL`$OaH-NO;Wwy!h怛vΟ0@Ē0co uo>O t2mzEf/_@.1b 3p@)c*{9V.-xoDFhvOc+pc˟cBce_5Ҏ`{dLq%;e6,,EQv.'n}.#}dn0Tir_yfWf5 ~?kFl9e^PTP.Tysii~Zh~|mx7`>l,h „ 2lႇ'Rh"ƌ7rܨ*Յf:,1*Wń%̘2gҬi&Μ:w)$Р" -j(ҤJpҨ QvjFVr+ذbǒ-k,ZJm۸r( u.l0Ċ3n1{l2fYY)3`|.m4ʨWnЕ"K҂RٺwV7p|ܢ _d}9SZK%l //qK8]` j`=~>).2/)H~ :8`,x^A 5!`@/c0BA"}#tԆ֡. 5 iٌCT)N2PxHr,GZVWj ^\ۭa/ͬ,%Fe&wAnۡ gIo:CkFvD8NB( )y0QgS%xFJ3T:jCJiA*xbAk:kA:z!Ht8dqT)wAgKm/ύᔏ ZSDtɂKK+)2;k L eW4*zA1T Sʰ!2/̶lG{+x%rkxͩ̄],}<M|1lLGOIdU[}5Yk5]g=5~}@Ee6mvd7(w}7y7}7 >8~8ޅ>8K>9[~9 Co~M>:饛~:ꩫ:뭻:>;輛>0 7<;˟:O ?LE|].~( Rv{:$#=5FA :E/^:: EH,;Xc _vDp`%s( ~8_@B$ GaM CB!qы`Р;9Qg㎸#,p<$X*("f;B/HW" =@'/Jzw iS*XIQn%.uH02H &tQC98mr3eɊ'4=dg&HE0c):iotpI4`c'zAO{ g+_a<'Bs˅@0Uh'O3ЉCe(EeNؠ'թJb|(NP44>b:Qb ޝ@Jx:OEi$A:UfNӳn}+\X\/v+^z˴z+`+ k,bƮÚ2&R,f3r\|=-jSղ}-lc+Ҷ-ns򶷾-p+smC2ulRl.AkrP񒷼JvͫW~o{+2g/O"%.3~0#, SxE.CK sý'/k9[wSvІxw/oR~s`?9y< NOx?zЩ{ r~HaW+È7y i wce4!ibރa[ۿamTK|{{腹Uu苀D5Nw8e:v!tXDn8 X%8у6Z}4>;hrng5Oѳ[lx_o>NY,JTY*^3C5mP5hXRЍRؑ6pA6  'm%6 r,`-N'}R(!aY]J߭ %!+N/`I** ֩ &%(N5-_* +ơ ֍^ ʡ a*TJ p\qC]HX; (`3I[ V4hA&2)(FT(S2E12A)ES0ʒ."$".A1FA*M6=c=S>1bNr]1bP1ؑ).c:"S6b<55z#/#|c8]Bxb%-N5Rh6>EC;`S<48Z-G($'V$I>SJ'с#'@ʟ?QbBK[ANMVRLF,e%?N4PERc@eM$(>kBk8A,va5*4Y+Ǧn>R]\q\LQUI<m,B"^-P u$! XR(bpm ʡ,eզfAh;351#.^e)8A-ߖ+I$ S\d<VeF-Ah_JfŔ|ll %xwRJ^+)qhJR*(:R$B"|!oNB/f/Fv/^// mFbfȾ/F(,1l/`\,eNɢZ?[%usV][nBT+&_^1 C%pO.m-6&ҰS5bݾm11 .X$*0nRZdUAnBoxpif~nnwA.q#%*VÏ>gi>ݡ1!#GZj8#_yT\/&E(])rkr+_++ϲY2-9ro/.32g.j[2Gs/AnzpQK38[0|_]Lq8s03 r3@=߫-2$ b4mCo]2сfBC>F@kA@wb;FAnk=ПiQ4N/,42NoNʎ%4Pw'(CSGu!5&T_uPZ5Vw@Wiu@95ZZ5[[5\ǵ\5]׵]5^^5__5``6aa!b/6c7c?6dGdO6eWe_6fgfo6gwg6hh6ii6jbCBFk l6m l6n綃ܶnoop oqwk7r/7s_r77tGw[4TF<~|Ĭrt,dND|bTvtԴԪD><4*$  亼|vlĞ:<̦<24TJLԦD:z鷚K~eלeQLv̰]ͻϥ[U&Ϳ/س\^}f$BPZW%;ʯޙ=[i!u-:K_םfiqW]i4B4hJ)NRڅ7d!th! Cj .H`w 2 9\p!L$yHI@H0Vbt78d9Ωv%!j.fjkR"qJwxNwbnx9)h2Bj&Ay磑Eq唛ij韀9JRha-N!b'*RG ~+y(gp׀HIKNaw ~'.Z'j^,!1d&/vlhhv06lھFLֿ*qxhf1Ʈm|H"2q$V%4lͦW@-DmH'L7,V(lգ M9ٍ4|']9O=;-Wn9P?9f9o.I~nkHUۚZjlr4[i"n ZZrħԺtXokG\p{j;l Zw./G_+i򱿶!m{)v,z€| 4E~}t@3"&ׂ:@x@pkpР,Z Q=o73jы%!PVbX#`4i O(EuO]Җ4s 5T CS◚pwNnjo%DN9BC=Њ֞vDu $5b&NIO] L}ҌAS(w xfnKN2IWPHBD &8yE\W-XZ!Y+K\䣊q"谖` w3O+O.d 8Cuf3$aL6b>JQ3d3p0VT=HG澏2#MiL=T+ei\RTiM=wSN;[O}9Ϗ*kj%nwPk癡qFm`49%t`%* 13+_άj=o`  p:BF0Py{CQxa9ˇ3CntN'MNWRKtiPLԣZM2T:m9f\jZuvk\;KjnVkzvW=h[-4g]vM64qJsWUo\[}B[tjf8} ~6P Wz7d ݚ0pkp="å\NN^v w)8j`(FS "jHlڨm|=Aw2S'>5)cer3-&e',cs& zIH+T\UǚY1%|L 1W$ĥ.hXomWs=|t.a<<=x,5twx4|SA?W+G6.9Z zҝ(]zR{{KNA%]#? LdOƘϾ 3{qKb0.~^-1b0 %:A ($q@x8@q1P 1P a0 X8|(@x) G~@ :X@FPD`n E6PRM(X PXUHO_a8UXfXhNln:rtX!xxz؇~x7xxr~؈qP8( ۷؉xJjvb|Cxj/ShsVыX!行LraNoFHad!%2D$$ Bwhg!e!\&AX vs$SLYD%)c'h.^xݘG `}v2MH{ԑKǍIi(K@)(,6*(/ c9Qw8D*Ғ2BV)Pfw8X%֒-Tgߑu'-^"ySQ)x/ᖯ!XUƗj l | 0}I9 1 Øs1Yqiy:xI9Y5vp9ٚ3ٙ7yIiJ%Yqa9 [E,iYZWaYCHqtSC)ٜ) ّYAyz q?ӡ+ZTaifʟT9(z;zؙ.Zy.:٢402>z8$j9D;ʢ=/jNKzM:#ZGzXZ\ڥ 5X%gS?XNkj?̸Ye b7_Z[U[tB"F>c[#$\w 6y߉]]ѱGiaOs)9_)רwju'tdGCutGGVWzmd  d1ItK`Dfu+9\BePKbuge 7*MֺM-e9g)3:)Aʛaz yPԺQzZ(# |*8+ٰ k9{49) k& 7)5x&plQ57#VJQ 2 @PKm=q+FmOHg./@>KPn*CNv%o Doژ2vm gJXNUXXo+tڅ>[B7p%q?twKK`ʧeU[5qCtO$rc*-骞^rruGJ %[5^ߵu[O9#Ketdtm&BAt"F`TpUaCuҊ^b TequK0b%fs`vxJk 6'rdtwe*MM[Dx <)d1{+SK-oxqN'Ɋ'.rOdff꠯`8@ wKaz΁z)_zB, p.^@@>8 !?>E>^yBDs2` \ fQGMG`,W ; `]]t bCeΪWDI"Mf+٫7}bMu.iXTB`q@>P`+y26v*TKw_;Z;@ǔqd2(-)'~ <ȡAVQPK0y2NxCLM-,LW"HxJ}wrdM­)TPb<0>Xns9/ 2^m~/)ֽAA!2#f /gC#"i}"l>?HEOO͊vlX3ٲmڋ2@VT/W%0h*0_oa?ٶ=yRcvm;4ם-M1+/`M߶M:>)dѬ,~ qjᑛȇ .$n!t(q,X^Ҡ^:^<'>nAbEGKM~Pes^r-͔ a<%H q BK $QD$)\\Q`Ç "T8QHW\ 8*(N$S"ƅ:1!$} @DEETRM>UTU^ŚUkRJ$fYsI%d|)  4*Fja+@ŠXzmw$CF"phɡ:,7޾kTzЭMFZj֭v+0%4JRBtB >t6m!G 5L ]:EOH7*Q,IQiAi/;[GH~?f6$ѣ$v`+B ),ȖP(Ч5\B"'/h[HbES\ I|0B *@'2J)pɈ8ʈxR$$bˈK1$3r<ӧ&3N9*OK Dc'%=@} uS:'RKSpJ%.H4Q;mTQIaTRYguL_5W]w57k6XaWcE6Y~YgMXeZc6[m}JZk7\+\sV\ueצXυ7`m^{%W^}qF_ niO1~*_~'J=ǁcd0yy$8f],ۘ^_Еgy=dߝiO[d @X" XjC C01<H` Pz HP/$y!CbB928Pm ij޺N[E{$!%^j֚kC % y`g}*y(JRxKߜ` /6'P耐5~ !a5H>{ 3B%kٽ%@z,dW;60*Uځ HHO` jH $FH@$-b ˂2B4 +\Ihn:,!AlB-gK'X%\0B"D E.VI%,q Ldr HF࢓0<܈\rrı'F1$2 JŖ1#Ms'p%I;AF2 `sFh3Y x b h23dgr?B41LeRrch&9-ީp3MtOHY7 B%<*RgtHc?" Li *҇*t eh%r@$H$ Ґ"P(fF㧎x#T#5@ӥ3٫҄%1Mi:MDR "YSK_:ԉTQ:dDO"HSԟHXT=IT˨ժ)pTg2k:VEL]kz/UQk^5WկLz^[+հ`۬"ֱb%K>ֲud5;^ֳfE$`H00윐zXB;Z$jұddo6Em1*rWWIl]DmjgljlkkZխ&xs-nPR:ǡr z}_ҦsnxI׸ uwr]A?Cn wIπwʠo|Kv~W@_Ɲxan~@ _)hA Fć a(6DJ/tbdBJ7,(e&:Plg+bL}rŕRlKiG5#z8Yty:"ǂ٭U= /$frossMP['Ɨf #,!ȫ1KY !%0QjjcL;kLӜ$qr9܎hy;yrHe=i7=TW\iuHIRAAґD!R (JKDE =uBG"gI3ZQMwjHѴK=NandɪDr)Rdթ>5D VIt^)}"ϥZ+Zzue}"mn'؟\=YiWv qW;&?T`*EVlkx>9mC\w5R;yʫ\խƃ3MD{_ݰwjo8:7T aMP|7H386N}rŐ/櫯>>Ü<ɰ$*S13a#p/ȅ5[1', (ېą Mѵ?K@5; M%&L;QA0;3%'\Ѐ(54-23˳) !N:BG#\Az(BrRc4ٴ()$5>)0Ŵb̂=Xl5TМ?NY tMߌM @ 4@ BZ1 2"˱kZpٚl,+ d!Zﬡ,ij"9%;+[׭-VƆ5KS5C$Z5P % N#CB=21[~9CL  hC8݈xhCds5@%A|%Y ܪl5QO z6(Rx'&D{&R7T67V^) ^$0%4 e<=(, ;F<9SM|Fi_e_S=_ot,qDT`^QGWcGn`RVz{$ᥣL}h[QR.ȭcWHn^Vkaa b!".b:b$%^b\'(jb*V[|Vn NW"ḅ/F[zw=xEzm5UrSjW1=\JB~MmG>*/sBE?mXXu̒Y >{>DY ZYILScFو%? ZMMU eZbޱ嬍eY*f8!uN^ }3l[ O4q[&SANciNVj )PE:B\nF#1$P̅9\$54P{\حYeA 5ևK NAMڽK]D&,zE{G\mbWDxR_RdxS'亮nEKRvidt_.8_fB'-(Ae%`83 VԴV*TT6J~].ixaaTb+⿺ll\lmmҦ>Lmf nf.׮hgc֍jYiT1cV4ΏF 9w-x}ʇ=m6#@nH*~ nۡg\ (J6LKOxo囯dce 0#%MecYue ~gH? ̞yф$faVZ4fDfeqޜqf pƢg [-gD[~ @qfHf|[wFe9g%2uAr!34s}ip4''Z5%h}n\X~\M3hN$Oz:1 _Pݍ.Gu]]]L]>]t CGpvKQ$X7i$tiits|SDuv7TO \lӮkӆ56X8k_ߨ.FS '>j4w^`fon"Tp̕9s}`ykkky.arx:/k춋xe1^x+G >yvIy7 oyuyy' pyjzy-` nm8yJ9B7nH'ȅ#pM1PĮz: o8EN,Z{02>WQ I KNv{{hM0 v?`lɧ/AJ(ݱ}]A|3O,֟2ORn~&X\ vrc`2J7Ah]/y/7HBx(P'HKXm _8R#,i\ AK$:B"ƌ7r#Ȑ"G "ʔ*Wl%̘2gҬi&Μ:w%%%(QCKJ$.Yp׸RDH"E.\ͺrҭkɟz/ek3w$91Ol2̚3Y`݊G.1ԪWn3p1#6܇Q7(a.n8򏼅3oOɧSNz9ڷkn;#s/oj׳_O=oo>8Svaő GPBPrW~I8|GG\pD;XtRx" eԅnm!$ hD,@br&#Dh,z@D\"[EVHр=  pčKHI%XgeSVXqQ# d$DAN0FD_*`V@<@u@?d)5& TIjƙKP !JKD:)E ;,g+F昄,A V|f8PAE6Y6DFQTIF6QZ{oOD .,!Q*ۖgEagBcPFQ y(D0,u8%? D'>1QX^;E/a B3QiT# FWG;RyaS!J@JG9(|$'I&R9H8 /![.Ii.aRm\,UbQ_Z'$&HH-@|iMN;̉J: 0Ѥ0,i~%@Tt˞tu "9G-Q 0,Uڕ&2V"NQ-iCdC/*kvOu-|=U}ֶxfadc@4 \Z%]K@-\BOg%A=u]vtB#_[IMauF*Յ5l^-%# ']ƖTLf7sQ)If2ENlm.b4th)A3RN%x`%<I(SŨI 9Ֆ@ N؁$6ݍkHUA1$6ϖm>݈j6Ci!mY;,gI@z]%"r`bo&e)єS>ǔ-[ 8) /R^%n׺.2s{G.Lp_/;[O9`>肅W`G݄'1S.^ Ӹ6:a>1,!g)B a%3N^rfw,X"02,h!2Ġlk㶷];pO#1tb#x˻'|᷿^ 3sx23P@83"ezC.򑓼&?9S򕳼.9c.Ӽ69s@[!F?:ғ3N:ԣ.S;,tDDTU U?;Ӯn'ޗ9v;wyCqt= e;3qz#/b)no蝧'I((b])*` (`-",>`B"v"0F^&&1*z IU 22#9@#)%8>#A 1c #O#;q=^<0?dޙ $BJ]l""6C""AV$޹NEnٝ(,y$HB].Еd$GaNhK$M$MdN<$OO$PP%QB_ĂR.%S6S>%TFTN%UVU^%VfVn%WvW~%XX%YY M[<$N$\֥]M%^_eM%`a fM&b6c>e%dVe^f)&MdQvg~&hh&i&Q&Yj&kk&lƦl&mFeZBfn>fc&pMJRf)ٝm*` !'!ؑY'^avBw|B%N^sVxgՑ&]H' z*( V]|{&z:e}Aqc1(,+2މ.LܡB(\B؂\ &4u#"nIB%Ё'aBd(]Ei _ҩ( ia(2)B)䩔!i)&hh)!'^Ng.Ji &ȂQ)!Y*VB ZV Ѕ߫^ڪA߮&a{@.x&_5,">r.\9 J B'`Bݹk+@ҟ) P@.-Ѕj"+u뷆+"jþXkgRkrĎ_b,(,0&ҕ빦+,,&] |"lǦĂ6c⫾#*}Jm,҉&Ҋ!nm:y-`*nN (%aYTB+(_n^""*#F,XAbٵ`-޺j.,$ *g6>>-X.>"Ӂ fҵ,($/z  32.*` !҉Fh~.r /o٭y%VԧYp,6r,T6(a *p?#()\)Cb!"\`W0V *ޯ?p!&C*CҠ p5/7#n]/01+!0 ƄJ؂A '^(av*"+.Jr؝H"B 0V/W!, 1 jR/ Үǖ:"r_$%%2љo*.+ A`@!qґr)k0q2 Ӳ-`+*/!zVooA֞"/bZ3b3-l,,.<|BN,7"( >s4036{>Wb720C2),W;>B."=0C"%&]?њ880WA(!B*|s8ϲA>t^E_~F*CK,E2e3"@(ZA#s#:a#B:u:.*,H07jߩ)]%,@R*v^uR4u"\7T5\W/ʊq^V0=4Y5~c85ѱRav\Uc *u$EA1\uVϲ\Gc잶KD8gwo8uxK,888Ǹ8׸8縎88_($/97?9GO9W_9go9w99999ǹ9׹9繞 9::'/:7?:GO:W_:gcz@;pyinotify/python2/docstrings/pyinotify._SysProcessEvent-class.html0000644000175000017500000005301511402071147025215 0ustar ookoiookoi pyinotify._SysProcessEvent
Module pyinotify :: Class _SysProcessEvent
[hide private]
[frames] | no frames]

Class _SysProcessEvent

source code


There is three kind of processing according to each event:

  1. special handling (deletion from internal container, bug, ...).
  2. default treatment: which is applied to the majority of events.
  3. IN_ISDIR is never sent alone, he is piggybacked with a standard event, he is not processed as the others events, instead, its value is captured and appropriately aggregated to dst event.
Instance Methods [hide private]
 
__init__(self, wm, notifier)
x.__init__(...) initializes x; see x.__class__.__doc__ for signature
source code
 
cleanup(self)
Cleanup (delete) old (>1mn) records contained in self._mv_cookie and self._mv.
source code
 
process_IN_CREATE(self, raw_event)
If the event affects a directory and the auto_add flag of the targetted watch is set to True, a new watch is added on this new directory, with the same attribute values than those of this watch.
source code
 
process_IN_MOVED_FROM(self, raw_event)
Map the cookie with the source path (+ date for cleaning).
source code
 
process_IN_MOVED_TO(self, raw_event)
Map the source path with the destination path (+ date for cleaning).
source code
 
process_IN_MOVE_SELF(self, raw_event)
STATUS: the following bug has been fixed in recent kernels (FIXME: which version ?).
source code
 
process_IN_Q_OVERFLOW(self, raw_event)
Only signal an overflow, most of the common flags are irrelevant for this event (path, wd, name).
source code
 
process_IN_IGNORED(self, raw_event)
The watch descriptor raised by this event is now ignored (forever), it can be safely deleted from the watch manager dictionary.
source code
 
process_default(self, raw_event, to_append=None)
Commons handling for the followings events:
source code

Inherited from _ProcessEvent: __call__, __repr__

Inherited from object: __delattr__, __format__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __setattr__, __sizeof__, __str__, __subclasshook__

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, wm, notifier)
(Constructor)

source code 

x.__init__(...) initializes x; see x.__class__.__doc__ for signature

Parameters:
  • wm (WatchManager instance) - Watch Manager.
  • notifier (Notifier instance) - Notifier.
Overrides: object.__init__

process_IN_MOVE_SELF(self, raw_event)

source code 

STATUS: the following bug has been fixed in recent kernels (FIXME: which version ?). Now it raises IN_DELETE_SELF instead.

Old kernels were bugged, this event raised when the watched item were moved, so we had to update its path, but under some circumstances it was impossible: if its parent directory and its destination directory wasn't watched. The kernel (see include/linux/fsnotify.h) doesn't bring us enough informations like the destination path of moved items.

process_IN_IGNORED(self, raw_event)

source code 

The watch descriptor raised by this event is now ignored (forever), it can be safely deleted from the watch manager dictionary. After this event we can be sure that neither the event queue nor the system will raise an event associated to this wd again.

process_default(self, raw_event, to_append=None)

source code 

Commons handling for the followings events:

IN_ACCESS, IN_MODIFY, IN_ATTRIB, IN_CLOSE_WRITE, IN_CLOSE_NOWRITE, IN_OPEN, IN_DELETE, IN_DELETE_SELF, IN_UNMOUNT.


pyinotify/python2/docstrings/class-tree.html0000644000175000017500000002566611402071145020656 0ustar ookoiookoi Class Hierarchy
 
[hide private]
[frames] | no frames]
[ Module Hierarchy | Class Hierarchy ]

Class Hierarchy

pyinotify/python2/docstrings/pyinotify.ChainIfTrue-class.html0000644000175000017500000003371511402071146024104 0ustar ookoiookoi pyinotify.ChainIfTrue
Module pyinotify :: Class ChainIfTrue
[hide private]
[frames] | no frames]

Class ChainIfTrue

source code


Makes conditional chaining depending on the result of the nested processing instance.

Instance Methods [hide private]
 
my_init(self, func)
Method automatically called from base class constructor.
source code
 
process_default(self, event)
Default processing event method.
source code

Inherited from ProcessEvent: __call__, __init__, nested_pevent, process_IN_Q_OVERFLOW

Inherited from _ProcessEvent: __repr__

Inherited from object: __delattr__, __format__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __setattr__, __sizeof__, __str__, __subclasshook__

Class Variables [hide private]

Inherited from ProcessEvent: pevent

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

my_init(self, func)

source code 

Method automatically called from base class constructor.

Parameters:
  • kargs - optional delegated arguments from __init__().
Overrides: ProcessEvent.my_init

process_default(self, event)

source code 

Default processing event method. By default does nothing. Subclass ProcessEvent and redefine this method in order to modify its behavior.

Parameters:
  • event - Event to be processed. Can be of any type of events but IN_Q_OVERFLOW events (see method process_IN_Q_OVERFLOW).
Overrides: ProcessEvent.process_default
(inherited documentation)

pyinotify/python2/docstrings/epydoc.js0000644000175000017500000002452511402071145017540 0ustar ookoiookoifunction toggle_private() { // Search for any private/public links on this page. Store // their old text in "cmd," so we will know what action to // take; and change their text to the opposite action. var cmd = "?"; var elts = document.getElementsByTagName("a"); for(var i=0; i...
"; elt.innerHTML = s; } } function toggle(id) { elt = document.getElementById(id+"-toggle"); if (elt.innerHTML == "-") collapse(id); else expand(id); return false; } function highlight(id) { var elt = document.getElementById(id+"-def"); if (elt) elt.className = "py-highlight-hdr"; var elt = document.getElementById(id+"-expanded"); if (elt) elt.className = "py-highlight"; var elt = document.getElementById(id+"-collapsed"); if (elt) elt.className = "py-highlight"; } function num_lines(s) { var n = 1; var pos = s.indexOf("\n"); while ( pos > 0) { n += 1; pos = s.indexOf("\n", pos+1); } return n; } // Collapse all blocks that mave more than `min_lines` lines. function collapse_all(min_lines) { var elts = document.getElementsByTagName("div"); for (var i=0; i 0) if (elt.id.substring(split, elt.id.length) == "-expanded") if (num_lines(elt.innerHTML) > min_lines) collapse(elt.id.substring(0, split)); } } function expandto(href) { var start = href.indexOf("#")+1; if (start != 0 && start != href.length) { if (href.substring(start, href.length) != "-") { collapse_all(4); pos = href.indexOf(".", start); while (pos != -1) { var id = href.substring(start, pos); expand(id); pos = href.indexOf(".", pos+1); } var id = href.substring(start, href.length); expand(id); highlight(id); } } } function kill_doclink(id) { var parent = document.getElementById(id); parent.removeChild(parent.childNodes.item(0)); } function auto_kill_doclink(ev) { if (!ev) var ev = window.event; if (!this.contains(ev.toElement)) { var parent = document.getElementById(this.parentID); parent.removeChild(parent.childNodes.item(0)); } } function doclink(id, name, targets_id) { var elt = document.getElementById(id); // If we already opened the box, then destroy it. // (This case should never occur, but leave it in just in case.) if (elt.childNodes.length > 1) { elt.removeChild(elt.childNodes.item(0)); } else { // The outer box: relative + inline positioning. var box1 = document.createElement("div"); box1.style.position = "relative"; box1.style.display = "inline"; box1.style.top = 0; box1.style.left = 0; // A shadow for fun var shadow = document.createElement("div"); shadow.style.position = "absolute"; shadow.style.left = "-1.3em"; shadow.style.top = "-1.3em"; shadow.style.background = "#404040"; // The inner box: absolute positioning. var box2 = document.createElement("div"); box2.style.position = "relative"; box2.style.border = "1px solid #a0a0a0"; box2.style.left = "-.2em"; box2.style.top = "-.2em"; box2.style.background = "white"; box2.style.padding = ".3em .4em .3em .4em"; box2.style.fontStyle = "normal"; box2.onmouseout=auto_kill_doclink; box2.parentID = id; // Get the targets var targets_elt = document.getElementById(targets_id); var targets = targets_elt.getAttribute("targets"); var links = ""; target_list = targets.split(","); for (var i=0; i" + target[0] + ""; } // Put it all together. elt.insertBefore(box1, elt.childNodes.item(0)); //box1.appendChild(box2); box1.appendChild(shadow); shadow.appendChild(box2); box2.innerHTML = "Which "+name+" do you want to see documentation for?" + ""; } return false; } function get_anchor() { var href = location.href; var start = href.indexOf("#")+1; if ((start != 0) && (start != href.length)) return href.substring(start, href.length); } function redirect_url(dottedName) { // Scan through each element of the "pages" list, and check // if "name" matches with any of them. for (var i=0; i-m" or "-c"; // extract the portion & compare it to dottedName. var pagename = pages[i].substring(0, pages[i].length-2); if (pagename == dottedName.substring(0,pagename.length)) { // We've found a page that matches `dottedName`; // construct its URL, using leftover `dottedName` // content to form an anchor. var pagetype = pages[i].charAt(pages[i].length-1); var url = pagename + ((pagetype=="m")?"-module.html": "-class.html"); if (dottedName.length > pagename.length) url += "#" + dottedName.substring(pagename.length+1, dottedName.length); return url; } } } pyinotify/python2/docstrings/pyinotify.ProcessEventError-class.html0000644000175000017500000002622111402071146025367 0ustar ookoiookoi pyinotify.ProcessEventError
Module pyinotify :: Class ProcessEventError
[hide private]
[frames] | no frames]

Class ProcessEventError

source code


ProcessEventError Exception. Raised on ProcessEvent error.

Instance Methods [hide private]
 
__init__(self, err)
x.__init__(...) initializes x; see x.__class__.__doc__ for signature
source code

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__, __unicode__

Inherited from object: __format__, __hash__, __reduce_ex__, __sizeof__, __subclasshook__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

Method Details [hide private]

__init__(self, err)
(Constructor)

source code 

x.__init__(...) initializes x; see x.__class__.__doc__ for signature

Parameters:
  • err (string) - Exception error description.
Overrides: object.__init__

pyinotify/python2/docstrings/uml_class_diagram_for_pyinotif_10.gif0000644000175000017500000002247711402071146025150 0ustar ookoiookoiGIF87a`0|LBDĤBDTĂ$"$b\Ģd^\bdT.,|ܲ,rd dJD<2,|^TܪvltĖ&$RT̪tTJD64D:4j\Ě 4&$rdܺԦlfd~|dRT\F<~t| RT̞tZTrl|fdԌ:<TB<̔NLjdD2,ܔ*,L:44.,z|쾼lRL Ċ,"̢jl|䲤,|bdԪ\JDjl 亼Ԣ$t~tZ\̚t^TTFL4>Yb VZŭ@UhV)_n_2& dWGAvC#  LG_B$'IJZҒ.Nz0hd#m`*i+0T$B#@W$ C/1CjыlLEShP4%  d`4ɐ " B.xr"D A ss$:Ns&8Yal@@ ~[HBL uA!'F3΍r6C*Ri<)Jҕڲ.u%LczʙҴ6GӞ@ PJԢHE*Ԧ:P*R.YXj z`!ڌhMZֶp5`ᆸծ]Zw׾oX+ΚH|#~],dZg,Y1J֬`Fg{ώw,a ֒_k07 u-6he 4rkP{0kqxwreD @abŵmj}U7MAd W5C3aV oD}!jì`~X\"F(2WͰ\K^jZq R W$NAeK`ApaVhl .sܵ ?0X5}[;^w fgc0$Y[1k iV\2z \{f(ɕzQ5*l4>%n"Р36p:m'a0'$l j? BI$7Ґ氓=JM vk PhE'ahmf`ɵZU5g#MIN7d='sZM%w>7d|w@oO;'N[P GN`O+p{0gug^8kr5@ˮ8HwsStZ:P3%a@ϸu[Nzv]5G]:n& \셰?8s+ꧣNz<2^_kP=jgX!/u˳L>mVXS.Wrx 'GXKq8Xxq'ssׁ"(^Ht!(^(?W \dR}hY0dVLwutwff^D8o`bfYА0UhW{W{QV>h>| a p(QhY\z!\EmevvUw?\[yeWu(v^G][7lkHviVmfGe` cf[[cGma7lk` 'Yf @E[ Y\7n@vB8ofamE`wf~vowHw {x}GZ3Xl_E_{wX`f@\P e`hV@?wdczw&fc8vVh9oWddBFdGZ0lvgyyc֐Hϰd& $<X{ňe޶g[e_ye`jyhGfVvy?𔟧[(e e^pIeQ)Y=)f_s9p% Ph}^\z'hu Z?FY)b'_pVu  uhՖf% W]YW*ej{{)^ |fk|89 Y&_6IkX`fen qp YnH6)YwWpmݵmV}9Yz|Zm&}ߙ9vVycF}n8?`x `n liVȜk wsZn0j 5kЌ%zszZ_ VJu5:? 0nۅaV759~79:ʇh:ځf1DFZHTѤN P:RƨhՂHX\2V:hVaZ}ՃNZRqCVF܅5FVVxՅgz闣{xVexvjVtsX3J}IQv `f u(` vƕȈulX苡 l)_? vސwfY`s7chuuu$zUwkVfbhʞ:fE:Y& R +ْ/cUgGn {Iy<f?hWW2RkU ~fϠ!jYjef)h%K[Y^`jxgVijn fٛ ¹fiZ Yj}nY񊲒%fEɟ\{ꭗV_U^ V jW}mYX:ZV#mVXyW, o03V5:O[~۹M}{ŗK{(.W0sfz{}զpY+ۯ}ȧflHxyV*H[jqeةkU]']ȾXvG_p (D WʏΪVXwOۣŬ֣ĸr|) 1 ܝGїmǍpׇlǗI3|oݗ_ Ѝ2uf$g+jHhM%v!H"g:֍ Fܢ.hQrڡMҁC+i\fIߘKӛ>T 9dpÆ$RKX(oOJ 0!)p?oa7]k6NpɫF\L7|VWrmҌCE q0PawP:KwG>7p&@B HsZy0teM y_`hvlU0PQR;F T"@/ <!ӖF.3 &?"Da XB,/ Yh ^`ΐ28D"шGDbߐ(щOb؁nHъWb=@Hdщ=ab88F2ь3эo|#8юw P J!l (ZRj$@>#6 Ena]Za Das[@RAsi HtjnwKY ڥ. I[HoF 5cݗ`*+Rx_TT9_[d̠!u è)'lO#"T HQX 7X Fczbb[lUSZ5vƇD~Q؍2;Uc1kb Xܗ54),) jE{݊ [@mJxMFWWAkKf#_`u3Q0FFňu`@=4Gin1FYnD 7vj (S"@31kZַ5[u=lbؾ<(V6`l vmnw=mrFikwieƷ-vsow}ps >gx@\7x©p;xE?<#Gy5nڱx/\7bt Rqmk覹olnTpwv^EJ¶cAֹ^l5 Sr%U`R.a/iulOJp߱5C^5zŋ=ݒ_lB wyO ܽxUdY!|q?K,׮6 _ X0G|v@x?͢|Ћ̯p hc7n[<.ۿksP>620+02?ғ+\ O >=+T4@~6Z>s.kA#ԽŃBX(:jT(.ACʛ=)dB'A+H\H?sA (+( +B-T&(oLcKmI|LPHOmkOk;m׌͌, HcHd츓 9ދNа̷ﴌO+L0ϙɓ7OKOψOώϢσO8MeЂ+PPsP|ПЛСPP P84NUѨ%PUOEPOQ Y#5d7@&ucdF'*mRi5W#S.#.0S,m253E4U5e6u789:;<=>S ;pyinotify/python2/docstrings/pyinotify-module.html0000644000175000017500000010053211402071145022113 0ustar ookoiookoi pyinotify
Module pyinotify
[hide private]
[frames] | no frames]

Module pyinotify

source code

pyinotify


Author: Sebastien Martini

License: MIT License

Contact: seb@dbzteam.org

Version: 0.9.0

Classes [hide private]
  PyinotifyError
Indicates exceptions raised by a Pyinotify class.
  UnsupportedPythonVersionError
Raised on unsupported Python versions.
  UnsupportedLibcVersionError
Raised on unsupported libc versions.
  PyinotifyLogger
Pyinotify logger used for logging unicode strings.
  UnicodeLogRecord
  SysCtlINotify
Access (read, write) inotify's variables through sysctl.
  EventsCodes
Set of codes corresponding to each kind of events.
  _Event
Event structure, represent events raised by the system.
  _RawEvent
Raw event, it contains only the informations provided by the system.
  Event
This class contains all the useful informations about the observed event.
  ProcessEventError
ProcessEventError Exception.
  _ProcessEvent
Abstract processing event class.
  _SysProcessEvent
There is three kind of processing according to each event:
  ProcessEvent
Process events objects, can be specialized via subclassing, thus its behavior can be overriden:
  PrintAllEvents
Dummy class used to print events strings representations.
  ChainIfTrue
Makes conditional chaining depending on the result of the nested processing instance.
  Stats
Compute and display trivial statistics about processed events.
  NotifierError
Notifier Exception.
  Notifier
Read notifications, process events.
  ThreadedNotifier
This notifier inherits from threading.Thread for instanciating a separate thread, and also inherits from Notifier, because it is a threaded notifier.
  AsyncNotifier
This notifier inherits from asyncore.file_dispatcher in order to be able to use pyinotify along with the asyncore framework.
  Watch
Represent a watch, i.e.
  ExcludeFilter
ExcludeFilter is an exclusion filter.
  WatchManagerError
WatchManager Exception.
  WatchManager
Provide operations for watching files and directories.
  Color
Internal class.
Functions [hide private]
 
_strerrno() source code
 
STRERRNO() source code
 
logger_init()
Initialize logger instance.
source code
 
compatibility_mode()
Use this function to turn on the compatibility mode.
source code
 
command_line()
By default the watched path is '/tmp' and all types of events are monitored.
source code
Variables [hide private]
  __author__ = 'seb@dbzteam.org (Sebastien Martini)'
  COMPATIBILITY_MODE = False
  LIBC = <CDLL 'libc.so.6', handle 400517f8 at 928cfac>
  LIBC_VERSION = '2.10.1'
  log = logger_init()
  ALL_EVENTS = 4095
  IN_ACCESS = 1
  IN_ATTRIB = 4
  IN_CLOSE_NOWRITE = 16
  IN_CLOSE_WRITE = 8
  IN_CREATE = 256
  IN_DELETE = 512
  IN_DELETE_SELF = 1024
  IN_DONT_FOLLOW = 33554432
  IN_IGNORED = 32768
  IN_ISDIR = 1073741824
  IN_MASK_ADD = 536870912
  IN_MODIFY = 2
  IN_MOVED_FROM = 64
  IN_MOVED_TO = 128
  IN_MOVE_SELF = 2048
  IN_ONESHOT = 2147483648
  IN_ONLYDIR = 16777216
  IN_OPEN = 32
  IN_Q_OVERFLOW = 16384
  IN_UNMOUNT = 8192
  __package__ = None
  attrname = 'max_user_watches'
  flagc = 'EVENT_FLAGS'
  max_queued_events = <max_queued_events=16384>
  max_user_instances = <max_user_instances=128>
  max_user_watches = <max_user_watches=8192>
  name = 'IN_UNMOUNT'
  val = 8192
  valc = {'IN_IGNORED': 32768, 'IN_Q_OVERFLOW': 16384, 'IN_UNMOU...
Function Details [hide private]

compatibility_mode()

source code 

Use this function to turn on the compatibility mode. The compatibility mode is used to improve compatibility with Pyinotify 0.7.1 (or older) programs. The compatibility mode provides additional variables 'is_dir', 'event_name', 'EventsCodes.IN_*' and 'EventsCodes.ALL_EVENTS' as Pyinotify 0.7.1 provided. Do not call this function from new programs!! Especially if there are developped for Pyinotify >= 0.8.x.

command_line()

source code 

By default the watched path is '/tmp' and all types of events are monitored. Events monitoring serves forever, type c^c to stop it.


Variables Details [hide private]

valc

Value:
{'IN_IGNORED': 32768, 'IN_Q_OVERFLOW': 16384, 'IN_UNMOUNT': 8192}

pyinotify/python2/docstrings/uml_class_diagram_for_pyinotif_5.gif0000644000175000017500000001514611402071146025067 0ustar ookoiookoiGIF87aULBDĢ$"$tbd<24dRTܲrt4&$jl \JL̪D:<侼Ԝ~|<.,ĞL>2Q@Wu3 I&mn>{:]cismq]£պu<7<Ũ04JzsI(A`yH+@!RЮ71)Y`zd@*P*T%%LVSFj<'d nRP5o##HVUc!a@75.bI1r$ChΔo|3%9v#iQKUml0?2\FѶ;[6@Ҷu6$k5s:k;{@ntIJ})azh7|nW1wVv~x;JA4GjnO;^-xٯ_c%IV 1AyZ~;l}MR{AlX#nwtˆYאw`nM=u"kc5՚'ûbc|UۡJDk{x/iU/ vz|wryR/Sq~q,gc;C(AprBAE3TGzremt 'ADd\Uet8uvgjVoWrvuTWw:f5}"FxHxM(S~Lxh.^H"7YRW~@iGeyyEC0t80Y&['L|FgnX16kz@#4E{ሸ6zs3a0|C5VA`Y&mϖK!my5}T}w8gUطO}1BrREoS7H~[~fs)W>t=C=-B%8=pCap"1LY X9Xn(48]TfIBB2B!D8)ہsU'sKvZDC\:K7VtumXV!HWq5x$(2, .24YTYxux0 G6xiF93K@jKgLu; aU ?![VQ olGAwdL զ]a5B$A°"覗 Q) !Brp=׌iY5@ ##H?2rɋ8(-=prYIH(N'av_1`ӅHGI&U%XeF7t+q)}(9F幞9099y6;a(p--6z.-l=)J8P@)1.NrlXVj 030 {HLݨ1L#!1F@KPO:;01\ٕfS4VQ0![J 0bIwj{j?96lXa6:3BV CYVTٗf;P9x.~*ÎˢC0ڑY0TeÜf ;sݖ)9>p,F970IHCIֈ:J1 ap:3+C)6Wu*@ 3-j@ T9e]?C N "zڋʩ0ABf#C$dBZF "C3b,r5™XZ+BRjٜLD&[dESdMtFIF#i42'A9@Ggsӝx_BwNbe:K<;DkF9KM{🵓x%:c@kZy z1# L7j=@6:ɕxK@?J3D47MQS:;c 8Ƥ\zK^3f7dl:n #f'{rx>mTyKY:OU{Z?zY݇gqHл֛ xey .Ҹa>דԿ+ eͪd8jҫ=::^`ம' ,~LNT[>^C Uړ"L¤N+| H&M8Ʋ'k#*%>3g%$ !)VHRhNIFC:5(vGsgpkhp֭ ~>uEuGIgMgOogQ?gE]IbN^n~  e;O_o h<@Q:Dpᯂ+ZQ in5"GFj\dQ#T#=!'UKbFl9Ć7J&th:,jBC<0醧QV tiSCXa *eTWC4\ I㡣(vXcE%b \@ ;DO$ӠlsƏ#OF"(1dӨ/g管GQЍ/p$ F ].CN]x:yt;wvX@G7G2@<Ȁ (V)pG&XRw6`PL}&DX!DK+^W QCHcyH@ߐYc#7 r-d:G%kdpum٥>!E,^)&teIsTCP9xD@ Q 6аsPxHYyFT  ,[0'j$5!LvM.; (l8{ ^ mz%Kn枋>8 oKoދoojLpp /p? qOLq_qoq r"Lrɾ;pyinotify/python2/docstrings/uml_class_diagram_for_pyinotif_25.gif0000644000175000017500000001566311402071147025156 0ustar ookoiookoiGIF87allRL<.,BD<Ălfd"$LB<̢ܲjdlbdĔFD$vtT.,24\NL̪  Ě|D:4,&$t^T\F<\JDd","!|b[L><̖rdܮvtĤNLĎܬ~| &$nl64^\.,><Ԧ̞̦ ̌ԮLBDD:S>B8b(̳f|¢xuq'|!(uHuYxaX!uo$aI,XJR!22 bfN<ei{O~WS:g֕9NY|fF:)&aNUj x,x6K΃&gD gΫf',ÑZjVzprAp>ጣq`d⒄xkm-v d-}Qlǚ5z 'O-Pz"Y [f 1tCnƋ쩢b WnEo(2!Ǝ,UZh+l3g- Y|@Ö/^H'L XcXg\w`- WI}A th'6Ulmp]S} P|K7S'AGЌ#8TK9jWM褗nz[O{LQM.^oǝnT$R(ppyksg?J%\4l_gkIyMO <L:R gg3E-Lu3?~CS}Jc )H 3KXȩE.  8lD )F3i~x HF bՔt1| oB@SY-M!n<ӈQOsӝH M:( tUc^̈́̚H$ ):ѓP(iRXR')U)XR'1hZSt'9թxST'AjЈZTtw#!t.}'}c}c*V'rԜ$ep֫u#e Ѕ)3Nu+>uD%q\ED ZDXp;j쑄M%\FxUdk&0nBg?kda؀DfRi7)Z). cdg>\tJbuq+b[V]D& k[ߺ2nW%E t91MZ*/g)Nl{IݘX'v*09~QP4tu0D LT(!.J6XKTQqKXbe 1Kh\㔽qJr:CH9 wc 'D(a LwA5I2hN34 EPL:ۙΌx5Q;y`ΈR 4L$3 D5kt#*_Ȅ3q / ^Kc_0,C78 !KDE&1\\F6 =sƛ ܺT k+7x!8qN cx9=AӐ pt*ؐCAp}{ݞ{8-X"Y7\1lfB yHMl͜ ,lofKX[6e5gϊpm`:/ȅ@ڽ0 ޜal]zŴߐ?@_9@LK7!Yxx3h nDfX莗ߌqohěPkopo ^~5q 1opBړ$ x fkPکrx |Xwfrb WN(_ Wn.fn`02QЮqXA9 JiJ و~QJI yxx)rXǘ"qHuކ0 y` ~n zxmx0L(w'qH戎ȨuꝎ h0n@Ρ_9n G`G.Ό8.YEW|:oyP 0'(ۗJ3ISɖqx./ߊ)t߆0 StiymQ/o[lp/Hijo( jC'JKN;IOɠ fʀ'?y 94nHJeZiJ>Z?7Oz8ɟz**|InA+0,HP! IfV20qP#>\Y@m%MDRJ&# I0} ۸0B?1+D6SO==ӣ4TSOERQ 4UWqUH}V[CU=lWW3u1}X. 61ZevS\EifXhOjZ?BڤՖgUkpϭkE?uU\mq^}U$vּ~wZカ` mxx^IQEZ/F7bhݔ&894dOFZܗQ"dmWe9gfg5p&y}fv\{FWWZۧh:kkr&lϞK`_Bm>jàn;oo)o'pbg|Ĺ:r'r!y;pyinotify/python2/docstrings/uml_class_diagram_for_pyinotif_22.gif0000644000175000017500000001756411402071147025155 0ustar ookoiookoiGIF87a|LBDĤBDĆ$"$d^\Ԧjdbd|dJDT., <2,ܶĖvt|^TĞTJDܪtvl$j\RT4&$&$D:4ԢԮdRTĞ \F<̦rd64tZTnd쾼|fdԌ~tTB< Ԧ<24TJL$jdD:< \FD~|TBD\JLL:<,"$vt̞TFDdNL|b\zt4*,t^\lVT,W H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳC JѣH*]ʴӧPzڤիXjʵׯ`ÊK$SZ˶۷p c ݻCs-AvZ~W0!/h;bPkq+%*#Nlrdi97,.i J".kMOk!c#B4r:haB}i|"TҬM-WXY4wNmܫ}#W\UuG (ZnA|)(Mւ >xs-x_e_`xDMh@C0ʸ!UR_ Hd'j-jA tJe5ni_k]d&il%mBlG%ekY斃&Ii`hD iHPm':f+$^~ D`'몭 _om):[h]Wn[u([WXt1*JJmi,kQ1/mz,J mY-']fQ!t-k,jH 0*B#(/+@mܱ ,[|p 7!1>e&Q FA׈DVL.7I%qFP+IH\Qd^-C|G'tA-5Vct[sF k'dQ#2ywh_礗n][KTǮG#\/o|{`7ӈH4B+kpZ6ӵDqm5zϞ;SBƢ^^ԍcD@:iU \zƤU}_]dֶG׺xҳ6r4_ X> 5 [ÙD/Vebcf`X3cHڅfL#SI~4 --E?@1x@0 U3Pɰ)@}"G~ `Ks6hCF5t %lp S*6' h _*z٥Ůc0c3K &cayضa(fV+ۗD6 mPӼEm27ֲ %f(// X`4KЏ}tgnռͭQjVֹoҍ`E,&Rb> 4>7}iV-^M2̎ ׄhEBX Aox;F}o 񬻤iOz +S6riw- ,uײ54}BRxVq,23PMlQtznq%S#-rs1vyFd2s5F}>g8G>:G{kmcotM5>CEzv~dSttQgap 4u-8gGu.N9P3T8VhmgYo8wYքgW9y8{7JօZCxb~aixrKQC!M#jaysYkyL؆v1z$bMv$'zX${qQlDmNn(]'/{XVdB}BTCwnG-h~f\~%on!Q)oъ!hhsRP$0 /gg(ƀeWd7-VSJ4oqsHu9P4'%>'B,((0@35hS긎1}ItTu:Bȁ!~Hx Duǒ0?8-yI6<2Vv!YUvE9e:tIN)?VKUoQK[L0kW\ǥ$hz{e]M9Ȧ])ƊHt}x~}~!.Dn5Ռg'~ &>lAqaW3R1v<7#S*rvc<7+F )GGFY)Ld$)OFF;ɓOU Nٝ1Y99~QBY:BNtVT9JLSI9QSRd[W9'ɱ_Y4Ɵ)f$V'{ Zvl .^T rHIJc/vИ' Y37SvQrМt[|tdY/)醆FztH#Guՙ l;-rzkZF}p|* Dwj8f-* 9SʥVkwiv]KE~!ʎ!\6kkrIUi(ɦ㥙[ZBফHɘ}ιʘFQoiأՑpۈaHp-h!6b%ڑ8caqAӉd;wJxj [+wgJf&wY}ѨSjw^?ѩc5;*t!\D䖱zq걵 (]$J"}y^ӗkHv:E$mڀ_{ϊݲ.Bo$"o9Uȍ"u*ݚ##23ɯI8qqrX#K)sBtv$m<8\bj=#)ui@*k; ۝˓~б]u$J(Uٲ/1[UY[~AytQ{OQNORoqѵ˽onעuV;Djۍߺp!.{k7vl!л =7gzy+Vl'<) +̒-|*+- K:3˷99;ܼp񼣋f6ux#4W[:j?{A Ď+R%5x1Rh\Lۯ[LB[Т/]{`Ş Z9_^חxpѶmtL~[{m{}&33S`+mx7ocQ5{z@ |Ĩ*tiָܸӺMV° М/9.ID<\l>A@ \|,<]>cP_ 0]5T 1T U&UF Pp0}&P 01# 0L`B(`0I X0L$ @=` M]1Qm\IQGdLPV` je 0t]5 x]S0yׂ==؃]؆׈y، ׎eْՔ]V}٘ԚCٞӠ1=ڤڪڬڮڰۯ s-۶}۸}BpA%^P:k9CfݷŭpܤSv9HV9 ح8݂XU<@ aCg潕ѳe4m}ܝzJIRz! ,L=@dmn!aѤN/N%nݗ'S(-N`$jZ| -q!^܍}+cfCe{b[ENkM~*;N܍-n4/8>80^cV>-ε3ݢi ɇ6y %3%Ս^N0D,q3s.<3nh.mOOqJZ5S )*˝Q778\CkynܓcԣٍF01нz뺾uV./Ai-nˎ.۸ގ;>^.N>p12a,7m.&KD  }@ {?=faAOFK\śG 06yja Ap 3p{ ]f Jip޷(E[DEZK` } r468F}n*-nR^pb8l^`wZrL) ,[%rpr@3AS<0ʇs&n~o",>+_ϒ.ޝ@tO/>uR^S@@ (JB >Q"A-^ĘQF7* H%I RJ-]t0męSN Qh2DOEEЊSz$UԈ@¢) U]TҪQv|EV-BF)j\^ߨZ(}U@*:ERUnX䔘4PeΝWe(0a+VM+R j֡ 8"[^ml}o%~\9˝Sm\zӭ~]{۽]C,^շwo~|jǟ_~G^ @D0?`0B 'B /0C 7B%G$`D4@cD 0QDFbADDG @$RD'Q= dhGK@Fd+/$sD#L_FT 5FE14)1,L>̩1I.Ԑ$ lAKr.r?P!D0hADDb0J/TS>v1UW1t+\eKM)FS1X@&ca@HA"4LCZE%4$ QG< .PU.$sCb\s5MFx\EE<.5-jas .!&$Z0S%aZTaD9D.DIsS9!0VeeYDTd+%TD:: YJMA 5t.\΁ [$Q#F kmc%\y>huҕE%nT[SjjN_pїa.hY+'\)zKEeR\ss`F$R'$e*UhʜR +q֥-3 + 7+ūp %$K$JR0Wgv+T0 0N$d&c?b٬jeM%x0N_Kf &f1h!VYo9#&er; Wre.w_st=hB};pyinotify/python2/docstrings/help.html0000644000175000017500000002473511402071145017540 0ustar ookoiookoi Help
 
[hide private]
[frames] | no frames]

API Documentation

This document contains the API (Application Programming Interface) documentation for this project. Documentation for the Python objects defined by the project is divided into separate pages for each package, module, and class. The API documentation also includes two pages containing information about the project as a whole: a trees page, and an index page.

Object Documentation

Each Package Documentation page contains:

  • A description of the package.
  • A list of the modules and sub-packages contained by the package.
  • A summary of the classes defined by the package.
  • A summary of the functions defined by the package.
  • A summary of the variables defined by the package.
  • A detailed description of each function defined by the package.
  • A detailed description of each variable defined by the package.

Each Module Documentation page contains:

  • A description of the module.
  • A summary of the classes defined by the module.
  • A summary of the functions defined by the module.
  • A summary of the variables defined by the module.
  • A detailed description of each function defined by the module.
  • A detailed description of each variable defined by the module.

Each Class Documentation page contains:

  • A class inheritance diagram.
  • A list of known subclasses.
  • A description of the class.
  • A summary of the methods defined by the class.
  • A summary of the instance variables defined by the class.
  • A summary of the class (static) variables defined by the class.
  • A detailed description of each method defined by the class.
  • A detailed description of each instance variable defined by the class.
  • A detailed description of each class (static) variable defined by the class.

Project Documentation

The Trees page contains the module and class hierarchies:

  • The module hierarchy lists every package and module, with modules grouped into packages. At the top level, and within each package, modules and sub-packages are listed alphabetically.
  • The class hierarchy lists every class, grouped by base class. If a class has more than one base class, then it will be listed under each base class. At the top level, and under each base class, classes are listed alphabetically.

The Index page contains indices of terms and identifiers:

  • The term index lists every term indexed by any object's documentation. For each term, the index provides links to each place where the term is indexed.
  • The identifier index lists the (short) name of every package, module, class, method, function, variable, and parameter. For each identifier, the index provides a short description, and a link to its documentation.

The Table of Contents

The table of contents occupies the two frames on the left side of the window. The upper-left frame displays the project contents, and the lower-left frame displays the module contents:

Project
Contents
...
API
Documentation
Frame


Module
Contents
 
...
 

The project contents frame contains a list of all packages and modules that are defined by the project. Clicking on an entry will display its contents in the module contents frame. Clicking on a special entry, labeled "Everything," will display the contents of the entire project.

The module contents frame contains a list of every submodule, class, type, exception, function, and variable defined by a module or package. Clicking on an entry will display its documentation in the API documentation frame. Clicking on the name of the module, at the top of the frame, will display the documentation for the module itself.

The "frames" and "no frames" buttons below the top navigation bar can be used to control whether the table of contents is displayed or not.

The Navigation Bar

A navigation bar is located at the top and bottom of every page. It indicates what type of page you are currently viewing, and allows you to go to related pages. The following table describes the labels on the navigation bar. Note that not some labels (such as [Parent]) are not displayed on all pages.

Label Highlighted when... Links to...
[Parent] (never highlighted) the parent of the current package
[Package] viewing a package the package containing the current object
[Module] viewing a module the module containing the current object
[Class] viewing a class the class containing the current object
[Trees] viewing the trees page the trees page
[Index] viewing the index page the index page
[Help] viewing the help page the help page

The "show private" and "hide private" buttons below the top navigation bar can be used to control whether documentation for private objects is displayed. Private objects are usually defined as objects whose (short) names begin with a single underscore, but do not end with an underscore. For example, "_x", "__pprint", and "epydoc.epytext._tokenize" are private objects; but "re.sub", "__init__", and "type_" are not. However, if a module defines the "__all__" variable, then its contents are used to decide which objects are private.

A timestamp below the bottom navigation bar indicates when each page was last updated.

pyinotify/python2/docstrings/redirect.html0000644000175000017500000000333011402071147020377 0ustar ookoiookoiEpydoc Redirect Page

Epydoc Auto-redirect page

When javascript is enabled, this page will redirect URLs of the form redirect.html#dotted.name to the documentation for the object with the given fully-qualified dotted name.

 

pyinotify/python2/docstrings/pyinotify.Stats-class.html0000644000175000017500000004522211402071146023035 0ustar ookoiookoi pyinotify.Stats
Module pyinotify :: Class Stats
[hide private]
[frames] | no frames]

Class Stats

source code


Compute and display trivial statistics about processed events.

Instance Methods [hide private]
 
my_init(self)
Method automatically called from base class constructor.
source code
 
process_default(self, event)
Processes |event|.
source code
 
_stats_copy(self) source code
 
__repr__(self)
repr(x)
source code
 
dump(self, filename)
Dumps statistics to file |filename|.
source code
 
__str__(self, scale=45)
str(x)
source code

Inherited from ProcessEvent: __call__, __init__, nested_pevent, process_IN_Q_OVERFLOW

Inherited from object: __delattr__, __format__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __setattr__, __sizeof__, __subclasshook__

Class Variables [hide private]

Inherited from ProcessEvent: pevent

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

my_init(self)

source code 

Method automatically called from base class constructor.

Parameters:
  • kargs - optional delegated arguments from __init__().
Overrides: ProcessEvent.my_init

process_default(self, event)

source code 

Processes |event|.

Parameters:
  • event - Event to be processed. Can be of any type of events but IN_Q_OVERFLOW events (see method process_IN_Q_OVERFLOW).
Overrides: ProcessEvent.process_default

__repr__(self)
(Representation operator)

source code 

repr(x)

Overrides: object.__repr__
(inherited documentation)

dump(self, filename)

source code 

Dumps statistics to file |filename|.

Parameters:
  • filename (string) - pathname.

__str__(self, scale=45)
(Informal representation operator)

source code 

str(x)

Overrides: object.__str__
(inherited documentation)

pyinotify/python2/docstrings/pyinotify.ThreadedNotifier-class.html0000644000175000017500000005214411402071146025160 0ustar ookoiookoi pyinotify.ThreadedNotifier
Module pyinotify :: Class ThreadedNotifier
[hide private]
[frames] | no frames]

Class ThreadedNotifier

source code


This notifier inherits from threading.Thread for instanciating a separate thread, and also inherits from Notifier, because it is a threaded notifier.

Note that every functionality provided by this class is also provided through Notifier class. Moreover Notifier should be considered first because it is not threaded and could be easily daemonized.

Instance Methods [hide private]
 
__init__(self, watch_manager, default_proc_fun=None, read_freq=0, threshold=0, timeout=None)
Initialization, initialize base classes.
source code
 
stop(self)
Stop notifier's loop.
source code
 
loop(self)
Thread's main loop.
source code
 
run(self)
Start thread's loop: read and process events until the method stop() is called.
source code

Inherited from threading.Thread: __repr__, getName, isAlive, isDaemon, is_alive, join, setDaemon, setName, start

Inherited from threading.Thread (private): _set_daemon, _set_ident

Inherited from threading._Verbose (private): _note

Inherited from Notifier: append_event, check_events, coalesce_events, proc_fun, process_events, read_events

Inherited from Notifier (private): _sleep

Inherited from object: __delattr__, __format__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __setattr__, __sizeof__, __str__, __subclasshook__

Properties [hide private]

Inherited from threading.Thread: daemon, ident, name

Inherited from object: __class__

Method Details [hide private]

__init__(self, watch_manager, default_proc_fun=None, read_freq=0, threshold=0, timeout=None)
(Constructor)

source code 

Initialization, initialize base classes. read_freq, threshold and timeout parameters are used when looping.

Parameters:
  • watch_manager (WatchManager instance) - Watch Manager.
  • default_proc_fun (instance of ProcessEvent) - Default processing method. See base class.
  • read_freq (int) - if read_freq == 0, events are read asap, if read_freq is > 0, this thread sleeps max(0, read_freq - timeout) seconds.
  • threshold (int) - File descriptor will be read only if the accumulated size to read becomes >= threshold. If != 0, you likely want to use it in combination with an appropriate value set for read_freq because without that you would keep looping without really reading anything and that until the amount of events to read is >= threshold. At least with read_freq you might sleep.
  • timeout (int) - see http://docs.python.org/lib/poll-objects.html#poll-objects
Overrides: object.__init__

stop(self)

source code 

Stop notifier's loop. Stop notification. Join the thread.

Overrides: Notifier.stop

loop(self)

source code 

Thread's main loop. Don't meant to be called by user directly. Call inherited start() method instead.

Events are read only once time every min(read_freq, timeout) seconds at best and only if the size of events to read is >= threshold.

Parameters:
  • callback - Functor called after each event processing iteration. Expects to receive the notifier object (self) as first parameter. If this function returns True the loop is immediately terminated otherwise the loop method keeps looping.
  • daemonize - This thread is daemonized if set to True.
  • args - Optional and relevant only if daemonize is True. Remaining keyworded arguments are directly passed to daemonize see __daemonize() method.
Overrides: Notifier.loop

run(self)

source code 

Start thread's loop: read and process events until the method stop() is called. Never call this method directly, instead call the start() method inherited from threading.Thread, which then will call run() in its turn.

Overrides: threading.Thread.run

pyinotify/python2/docstrings/pyinotify.PyinotifyLogger-class.html0000644000175000017500000003215611402071146025073 0ustar ookoiookoi pyinotify.PyinotifyLogger
Module pyinotify :: Class PyinotifyLogger
[hide private]
[frames] | no frames]

Class PyinotifyLogger

source code


Pyinotify logger used for logging unicode strings.

Instance Methods [hide private]
 
makeRecord(self, name, level, fn, lno, msg, args, exc_info, func=None, extra=None)
A factory method which can be overridden in subclasses to create specialized LogRecords.
source code

Inherited from logging.Logger: __init__, addHandler, callHandlers, critical, debug, error, exception, fatal, findCaller, getEffectiveLevel, handle, info, isEnabledFor, log, removeHandler, setLevel, warn, warning

Inherited from logging.Logger (private): _log

Inherited from logging.Filterer: addFilter, filter, removeFilter

Class Variables [hide private]

Inherited from logging.Logger: manager, root

Method Details [hide private]

makeRecord(self, name, level, fn, lno, msg, args, exc_info, func=None, extra=None)

source code 

A factory method which can be overridden in subclasses to create specialized LogRecords.

Overrides: logging.Logger.makeRecord
(inherited documentation)

pyinotify/python2/docstrings/pyinotify.SysCtlINotify-class.html0000644000175000017500000004573211402071146024470 0ustar ookoiookoi pyinotify.SysCtlINotify
Module pyinotify :: Class SysCtlINotify
[hide private]
[frames] | no frames]

Class SysCtlINotify

source code


Access (read, write) inotify's variables through sysctl. Usually it requires administrator rights to update them.

Examples:

  • Read max_queued_events attribute: myvar = max_queued_events.value
  • Update max_queued_events attribute: max_queued_events.value = 42
Instance Methods [hide private]
 
__init__(self, attrname)
x.__init__(...) initializes x; see x.__class__.__doc__ for signature
source code
int
get_val(self)
Gets attribute's value.
source code
 
set_val(self, nval)
Sets new attribute's value.
source code
 
__repr__(self)
repr(x)
source code

Inherited from object: __delattr__, __format__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __setattr__, __sizeof__, __str__, __subclasshook__

Class Variables [hide private]
  inotify_attrs = {'max_queued_events': 3, 'max_user_instances':...
Properties [hide private]
int value
Gets attribute's value.

Inherited from object: __class__

Method Details [hide private]

__init__(self, attrname)
(Constructor)

source code 

x.__init__(...) initializes x; see x.__class__.__doc__ for signature

Overrides: object.__init__
(inherited documentation)

get_val(self)

source code 

Gets attribute's value.

Returns: int
stored value.

set_val(self, nval)

source code 

Sets new attribute's value.

Parameters:
  • nval (int) - replaces current value by nval.

__repr__(self)
(Representation operator)

source code 

repr(x)

Overrides: object.__repr__
(inherited documentation)

Class Variable Details [hide private]

inotify_attrs

Value:
{'max_queued_events': 3,
 'max_user_instances': 1,
 'max_user_watches': 2}

Property Details [hide private]

value

Gets attribute's value.

Get Method:
get_val(self) - Gets attribute's value.
Set Method:
set_val(self, nval) - Sets new attribute's value.
Type:
int

pyinotify/python2/docstrings/pyinotify.UnicodeLogRecord-class.html0000644000175000017500000002415011402071146025123 0ustar ookoiookoi pyinotify.UnicodeLogRecord
Module pyinotify :: Class UnicodeLogRecord
[hide private]
[frames] | no frames]

Class UnicodeLogRecord

source code


Instance Methods [hide private]
 
__init__(self, name, level, pathname, lineno, msg, args, exc_info, func=None)
Initialize a logging record with interesting information.
source code
 
getMessage(self)
Return the message for this LogRecord.
source code

Inherited from logging.LogRecord: __str__

Method Details [hide private]

__init__(self, name, level, pathname, lineno, msg, args, exc_info, func=None)
(Constructor)

source code 

Initialize a logging record with interesting information.

Overrides: logging.LogRecord.__init__
(inherited documentation)

getMessage(self)

source code 

Return the message for this LogRecord.

Return the message for this LogRecord after merging any user-supplied arguments with the message.

Overrides: logging.LogRecord.getMessage
(inherited documentation)

pyinotify/python2/docstrings/uml_class_diagram_for_pyinotif_21.gif0000644000175000017500000002542111402071146025142 0ustar ookoiookoiGIF87aLBD$"$Ģtbd<24dRTܲrt4&$jl \JL̪D:<侼~|<.,L> H*\ȰÇ#JHŋ3jȱǏ C.c(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*I ?JJիXjʵׯ`ÊKٳ]G8\@Fف߿ LaFvǐ#KD'\Uu1@$v)^ͺׁ?M۷x^\M=\QS(!УỦسgD2~8C ?H옡#Q$ITFVXr_H0z^W )6@3TP{9݆vؚl5$(o qM >D5"}R%,",1ؗX5A2hcT7 !B%*&)\Xdfop77wSpa? <Ux'@4^ :蚘f:X駠^72ĥ1 "ew砇.褗n:@.n/o'7w@]hRngOV?V? Gh:7tij~ O}BXl*xb% |wCD:`EJt#t JJي~0 7XI6 ]1G`HưBT^FO>L \A ]t*BPO"(گ 80J \habXAB\9+la|P(beBP,!66&C qy8 Odhs5,Av,ORSU]u0 `LR`5f W0A?`Ugz]Js K `}ԁ7Csk3i!/xuO2 DW4EOe] $<ElO*DE e}EpCZ0d޲J"p~OD`AIBFOEan$2*Ţ2\|}N_Tb\~yxGk =R<B{́7p8@yN7HE\v*\*O@>ȵWcOU4+/=>G w^ @\Ph*Ky<wN{mt+$ArmR* ZPL ={}/zOrc/?+^Q;U_h@*@Z??y],eyp_*- YOE0 0oF25WuoFCSbGvf(+.vtKggHbztTsR64;'xO1Hq:f~y-ul]KMS4ڤ2gCM۶1N"!Nt2)MfuҔMW~TbOH#RxotMt2f1{V2'M0ETXN MQUDP4 vINK&C(C0p6JR? s8x~!c@0eP&5^?8Pfgf445+P P(CS4ȊUoBSPO+]BlbU:P‹ E5_(BpE fd&t1H-P\-v`Y։𣃪Q'FƏ$r$@~q~F%$B3'dŨff"i[G"y 8 Y*,0.4Yq6< 389 ՓB)3>Y\Y+T]C0U,ܵ\IRR9[YXKe҈]yy![Vg' ifeX6,B`vehyUr%Y"E%- m,EVzIL(RwuTWBwsQtu4tbu4pyyyvyǚI{R~eTu(ouKwc$$GtQ$2MB؅Yٝ݃&5Z#ŊuژuPv2VYkYiYsw7{9 ꉅ%3!)$*>_*Sڡ R$Q#Z(ZRi>:.J+j?-4ZJ'*%9bJHbUB7^h!_WUb6PE([vc!FYjQڥ–tBotAAiDzf%d'WBveceWdAA!ї^:&9rQDm<'D?@DFDn;F?$ElfE)m{TᨐGp\IJ>*Ahb$EjlFpt'v_'+G}XyzoiygXH4I+‡I'zI{)DIłz>Ԫ@yjgJ.I9a:p6}z%c$VLL1Yf݄\ذJL?@Q{gT!OdO$5Ouoyi؊U%6PH({eYRkFFh2z dS>?Yi: lSڶpXbt;7o[x/w|,{۷)&3YhףYkd7KM OS;`IUcu\( fuV{~Beh6BQ1LYxfRQ}GyZtʨ(ED$DDꘟyE&[4uY Kjwë:+ GĺF髬{ 3CJ|"ښEcJaˬIHJ(w 0Ĺ?:}G?!;4Mu PDîi;ㄇ«yɳEJ@[Oh˸f9x?O,KL~I\4Ѵɟ)LƪdƬcʝlw;wn|LpDŽ, O\Ȋ\sȎȒl<ɖ|LZ@+t:Zuq2\g)1 gW˅AJʫ1^UZ˙^+'fa,` sbh2ZͥټweΈ˪!_Q ]ѹ|բΜ.6}0, bѡk<ѓ!ϰݱ" ZhlֺVAiAljF#BprZwٖz pDj4]iVivbYBt<כ=سru mPl` g&4q㋘kK4KTNѶppM+[wp یEva#ݖ%oF(-Co8.pixVo եfzyVݩT߸'ݼ喘ϛmW=Xbv pu޽.S, -#ПMk荽M+~@dMpi.Y, /k틫qztԫsz DrG0xbW%PͳEw)cgs7ag`!@fȀfGHX7"RVQ>z荲IG HKeH2Hyw\Z~~8>uX~t2Subw+ހ`u9{UQjIzo\B,^o7RAwu|YgtQ0Gf<+|IX,.VӾyb+ݚa.K.zb#_z.O{y /¾*a7O u&Tp}*K>vDogJsغw陾f8[*cρL+.-L;hjU`r[XxQ|OyK^'S1µykg^G RhD\Q!L ;ĮԄo=3={gێIv9li;P8I44FóEѷAD=(V2,䯇/E+34aдpry4pp324s21D$xq9$)Jjs ;;Zl䰁pbI{x0J\;, C+9LC4;XM.nh`o#Ȃhx@A$%G.I<ќ )ա5f aQL aQ C)RfN&Q$gP]5oc9€C?<ӊ a}BT>W|.h9zY菋;ɝLĬK^ʕƱSs-x0rQ|9ZtDpr;u8?(;VX3>˷g9˻5E,0Qېm+dWro8^A=¼zʛo8>W#]ͯ$_BZ:^$w^aHP_ hb(.(H1 " @H0 IdáJ7 N>߁6$`EgnP>ye^Ʒ_&&h0C _l^Y曻a$,$rg~ hJhމzh> iNJ&zޢni~ js)i:jj_~ފkڧ*Kl눯,!IbnjF8'jmpo9沭حջU`*l^;  #T!Lmnip2% :& /JB N_=i3V9/<2өGY&}H /hʿjS&@p8԰ :UUa8.P 8b%G!|sFp O6/yq^Ǖ ,aG=63 &Ɖ;i@h6{u֙0BSwY5"D:N5><첫s7@ dS8Ǟ0ڗC2~]keo!C uT=Ah^ jڬ$@H! \#xEdB'jƒۑN 0>qH b>D O(6t h0C g"`ZпLfGC!3x0j@.00 O 1O0z2+v@`!V` Љl3h`ռ1̸BI&ir Y 7<^~wP,y9Z/c{~2#c3)'Vo!b6N˾ϿCSK(\ƹ nr[&y~fS;0>-V~ ~70"0KqD(DD9C$I?FTE.dI2aCTl Ȃ-xx vd4ctNN8M4N=e!PPKT.KHu0ejYwVbEV% kŹ\BUa\Lhgx,N$=56UdS%3uc^=% f^uidhH+ju"e`&f?@ffepA@Eņvk<+hhn1 n$7%!׊B.gq;w .2tt2uȌ)9#="\`' jȍp&i&ZwAwU" ׍Ȏ{({(hGxMhuP|iyKyw 20||A}},#}76&'yl{Q 凒3~8 (?a97389? :l3c HSH .#XJ&):0YbBBJHoɍ86ETqP[ v_,."4]RT!\i@s9s8W7>7U=|7xG@u 9.çك=3?Z@E@Rɦ3LpKDQHFIBuTC7HAwD4H4Cq JjJKZVjKS<$j^PO' 8HyP~PANiS"RAXR+; R?AuiRZQIښZ  sev[Y[t[W8񙠅j!wr1~RxG5\*v\U ; [0Ś b⚎^5EcwX4o2cb?d-{Ht2;Tj\;㜓8]ful˹?ijlf&7Ve l hԩpIIڶgnrnqmk[)g.'q`ܹp7's:4%NW&P'Ii^2qvq}r ˵εAǼ"ϋm˽ +廍k 諾kk+ۂkF#Ҷ9jR) vtFjGX 0u%<&5PM[?Zg¡+#a:c *Ek—J3zj=A =^wcć 3HXS㨾 {*_RGL5y)4TtTt4:jFTPX"K (<Ijm쬈]H EH ET4KҪ Hȑ•Z~DG jGʆljشLjQAZ Zy"]Sگ ͚lgDuQF :p>/(OZrP0ꑯ|OI˒{#۹Ȝ[[ +i\Hhg*WyWx_XQ[Ŕq"i"-Э1{<ƒ7[9 S ,ݴ pyinotify.WatchManagerError
Module pyinotify :: Class WatchManagerError
[hide private]
[frames] | no frames]

Class WatchManagerError

source code


WatchManager Exception. Raised on error encountered on watches operations.

Instance Methods [hide private]
 
__init__(self, msg, wmd)
x.__init__(...) initializes x; see x.__class__.__doc__ for signature
source code

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__, __unicode__

Inherited from object: __format__, __hash__, __reduce_ex__, __sizeof__, __subclasshook__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

Method Details [hide private]

__init__(self, msg, wmd)
(Constructor)

source code 

x.__init__(...) initializes x; see x.__class__.__doc__ for signature

Parameters:
  • msg (string) - Exception string's description.
  • wmd (dict) - This dictionary contains the wd assigned to paths of the same call for which watches were successfully added.
Overrides: object.__init__

pyinotify/python2/docstrings/uml_class_diagram_for_pyinotif_24.gif0000644000175000017500000000520111402071147025140 0ustar ookoiookoiGIF87aLBDĤBDĢ$"$jdĺĆlZ\fd<2, dJD&$ԦvtļԬRTD:<̢\NLĤFDndĊt^\<24*,ļԬVTD><ܶ$~t4*,j\侼 Ď~|lVT><^\L:<ܮNLrt䶴rl<.,D64z| ,&$ԦԮ̦|bd\JLTBDdNL̞, H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜIM\ɳϟ@ JѢxӧPJJիXRt`ÊKY(?Ϫ۰_vݻEظ] &w†[7`apA `!^btK? e!(@i!=˨㥳귧727PzE$(Vu7q5nW(21z蹗͞q޿jу+a {g0W\6E!gɅZcpWVE#