diff --git a/lib/pyinotify.py b/lib/pyinotify.py
deleted file mode 100644
index 3c5dab03125..00000000000
--- a/lib/pyinotify.py
+++ /dev/null
@@ -1,2326 +0,0 @@
-#
-# pyinotify.py - python interface to inotify
-# Copyright (c) 2005-2015 Sebastien Martini <seb@dbzteam.org>
-#
-# SPDX-License-Identifier: MIT
-#
-"""
-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)
-
-
-# Check Python version
-import sys
-if sys.version_info < (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 re
-import glob
-import locale
-import subprocess
-
-try:
-    from functools import reduce
-except ImportError:
-    pass  # Will fail on Python 2.4 which has reduce() builtin anyway.
-
-try:
-    import ctypes
-    import ctypes.util
-except ImportError:
-    ctypes = None
-
-try:
-    import inotify_syscalls
-except ImportError:
-    inotify_syscalls = None
-
-
-__author__ = "seb@dbzteam.org (Sebastien Martini)"
-
-__version__ = "0.9.6"
-
-
-# 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
-
-
-class InotifyBindingNotFoundError(PyinotifyError):
-    """
-    Raised when no inotify support couldn't be found.
-    """
-    def __init__(self):
-        err = "Couldn't find any inotify binding"
-        PyinotifyError.__init__(self, err)
-
-
-class INotifyWrapper:
-    """
-    Abstract class wrapping access to inotify's functions. This is an
-    internal class.
-    """
-    @staticmethod
-    def create():
-        """
-        Factory method instanciating and returning the right wrapper.
-        """
-        # First, try to use ctypes.
-        if ctypes:
-            inotify = _CtypesLibcINotifyWrapper()
-            if inotify.init():
-                return inotify
-        # Second, see if C extension is compiled.
-        if inotify_syscalls:
-            inotify = _INotifySyscallsWrapper()
-            if inotify.init():
-                return inotify
-
-    def get_errno(self):
-        """
-        Return None is no errno code is available.
-        """
-        return self._get_errno()
-
-    def str_errno(self):
-        code = self.get_errno()
-        if code is None:
-            return 'Errno: no errno support'
-        return 'Errno=%s (%s)' % (os.strerror(code), errno.errorcode[code])
-
-    def inotify_init(self):
-        return self._inotify_init()
-
-    def inotify_add_watch(self, fd, pathname, mask):
-        # Unicode strings must be encoded to string prior to calling this
-        # method.
-        assert isinstance(pathname, str)
-        return self._inotify_add_watch(fd, pathname, mask)
-
-    def inotify_rm_watch(self, fd, wd):
-        return self._inotify_rm_watch(fd, wd)
-
-
-class _INotifySyscallsWrapper(INotifyWrapper):
-    def __init__(self):
-        # Stores the last errno value.
-        self._last_errno = None
-
-    def init(self):
-        assert inotify_syscalls
-        return True
-
-    def _get_errno(self):
-        return self._last_errno
-
-    def _inotify_init(self):
-        try:
-            fd = inotify_syscalls.inotify_init()
-        except IOError as err:
-            self._last_errno = err.errno
-            return -1
-        return fd
-
-    def _inotify_add_watch(self, fd, pathname, mask):
-        try:
-            wd = inotify_syscalls.inotify_add_watch(fd, pathname, mask)
-        except IOError as err:
-            self._last_errno = err.errno
-            return -1
-        return wd
-
-    def _inotify_rm_watch(self, fd, wd):
-        try:
-            ret = inotify_syscalls.inotify_rm_watch(fd, wd)
-        except IOError as err:
-            self._last_errno = err.errno
-            return -1
-        return ret
-
-
-class _CtypesLibcINotifyWrapper(INotifyWrapper):
-    def __init__(self):
-        self._libc = None
-        self._get_errno_func = None
-
-    def init(self):
-        assert ctypes
-
-        try_libc_name = 'c'
-        if sys.platform.startswith('freebsd'):
-            try_libc_name = 'inotify'
-
-        libc_name = None
-        try:
-            libc_name = ctypes.util.find_library(try_libc_name)
-        except (OSError, IOError):
-            pass  # Will attemp to load it with None anyway.
-
-        self._libc = ctypes.CDLL(libc_name, use_errno=True)
-        self._get_errno_func = ctypes.get_errno
-
-        # Eventually check that libc has needed inotify bindings.
-        if (not hasattr(self._libc, 'inotify_init') or
-            not hasattr(self._libc, 'inotify_add_watch') or
-            not hasattr(self._libc, 'inotify_rm_watch')):
-            return False
-
-        self._libc.inotify_init.argtypes = []
-        self._libc.inotify_init.restype = ctypes.c_int
-        self._libc.inotify_add_watch.argtypes = [ctypes.c_int, ctypes.c_char_p,
-                                                 ctypes.c_uint32]
-        self._libc.inotify_add_watch.restype = ctypes.c_int
-        self._libc.inotify_rm_watch.argtypes = [ctypes.c_int, ctypes.c_int]
-        self._libc.inotify_rm_watch.restype = ctypes.c_int
-        return True
-
-    def _get_errno(self):
-        assert self._get_errno_func
-        return self._get_errno_func()
-
-    def _inotify_init(self):
-        assert self._libc is not None
-        return self._libc.inotify_init()
-
-    def _inotify_add_watch(self, fd, pathname, mask):
-        assert self._libc is not None
-        # Encodes path to a bytes string. This conversion seems required because
-        # ctypes.create_string_buffer seems to manipulate bytes internally.
-        # Moreover it seems that inotify_add_watch does not work very well when
-        # it receives an ctypes.create_unicode_buffer instance as argument.
-        pathname = pathname.encode(sys.getfilesystemencoding())
-        pathname = ctypes.create_string_buffer(pathname)
-        return self._libc.inotify_add_watch(fd, pathname, mask)
-
-    def _inotify_rm_watch(self, fd, wd):
-        assert self._libc is not None
-        return self._libc.inotify_rm_watch(fd, wd)
-
-
-# Logging
-def logger_init():
-    """Initialize logger instance."""
-    log = logging.getLogger("pyinotify")
-    console_handler = logging.StreamHandler()
-    console_handler.setFormatter(
-        logging.Formatter("[%(asctime)s %(name)s %(levelname)s] %(message)s"))
-    log.addHandler(console_handler)
-    log.setLevel(20)
-    return log
-
-log = logger_init()
-
-
-# inotify's variables
-class ProcINotify:
-    """
-    Access (read, write) inotify's variables through /proc/sys/. Note that
-    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
-    """
-    def __init__(self, attr):
-        self._base = "/proc/sys/fs/inotify"
-        self._attr = attr
-
-    def get_val(self):
-        """
-        Gets attribute's value.
-
-        @return: stored value.
-        @rtype: int
-        @raise IOError: if corresponding file in /proc/sys cannot be read.
-        """
-        with open(os.path.join(self._base, self._attr), 'r') as file_obj:
-            return int(file_obj.readline())
-
-    def set_val(self, nval):
-        """
-        Sets new attribute's value.
-
-        @param nval: replaces current value by nval.
-        @type nval: int
-        @raise IOError: if corresponding file in /proc/sys cannot be written.
-        """
-        with open(os.path.join(self._base, self._attr), 'w') as file_obj:
-            file_obj.write(str(nval) + '\n')
-
-    value = property(get_val, set_val)
-
-    def __repr__(self):
-        return '<%s=%d>' % (self._attr, self.get_val())
-
-
-# Inotify's variables
-#
-# Note: may raise IOError if the corresponding value in /proc/sys
-#       cannot be accessed.
-#
-# Examples:
-#  - 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] = ProcINotify(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_EXCL_UNLINK: Events are not generated for children after they
-                          have been unlinked from the watched directory.
-                          (new in kernel 2.6.36).
-    @type IN_EXCL_UNLINK: 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_EXCL_UNLINK'   : 0x04000000,  # exclude events on unlinked objects
-        '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' % (output_format.field_name(attr),
-                              output_format.punctuation('='),
-                              output_format.field_value(value))
-
-        s = '%s%s%s %s' % (output_format.punctuation('<'),
-                           output_format.class_name(self.__class__.__name__),
-                           s,
-                           output_format.punctuation('>'))
-        return s
-
-    def __str__(self):
-        return repr(self)
-
-
-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
-        """
-        # Use this variable to cache the result of str(self), this object
-        # is immutable.
-        self._str = None
-        # name: remove trailing '\0'
-        d = {'wd': wd,
-             'mask': mask,
-             'cookie': cookie,
-             'name': name.rstrip('\0')}
-        _Event.__init__(self, d)
-        log.debug(str(self))
-
-    def __str__(self):
-        if self._str is None:
-            self._str = _Event.__str__(self)
-        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 & ~IN_ISDIR
-        # Bitbake hack - we see event masks of 0x6, i.e., IN_MODIFY & IN_ATTRIB.
-        # The kernel inotify code can set more than one of the bits in the mask,
-        # fsnotify_change() in linux/fsnotify.h is quite clear that IN_ATTRIB,
-        # IN_MODIFY and IN_ACCESS can arrive together.
-        # This breaks the code below which assume only one mask bit is ever
-        # set in an event. We don't care about attrib or access in bitbake so
-        # drop those.
-        if stripped_mask & IN_MODIFY:
-            stripped_mask &= ~(IN_ATTRIB | IN_ACCESS)
-
-        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 /d1/d2/t3 where d1 is watched and
-                # d2 and t3 (directory or file) are created.
-                # Since the directory d2 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) and
-                    os.path.isdir(created_dir)):
-                    try:
-                        for name in os.listdir(created_dir):
-                            inner = os.path.join(created_dir, name)
-                            if self._watch_manager.get_wd(inner) is not None:
-                                continue
-                            # Generate (simulate) creation events for sub-
-                            # directories and files.
-                            if os.path.isfile(inner):
-                                # symlinks are handled as files.
-                                flags = IN_CREATE
-                            elif os.path.isdir(inner):
-                                flags = IN_CREATE | IN_ISDIR
-                            else:
-                                # This path should not be taken.
-                                continue
-                            rawevent = _RawEvent(created_dir_wd, flags, 0, name)
-                            self._notifier.append_event(rawevent)
-                    except OSError as err:
-                        msg = "process_IN_CREATE, invalid directory: %s"
-                        log.debug(msg % str(err))
-        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(str(event))
-        self._out.write('\n')
-        self._out.flush()
-
-
-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' % (output_format.field_name(ev),
-                                 output_format.field_value(value)))
-        s = '<%s%s >' % (output_format.class_name(self.__class__.__name__),
-                         ''.join(l))
-        return s
-
-    def dump(self, filename):
-        """
-        Dumps statistics.
-
-        @param filename: filename where stats will be dumped, filename is
-                         created and must not exist prior to this call.
-        @type filename: string
-        """
-        flags = os.O_WRONLY|os.O_CREAT|os.O_NOFOLLOW|os.O_EXCL
-        fd = os.open(filename, flags, 0o0600)
-        os.write(fd, bytes(self.__str__(), locale.getpreferredencoding()))
-        os.close(fd)
-
-    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(output_format.field_value('@' * scale))
-                                   + 1)
-        def func(x):
-            return fmt % (output_format.field_name(x[0]),
-                          output_format.field_value('@' * int(x[1] * unity)),
-                          output_format.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 / 1000)) 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: see read_freq above. If provided, it must be set in
-                        milliseconds. See
-                        https://docs.python.org/3/library/select.html#select.poll.poll
-        @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. timeout must be sepcified in
-                        milliseconds.
-        @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.args[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 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
-            if self._watch_manager.ignore_events:
-                log.debug("Event ignored: %s" % repr(raw_event))
-                continue
-            watch_ = self._watch_manager.get_watch(raw_event.wd)
-            if (watch_ is None) and not (raw_event.mask & IN_Q_OVERFLOW):
-                if not (raw_event.mask & IN_IGNORED):
-                    # 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, stdin=os.devnull, stdout=os.devnull,
-                    stderr=os.devnull):
-        """
-        pid_file: file where the pid will be written. If pid_file=None the pid
-                  is written to /var/run/<sys.argv[0]|pyinotify>.pid, if
-                  pid_file=False no pid_file is written.
-        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 pid_file and os.path.lexists(pid_file):
-            err = 'Cannot daemonize: pid file %s already exists.' % pid_file
-            raise NotifierError(err)
-
-        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(0o022)
-                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, 0o0600)
-            os.dup2(fd_out, 1)
-            fd_err = os.open(stderr, os.O_WRONLY|os.O_CREAT, 0o0600)
-            os.dup2(fd_err, 2)
-
-        # Detach task
-        fork_daemon()
-
-        # Write pid
-        if pid_file:
-            flags = os.O_WRONLY|os.O_CREAT|os.O_NOFOLLOW|os.O_EXCL
-            fd_pid = os.open(pid_file, flags, 0o0600)
-            os.write(fd_pid,  bytes(str(os.getpid()) + '\n',
-                                    locale.getpreferredencoding()))
-            os.close(fd_pid)
-            # Register unlink function
-            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. If pid_file=None or is set to a
-                     pathname the caller must ensure the file does not exist
-                     before this method is called otherwise an exception
-                     pyinotify.NotifierError will be raised. If pid_file=False
-                     it is still daemonized but the pid is not written in any
-                     file.
-        @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().
-        Afterward it is invalid to access this instance.
-        """
-        if self._fd is not None:
-            self._pollobj.unregister(self._fd)
-            os.close(self._fd)
-            self._fd = None
-        self._sys_proc_fun = None
-
-
-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 / 1000)) 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 read_freq above. If provided, it must be set in
-                        milliseconds. See
-                        https://docs.python.org/3/library/select.html#select.poll.poll
-        @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 TornadoAsyncNotifier(Notifier):
-    """
-    Tornado ioloop adapter.
-
-    """
-    def __init__(self, watch_manager, ioloop, callback=None,
-                 default_proc_fun=None, read_freq=0, threshold=0, timeout=None,
-                 channel_map=None):
-        """
-        Note that if later you must call ioloop.close() be sure to let the
-        default parameter to all_fds=False.
-
-        See example tornado_notifier.py for an example using this notifier.
-
-        @param ioloop: Tornado's IO loop.
-        @type ioloop: tornado.ioloop.IOLoop instance.
-        @param callback: Functor called at the end of each call to handle_read
-                         (IOLoop's read handler). Expects to receive the
-                         notifier object (self) as single parameter.
-        @type callback: callable object or function
-        """
-        self.io_loop = ioloop
-        self.handle_read_callback = callback
-        Notifier.__init__(self, watch_manager, default_proc_fun, read_freq,
-                          threshold, timeout)
-        ioloop.add_handler(self._fd, self.handle_read, ioloop.READ)
-
-    def stop(self):
-        self.io_loop.remove_handler(self._fd)
-        Notifier.stop(self)
-
-    def handle_read(self, *args, **kwargs):
-        """
-        See comment in AsyncNotifier.
-
-        """
-        self.read_events()
-        self.process_events()
-        if self.handle_read_callback is not None:
-            self.handle_read_callback(self)
-
-
-class AsyncioNotifier(Notifier):
-    """
-
-    asyncio/trollius event loop adapter.
-
-    """
-    def __init__(self, watch_manager, loop, callback=None,
-                 default_proc_fun=None, read_freq=0, threshold=0, timeout=None):
-        """
-
-        See examples/asyncio_notifier.py for an example usage.
-
-        @param loop: asyncio or trollius event loop instance.
-        @type loop: asyncio.BaseEventLoop or trollius.BaseEventLoop instance.
-        @param callback: Functor called at the end of each call to handle_read.
-                         Expects to receive the notifier object (self) as
-                         single parameter.
-        @type callback: callable object or function
-
-        """
-        self.loop = loop
-        self.handle_read_callback = callback
-        Notifier.__init__(self, watch_manager, default_proc_fun, read_freq,
-                          threshold, timeout)
-        loop.add_reader(self._fd, self.handle_read)
-
-    def stop(self):
-        self.loop.remove_reader(self._fd)
-        Notifier.stop(self)
-
-    def handle_read(self, *args, **kwargs):
-        self.read_events()
-        self.process_events()
-        if self.handle_read_callback is not None:
-            self.handle_read_callback(self)
-
-
-class Watch:
-    """
-    Represent a watch, i.e. a file or directory being watched.
-
-    """
-    __slots__ = ('wd', 'path', 'mask', 'proc_fun', 'auto_add',
-                 'exclude_filter', 'dir')
-
-    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' % (output_format.field_name(attr),
-                                  output_format.punctuation('='),
-                                  output_format.field_value(getattr(self,
-                                                                    attr))) \
-                      for attr in self.__slots__ if not attr.startswith('_')])
-
-        s = '%s%s %s %s' % (output_format.punctuation('<'),
-                            output_format.class_name(self.__class__.__name__),
-                            s,
-                            output_format.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
-
-        Note: it is not possible to exclude a file if its encapsulating
-              directory is itself watched. See this issue for more details
-              https://github.com/seb-m/pyinotify/issues/31
-
-        @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, raise InotifyBindingNotFoundError
-        if no inotify binding was found (through ctypes or from direct access to
-        syscalls).
-
-        @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._ignore_events = False
-        self._exclude_filter = exclude_filter
-        self._wmd = {}  # watch dict key: watch descriptor, value: watch
-
-        self._inotify_wrapper = INotifyWrapper.create()
-        if self._inotify_wrapper is None:
-            raise InotifyBindingNotFoundError()
-
-        self._fd = self._inotify_wrapper.inotify_init() # file descriptor
-        if self._fd < 0:
-            err = 'Cannot initialize new instance of inotify, %s'
-            raise OSError(err % self._inotify_wrapper.str_errno())
-
-    def close(self):
-        """
-        Close inotify's file descriptor, this action will also automatically
-        remove (i.e. stop watching) all its associated watch descriptors.
-        After a call to this method the WatchManager's instance become useless
-        and cannot be reused, a new instance must then be instanciated. It
-        makes sense to call this method in few situations for instance if
-        several independant WatchManager must be instanciated or if all watches
-        must be removed and no other watches need to be added.
-        """
-        os.close(self._fd)
-
-    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('Cannot delete unknown watch descriptor %s' % 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)
-        if auto_add and not mask & IN_CREATE:
-            mask |= IN_CREATE
-        wd = self._inotify_wrapper.inotify_add_watch(self._fd, 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)
-        # wd are _always_ indexed with their original unicode paths in wmd.
-        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.
-                         If |auto_add| is True, IN_CREATE is ored with |mask|
-                         when the watch is added.
-        @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 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' % \
-                                       (rpath, wd,
-                                        self._inotify_wrapper.str_errno()))
-                            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|.
-                         If |auto_add| is True, IN_CREATE is ored with |mask|
-                         when the watch is updated.
-        @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:
-                wd_ = self._inotify_wrapper.inotify_add_watch(self._fd, apath,
-                                                              mask)
-                if wd_ < 0:
-                    ret_[awd] = False
-                    err = ('update_watch: cannot update %s WD=%d, %s' % \
-                               (apath, wd_, self._inotify_wrapper.str_errno()))
-                    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_ = self._inotify_wrapper.inotify_rm_watch(self._fd, awd)
-            if wd_ < 0:
-                ret_[awd] = False
-                err = ('rm_watch: cannot remove WD=%d, %s' % \
-                           (awd, self._inotify_wrapper.str_errno()))
-                if quiet:
-                    log.error(err)
-                    continue
-                raise WatchManagerError(err, ret_)
-
-            # Remove watch from our dictionary
-            if awd in self._wmd:
-                del self._wmd[awd]
-            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)
-
-    def get_ignore_events(self):
-        return self._ignore_events
-
-    def set_ignore_events(self, nval):
-        self._ignore_events = nval
-
-    ignore_events = property(get_ignore_events, set_ignore_events,
-                             "Make watch manager ignoring new events.")
-
-
-class RawOutputFormat:
-    """
-    Format string representations.
-    """
-    def __init__(self, format=None):
-        self.format = format or {}
-
-    def simple(self, s, attribute):
-        if not isinstance(s, str):
-            s = str(s)
-        return (self.format.get(attribute, '') + s +
-                self.format.get('normal', ''))
-
-    def punctuation(self, s):
-        """Punctuation color."""
-        return self.simple(s, 'normal')
-
-    def field_value(self, s):
-        """Field value color."""
-        return self.simple(s, 'purple')
-
-    def field_name(self, s):
-        """Field name color."""
-        return self.simple(s, 'blue')
-
-    def class_name(self, s):
-        """Class name color."""
-        return self.format.get('red', '') + self.simple(s, 'bold')
-
-output_format = RawOutputFormat()
-
-class ColoredOutputFormat(RawOutputFormat):
-    """
-    Format colored string representations.
-    """
-    def __init__(self):
-        f = {'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'}
-        RawOutputFormat.__init__(self, f)
-
-
-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("-g", "--glob", action="store_true",
-                      dest="glob",
-                      help="Treat paths as globs")
-    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")
-    parser.add_option("-V", "--version", action="store_true",
-                      dest="version",  help="Pyinotify version")
-    parser.add_option("-f", "--raw-format", action="store_true",
-                      dest="raw_format",
-                      help="Disable enhanced output format.")
-    parser.add_option("-c", "--command", action="store",
-                      dest="command",
-                      help="Shell command to run upon event")
-
-    (options, args) = parser.parse_args()
-
-    if options.verbose:
-        log.setLevel(10)
-
-    if options.version:
-        print(__version__)
-
-    if not options.raw_format:
-        global output_format
-        output_format = ColoredOutputFormat()
-
-    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):
-            sys.stdout.write(repr(s.proc_fun()))
-            sys.stdout.write('\n')
-            sys.stdout.write(str(s.proc_fun()))
-            sys.stdout.write('\n')
-            sys.stdout.flush()
-        cb_fun = cb
-
-    # External command
-    if options.command:
-        def cb(s):
-            subprocess.Popen(options.command, shell=True)
-        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, do_glob=options.glob)
-    # Loop forever (until sigint signal get caught)
-    notifier.loop(callback=cb_fun)
-
-
-if __name__ == '__main__':
-    command_line()
