Hello community,

here is the log from the commit of package python-watchdog for openSUSE:Factory 
checked in at 2018-11-20 22:43:13
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-watchdog (Old)
 and      /work/SRC/openSUSE:Factory/.python-watchdog.new.19453 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-watchdog"

Tue Nov 20 22:43:13 2018 rev:4 rq:650294 version:0.9.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-watchdog/python-watchdog.changes  
2018-08-24 17:01:35.877893089 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-watchdog.new.19453/python-watchdog.changes   
    2018-11-20 22:43:26.314260537 +0100
@@ -1,0 +2,8 @@
+Mon Nov 19 13:00:25 UTC 2018 - John Paul Adrian Glaubitz 
<[email protected]>
+
+- Update to version 0.8.3
+- Cherry-pick upstream patch to fix testsuite
+  + add-missing-conftest.patch
+- Update BuildRequires from setup.py
+
+-------------------------------------------------------------------

Old:
----
  watchdog-0.8.3.tar.gz

New:
----
  add-missing-conftest.patch
  watchdog-0.9.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-watchdog.spec ++++++
--- /var/tmp/diff_new_pack.q0GD6x/_old  2018-11-20 22:43:28.734259624 +0100
+++ /var/tmp/diff_new_pack.q0GD6x/_new  2018-11-20 22:43:28.738259623 +0100
@@ -12,20 +12,23 @@
 # license that conforms to the Open Source Definition (Version 1.9)
 # published by the Open Source Initiative.
 
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
 #
 
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-watchdog
-Version:        0.8.3
+Version:        0.9.0
 Release:        0
 Summary:        Filesystem events monitoring
 License:        Apache-2.0
 Group:          Development/Languages/Python
 URL:            http://github.com/gorakhargosh/watchdog
 Source:         
https://files.pythonhosted.org/packages/source/w/watchdog/watchdog-%{version}.tar.gz
+Patch0:         add-missing-conftest.patch
 BuildRequires:  %{python_module pathtools}
+BuildRequires:  %{python_module pytest-cov}
+BuildRequires:  %{python_module pytest-timeout >= 0.3}
 BuildRequires:  %{python_module pytest}
 BuildRequires:  %{python_module setuptools}
 BuildRequires:  fdupes
@@ -52,6 +55,7 @@
 
 %prep
 %setup -q -n watchdog-%{version}
+%patch0 -p1
 chmod -x README.rst
 # Remove all shebangs
 find src -name "*.py" | xargs sed -i -e '/^#!\//, 1d'

++++++ add-missing-conftest.patch ++++++
diff -Nru watchdog-0.9.0.old/tests/conftest.py watchdog-0.9.0/tests/conftest.py
--- watchdog-0.9.0.old/tests/conftest.py        1970-01-01 01:00:00.000000000 
+0100
+++ watchdog-0.9.0/tests/conftest.py    2018-11-19 13:54:38.883980668 +0100
@@ -0,0 +1,22 @@
+from functools import partial
+import os
+import pytest
+from tests import shell
+
+
[email protected]()
+def tmpdir(request):
+    path = os.path.realpath(shell.mkdtemp())
+    def finalizer():
+        shell.rm(path, recursive=True)
+    request.addfinalizer(finalizer)
+    return path
+
+
[email protected]()
+def p(tmpdir, *args):
+    """
+    Convenience function to join the temporary directory path
+    with the provided arguments.
+    """
+    return partial(os.path.join, tmpdir)
++++++ watchdog-0.8.3.tar.gz -> watchdog-0.9.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/AUTHORS new/watchdog-0.9.0/AUTHORS
--- old/watchdog-0.8.3/AUTHORS  2015-02-11 10:54:50.000000000 +0100
+++ new/watchdog-0.9.0/AUTHORS  2018-08-28 02:33:44.000000000 +0200
@@ -6,6 +6,7 @@
 -----------------------------------
 Adrian Tejn Kern <[email protected]>
 Andrew Schaaf <[email protected]>
+Danilo de Jesus da Silva Bellini <[email protected]>
 David LaPalomento <[email protected]>
 Filip Noetzel <[email protected]>
 Gary van der Merwe <[email protected]>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/PKG-INFO new/watchdog-0.9.0/PKG-INFO
--- old/watchdog-0.8.3/PKG-INFO 2015-02-11 11:25:48.000000000 +0100
+++ new/watchdog-0.9.0/PKG-INFO 2018-08-28 22:42:19.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: watchdog
-Version: 0.8.3
+Version: 0.9.0
 Summary: Filesystem events monitoring
 Home-page: http://github.com/gorakhargosh/watchdog
 Author: Yesudeep Mangalapilly
@@ -174,7 +174,7 @@
         
             pip install pytest
             pip install -e .
-            py.tests tests
+            py.test tests
         
         
         Supported Platforms
@@ -317,7 +317,16 @@
 Classifier: Operating System :: Microsoft :: Windows :: Windows NT/2000
 Classifier: Operating System :: OS Independent
 Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
 Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.2
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: Implementation :: PyPy
 Classifier: Programming Language :: C
 Classifier: Topic :: Software Development :: Libraries
 Classifier: Topic :: System :: Monitoring
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/README.rst 
new/watchdog-0.9.0/README.rst
--- old/watchdog-0.8.3/README.rst       2015-02-11 10:54:50.000000000 +0100
+++ new/watchdog-0.9.0/README.rst       2018-08-27 23:46:08.000000000 +0200
@@ -166,7 +166,7 @@
 
     pip install pytest
     pip install -e .
-    py.tests tests
+    py.test tests
 
 
 Supported Platforms
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/docs/source/global.rst.inc 
new/watchdog-0.9.0/docs/source/global.rst.inc
--- old/watchdog-0.8.3/docs/source/global.rst.inc       2015-02-11 
10:54:50.000000000 +0100
+++ new/watchdog-0.9.0/docs/source/global.rst.inc       2018-08-28 
22:25:40.000000000 +0200
@@ -4,7 +4,7 @@
 .. |author_email| replace:: [email protected]
 .. |copyright| replace:: Copyright 2012 Google, Inc.
 .. |project_name| replace:: ``watchdog``
-.. |project_version| replace:: 0.8.3
+.. |project_version| replace:: 0.9.0
 
 .. _issue tracker: http://github.com/gorakhargosh/watchdog/issues
 .. _code repository: http://github.com/gorakhargosh/watchdog
@@ -30,7 +30,7 @@
 .. _inotify-tools: http://github.com/rvoicilas/inotify-tools
 .. _jnotify: http://jnotify.sourceforge.net/
 .. _LibYAML: http://pyyaml.org/wiki/LibYAML
-.. _nose: http://somethingaboutorange.com/mrl/projects/nose/0.11.2/
+.. _nose: http://nose.readthedocs.org/en/latest/
 .. _pip: http://pypi.python.org/pypi/pip
 .. _pnotify: http://mark.heily.com/pnotify
 .. _pyfilesystem: http://code.google.com/p/pyfilesystem
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/docs/source/quickstart.rst 
new/watchdog-0.9.0/docs/source/quickstart.rst
--- old/watchdog-0.8.3/docs/source/quickstart.rst       2015-02-11 
10:54:50.000000000 +0100
+++ new/watchdog-0.9.0/docs/source/quickstart.rst       2018-08-27 
23:46:08.000000000 +0200
@@ -32,7 +32,6 @@
 file system changes and simply log them to the console::
 
     import sys
-    import time
     import logging
     from watchdog.observers import Observer
     from watchdog.events import LoggingEventHandler
@@ -47,8 +46,8 @@
         observer.schedule(event_handler, path, recursive=True)
         observer.start()
         try:
-            while True:
-                time.sleep(1)
+            while observer.isAlive():
+                observer.join(1)
         except KeyboardInterrupt:
             observer.stop()
         observer.join()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/setup.cfg new/watchdog-0.9.0/setup.cfg
--- old/watchdog-0.8.3/setup.cfg        2015-02-11 11:25:48.000000000 +0100
+++ new/watchdog-0.9.0/setup.cfg        2018-08-28 22:42:19.000000000 +0200
@@ -9,5 +9,4 @@
 [egg_info]
 tag_build = 
 tag_date = 0
-tag_svn_revision = 0
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/setup.py new/watchdog-0.9.0/setup.py
--- old/watchdog-0.8.3/setup.py 2015-02-11 10:54:50.000000000 +0100
+++ new/watchdog-0.9.0/setup.py 2018-08-28 21:28:26.000000000 +0200
@@ -81,7 +81,11 @@
 if sys.version_info < (2, 7, 0):
     tests_require.append('unittest2')
 
-install_requires = ['PyYAML >=3.10', 'argh >=0.24.1', 'pathtools >=0.1.1']
+install_requires = [
+    "PyYAML<3.13" if sys.version_info[:2] == (3, 2) else "PyYAML>=3.10",
+    "argh>=0.24.1",
+    "pathtools>=0.1.1",
+]
 if sys.version_info < (2, 7, 0):
     # argparse is merged into Python 2.7 in the Python 2x series
     # and Python 3.2 in the Python 3x series.
@@ -131,7 +135,16 @@
           'Operating System :: Microsoft :: Windows :: Windows NT/2000',
           'Operating System :: OS Independent',
           'Programming Language :: Python',
+          'Programming Language :: Python :: 2.6',
+          'Programming Language :: Python :: 2.7',
           'Programming Language :: Python :: 3',
+          'Programming Language :: Python :: 3.2',
+          'Programming Language :: Python :: 3.3',
+          'Programming Language :: Python :: 3.4',
+          'Programming Language :: Python :: 3.5',
+          'Programming Language :: Python :: 3.6',
+          'Programming Language :: Python :: 3.7',
+          'Programming Language :: Python :: Implementation :: PyPy',
           'Programming Language :: C',
           'Topic :: Software Development :: Libraries',
           'Topic :: System :: Monitoring',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/src/watchdog/observers/__init__.py 
new/watchdog-0.9.0/src/watchdog/observers/__init__.py
--- old/watchdog-0.8.3/src/watchdog/observers/__init__.py       2015-02-11 
10:54:50.000000000 +0100
+++ new/watchdog-0.9.0/src/watchdog/observers/__init__.py       2018-08-28 
03:15:25.000000000 +0200
@@ -90,3 +90,5 @@
 
 else:
     from .polling import PollingObserver as Observer
+
+__all__ = ["Observer"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/src/watchdog/observers/fsevents.py 
new/watchdog-0.9.0/src/watchdog/observers/fsevents.py
--- old/watchdog-0.8.3/src/watchdog/observers/fsevents.py       2015-02-11 
10:54:50.000000000 +0100
+++ new/watchdog-0.9.0/src/watchdog/observers/fsevents.py       2018-08-28 
03:24:46.000000000 +0200
@@ -137,7 +137,7 @@
                                 callback,
                                 self.pathnames)
             _fsevents.read_events(self)
-        except Exception as e:
+        except:
             pass
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/src/watchdog/observers/fsevents2.py 
new/watchdog-0.9.0/src/watchdog/observers/fsevents2.py
--- old/watchdog-0.8.3/src/watchdog/observers/fsevents2.py      2015-02-11 
10:54:50.000000000 +0100
+++ new/watchdog-0.9.0/src/watchdog/observers/fsevents2.py      2018-08-28 
02:57:26.000000000 +0200
@@ -71,7 +71,6 @@
     kFSEventStreamEventFlagItemFinderInfoMod,
     kFSEventStreamEventFlagItemChangeOwner,
     kFSEventStreamEventFlagItemXattrMod,
-    kFSEventStreamEventFlagItemIsFile,
     kFSEventStreamEventFlagItemIsDir,
     kFSEventStreamEventFlagItemIsSymlink,
 )
@@ -88,8 +87,8 @@
         self._run_loop = None
 
         if isinstance(path, bytes):
-            self._path = path.decode('utf-8')
-        self._path = unicodedata.normalize('NFC', self._path)
+            path = path.decode('utf-8')
+        self._path = unicodedata.normalize('NFC', path)
 
         context = None
         latency = 1.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/src/watchdog/observers/inotify.py 
new/watchdog-0.9.0/src/watchdog/observers/inotify.py
--- old/watchdog-0.8.3/src/watchdog/observers/inotify.py        2015-02-11 
10:54:50.000000000 +0100
+++ new/watchdog-0.9.0/src/watchdog/observers/inotify.py        2018-08-28 
02:48:58.000000000 +0200
@@ -124,7 +124,9 @@
         if self._inotify:
             self._inotify.close()
 
-    def queue_events(self, timeout):
+    def queue_events(self, timeout, full_events=False):
+        #If "full_events" is true, then the method will report unmatched move 
events as seperate events
+        #This behavior is by default only called by a InotifyFullEmitter
         with self._lock:
             event = self._inotify.read_event()
             if event is None:
@@ -144,8 +146,12 @@
 
             src_path = self._decode_path(event.src_path)
             if event.is_moved_to:
-                cls = DirCreatedEvent if event.is_directory else 
FileCreatedEvent
-                self.queue_event(cls(src_path))
+                if (full_events):
+                    cls = DirMovedEvent if event.is_directory else 
FileMovedEvent
+                    self.queue_event(cls(None, src_path))
+                else:
+                    cls = DirCreatedEvent if event.is_directory else 
FileCreatedEvent
+                    self.queue_event(cls(src_path))
                 self.queue_event(DirModifiedEvent(os.path.dirname(src_path)))
                 if event.is_directory and self.watch.is_recursive:
                     for sub_event in generate_sub_created_events(src_path):
@@ -156,13 +162,14 @@
             elif event.is_modify:
                 cls = DirModifiedEvent if event.is_directory else 
FileModifiedEvent
                 self.queue_event(cls(src_path))
-            elif event.is_delete_self:
-                cls = DirDeletedEvent if event.is_directory else 
FileDeletedEvent
-                self.queue_event(cls(src_path))
-            elif event.is_delete or event.is_moved_from:
+            elif event.is_delete or (event.is_moved_from and not full_events):
                 cls = DirDeletedEvent if event.is_directory else 
FileDeletedEvent
                 self.queue_event(cls(src_path))
                 self.queue_event(DirModifiedEvent(os.path.dirname(src_path)))
+            elif event.is_moved_from and full_events:
+                cls = DirMovedEvent if event.is_directory else FileMovedEvent
+                self.queue_event(cls(src_path, None))
+                self.queue_event(DirModifiedEvent(os.path.dirname(src_path)))
             elif event.is_create:
                 cls = DirCreatedEvent if event.is_directory else 
FileCreatedEvent
                 self.queue_event(cls(src_path))
@@ -175,12 +182,37 @@
         return unicode_paths.decode(path)
 
 
+class InotifyFullEmitter(InotifyEmitter):
+    """
+    inotify(7)-based event emitter. By default this class produces move events 
even if they are not matched
+    Such move events will have a ``None`` value for the unmatched part.
+
+    :param event_queue:
+        The event queue to fill with events.
+    :param watch:
+        A watch object representing the directory to monitor.
+    :type watch:
+        :class:`watchdog.observers.api.ObservedWatch`
+    :param timeout:
+        Read events blocking timeout (in seconds).
+    :type timeout:
+        ``float``
+    """
+    def __init__(self, event_queue, watch, timeout=DEFAULT_EMITTER_TIMEOUT):
+        InotifyEmitter.__init__(self, event_queue, watch, timeout)
+        
+    def queue_events(self, timeout, events=True):
+        InotifyEmitter.queue_events(self, timeout, full_events=events)
+
 class InotifyObserver(BaseObserver):
     """
     Observer thread that schedules watching directories and dispatches
     calls to event handlers.
     """
 
-    def __init__(self, timeout=DEFAULT_OBSERVER_TIMEOUT):
-        BaseObserver.__init__(self, emitter_class=InotifyEmitter,
+    def __init__(self, timeout=DEFAULT_OBSERVER_TIMEOUT, 
generate_full_events=False):
+        if (generate_full_events):
+            BaseObserver.__init__(self, emitter_class=InotifyFullEmitter, 
timeout=timeout)
+        else:
+            BaseObserver.__init__(self, emitter_class=InotifyEmitter,
                               timeout=timeout)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/watchdog-0.8.3/src/watchdog/observers/inotify_buffer.py 
new/watchdog-0.9.0/src/watchdog/observers/inotify_buffer.py
--- old/watchdog-0.8.3/src/watchdog/observers/inotify_buffer.py 2015-02-11 
10:54:50.000000000 +0100
+++ new/watchdog-0.9.0/src/watchdog/observers/inotify_buffer.py 2018-08-27 
23:46:08.000000000 +0200
@@ -55,7 +55,8 @@
         IN_MOVE_TO event, remove the previous added matching IN_MOVE_FROM event
         and add them back to the queue as a tuple.
         """
-        while self.should_keep_running():
+        deleted_self = False
+        while self.should_keep_running() and not deleted_self:
             inotify_events = self._inotify.read_events()
             for inotify_event in inotify_events:
                 logger.debug("in-event %s", inotify_event)
@@ -74,3 +75,7 @@
                 else:
                     self._queue.put(inotify_event)
 
+                if inotify_event.is_delete_self and \
+                        inotify_event.src_path == self._inotify.path:
+                    # Deleted the watched directory, stop watching for events
+                    deleted_self = True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/src/watchdog/observers/inotify_c.py 
new/watchdog-0.9.0/src/watchdog/observers/inotify_c.py
--- old/watchdog-0.8.3/src/watchdog/observers/inotify_c.py      2015-02-11 
10:54:50.000000000 +0100
+++ new/watchdog-0.9.0/src/watchdog/observers/inotify_c.py      2018-08-28 
01:40:17.000000000 +0200
@@ -32,7 +32,7 @@
     libc_path = None
     try:
         libc_path = ctypes.util.find_library('c')
-    except (OSError, IOError):
+    except (OSError, IOError, RuntimeError):
         # Note: find_library will on some platforms raise these undocumented
         # errors, e.g.on android IOError "No usable temporary directory found"
         # will be raised.
@@ -45,7 +45,19 @@
     try:
         return ctypes.CDLL('libc.so')
     except (OSError, IOError):
+        pass
+
+    try:
         return ctypes.CDLL('libc.so.6')
+    except (OSError, IOError):
+        pass
+
+    # uClibc
+    try:
+        return ctypes.CDLL('libc.so.0')
+    except (OSError, IOError) as err:
+        raise err
+
 
 libc = _load_libc()
 
@@ -248,7 +260,8 @@
             Path string for which the watch will be removed.
         """
         with self._lock:
-            wd = self._remove_watch_bookkeeping(path)
+            wd = self._wd_for_path.pop(path)
+            del self._path_for_wd[wd]
             if inotify_rm_watch(self._inotify_fd, wd) == -1:
                 Inotify._raise_error()
 
@@ -257,8 +270,9 @@
         Closes the inotify instance and removes all associated watches.
         """
         with self._lock:
-            wd = self._wd_for_path[self._path]
-            inotify_rm_watch(self._inotify_fd, wd)
+            if self._path in self._wd_for_path:
+                wd = self._wd_for_path[self._path]
+                inotify_rm_watch(self._inotify_fd, wd)
             os.close(self._inotify_fd)
 
     def read_events(self, event_buffer_size=DEFAULT_EVENT_BUFFER_SIZE):
@@ -322,7 +336,9 @@
 
                 if inotify_event.is_ignored:
                     # Clean up book-keeping for deleted watches.
-                    self._remove_watch_bookkeeping(src_path)
+                    path = self._path_for_wd.pop(wd)
+                    if self._wd_for_path[path] == wd:
+                        del self._wd_for_path[path]
                     continue
 
                 event_list.append(inotify_event)
@@ -387,11 +403,6 @@
         self._path_for_wd[wd] = path
         return wd
 
-    def _remove_watch_bookkeeping(self, path):
-        wd = self._wd_for_path.pop(path)
-        del self._path_for_wd[wd]
-        return wd
-
     @staticmethod
     def _raise_error():
         """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/src/watchdog/observers/polling.py 
new/watchdog-0.9.0/src/watchdog/observers/polling.py
--- old/watchdog-0.8.3/src/watchdog/observers/polling.py        2015-02-11 
10:54:50.000000000 +0100
+++ new/watchdog-0.9.0/src/watchdog/observers/polling.py        2018-08-28 
03:25:42.000000000 +0200
@@ -88,7 +88,13 @@
 
             # Get event diff between fresh snapshot and previous snapshot.
             # Update snapshot.
-            new_snapshot = self._take_snapshot()
+            try:
+                new_snapshot = self._take_snapshot()
+            except OSError:
+                self.queue_event(DirDeletedEvent(self.watch.path))
+                self.stop()
+                return
+
             events = DirectorySnapshotDiff(self._snapshot, new_snapshot)
             self._snapshot = new_snapshot
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/watchdog-0.8.3/src/watchdog/observers/read_directory_changes.py 
new/watchdog-0.9.0/src/watchdog/observers/read_directory_changes.py
--- old/watchdog-0.8.3/src/watchdog/observers/read_directory_changes.py 
2015-02-11 10:54:50.000000000 +0100
+++ new/watchdog-0.9.0/src/watchdog/observers/read_directory_changes.py 
2018-08-28 03:15:27.000000000 +0200
@@ -19,14 +19,12 @@
 
 from __future__ import with_statement
 
-import ctypes
 import threading
 import os.path
 import time
 
 from watchdog.events import (
     DirCreatedEvent,
-    DirDeletedEvent,
     DirMovedEvent,
     DirModifiedEvent,
     FileCreatedEvent,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/src/watchdog/observers/winapi.py 
new/watchdog-0.9.0/src/watchdog/observers/winapi.py
--- old/watchdog-0.8.3/src/watchdog/observers/winapi.py 2015-02-11 
10:54:50.000000000 +0100
+++ new/watchdog-0.9.0/src/watchdog/observers/winapi.py 2018-08-28 
03:15:29.000000000 +0200
@@ -39,7 +39,6 @@
 from __future__ import with_statement
 
 import ctypes.wintypes
-import struct
 from functools import reduce
 
 try:
@@ -63,7 +62,7 @@
 
 FILE_FLAG_BACKUP_SEMANTICS = 0x02000000
 FILE_FLAG_OVERLAPPED = 0x40000000
-FILE_LIST_DIRECTORY = 0x01
+FILE_LIST_DIRECTORY = 1
 FILE_SHARE_READ = 0x01
 FILE_SHARE_WRITE = 0x02
 FILE_SHARE_DELETE = 0x04
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/src/watchdog/tricks/__init__.py 
new/watchdog-0.9.0/src/watchdog/tricks/__init__.py
--- old/watchdog-0.8.3/src/watchdog/tricks/__init__.py  2015-02-11 
10:54:50.000000000 +0100
+++ new/watchdog-0.9.0/src/watchdog/tricks/__init__.py  2018-08-27 
23:46:08.000000000 +0200
@@ -138,13 +138,13 @@
                  kill_after=10):
         super(AutoRestartTrick, self).__init__(
             patterns, ignore_patterns, ignore_directories)
-        self.command = ['setsid'] + command
+        self.command = command
         self.stop_signal = stop_signal
         self.kill_after = kill_after
         self.process = None
 
     def start(self):
-        self.process = subprocess.Popen(self.command)
+        self.process = subprocess.Popen(self.command, preexec_fn=os.setsid)
 
     def stop(self):
         if self.process is None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/src/watchdog/utils/__init__.py 
new/watchdog-0.9.0/src/watchdog/utils/__init__.py
--- old/watchdog-0.8.3/src/watchdog/utils/__init__.py   2015-02-11 
10:54:50.000000000 +0100
+++ new/watchdog-0.9.0/src/watchdog/utils/__init__.py   2018-08-28 
01:38:03.000000000 +0200
@@ -33,9 +33,8 @@
 import os
 import sys
 import threading
-import watchdog.utils.platform
+from watchdog.utils import platform
 from watchdog.utils.compat import Event
-from collections import namedtuple
 
 
 if sys.version_info[0] == 2 and platform.is_windows():
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/src/watchdog/utils/dirsnapshot.py 
new/watchdog-0.9.0/src/watchdog/utils/dirsnapshot.py
--- old/watchdog-0.8.3/src/watchdog/utils/dirsnapshot.py        2015-02-11 
10:54:50.000000000 +0100
+++ new/watchdog-0.9.0/src/watchdog/utils/dirsnapshot.py        2018-08-28 
02:49:06.000000000 +0200
@@ -47,7 +47,6 @@
 import errno
 import os
 from stat import S_ISDIR
-from watchdog.utils import platform
 from watchdog.utils import stat as default_stat
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/src/watchdog/utils/echo.py 
new/watchdog-0.9.0/src/watchdog/utils/echo.py
--- old/watchdog-0.8.3/src/watchdog/utils/echo.py       2015-02-11 
10:54:50.000000000 +0100
+++ new/watchdog-0.9.0/src/watchdog/utils/echo.py       2018-08-27 
23:46:08.000000000 +0200
@@ -41,10 +41,17 @@
     return item.__name__
 
 
-def is_classmethod(instancemethod):
+def is_classmethod(instancemethod, klass):
     " Determine if an instancemethod is a classmethod. "
-    return instancemethod.__self__ is not None
+    return inspect.ismethod(instancemethod) and instancemethod.__self__ is 
klass
 
+def is_static_method(method, klass):
+    """Returns True if method is an instance method of klass."""
+    for c in klass.mro():
+        if name(method) in c.__dict__:
+            return isinstance(c.__dict__[name(method)], staticmethod)
+    else:
+        return False
 
 def is_class_private_name(name):
     " Determine if a name is a class private name. "
@@ -115,20 +122,24 @@
     never_echo = "__str__", "__repr__",  # Avoid recursion printing method 
calls
     if mname in never_echo:
         pass
-    elif is_classmethod(method):
+    elif is_classmethod(method, klass):
         setattr(klass, mname, classmethod(echo(method.__func__, write)))
     else:
         setattr(klass, mname, echo(method, write))
 
-
 def echo_class(klass, write=sys.stdout.write):
     """ Echo calls to class methods and static functions
     """
     for _, method in inspect.getmembers(klass, inspect.ismethod):
+        #In python 3 only class methods are returned here, but in python2 
instance methods are too.
         echo_instancemethod(klass, method, write)
     for _, fn in inspect.getmembers(klass, inspect.isfunction):
-        setattr(klass, name(fn), staticmethod(echo(fn, write)))
-
+        if is_static_method(fn, klass):
+            setattr(klass, name(fn), staticmethod(echo(fn, write)))
+        else:
+            #It's not a class or a static method, so it must be an instance 
method.
+            #This should only be called in python 3, because in python 3 
instance methods are considered functions.
+            echo_instancemethod(klass, fn, write)
 
 def echo_module(mod, write=sys.stdout.write):
     """ Echo calls to functions and methods in a module.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/src/watchdog/utils/platform.py 
new/watchdog-0.9.0/src/watchdog/utils/platform.py
--- old/watchdog-0.8.3/src/watchdog/utils/platform.py   2015-02-11 
10:54:50.000000000 +0100
+++ new/watchdog-0.9.0/src/watchdog/utils/platform.py   2018-08-27 
23:46:08.000000000 +0200
@@ -33,7 +33,7 @@
         return PLATFORM_DARWIN
     elif sys.platform.startswith('linux'):
         return PLATFORM_LINUX
-    elif sys.platform.startswith('bsd'):
+    elif sys.platform.startswith(('dragonfly', 'freebsd', 'netbsd', 'openbsd', 
)):
         return PLATFORM_BSD
     else:
         return PLATFORM_UNKNOWN
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/src/watchdog/version.py 
new/watchdog-0.9.0/src/watchdog/version.py
--- old/watchdog-0.8.3/src/watchdog/version.py  2015-02-11 10:54:50.000000000 
+0100
+++ new/watchdog-0.9.0/src/watchdog/version.py  2018-08-28 22:25:40.000000000 
+0200
@@ -20,8 +20,8 @@
 # When updating this version number, please update the
 # ``docs/source/global.rst.inc`` file as well.
 VERSION_MAJOR = 0
-VERSION_MINOR = 8
-VERSION_BUILD = 3
+VERSION_MINOR = 9
+VERSION_BUILD = 0
 VERSION_INFO = (VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD)
 VERSION_STRING = "%d.%d.%d" % VERSION_INFO
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/src/watchdog/watchmedo.py 
new/watchdog-0.9.0/src/watchdog/watchmedo.py
--- old/watchdog-0.8.3/src/watchdog/watchmedo.py        2015-02-11 
10:54:50.000000000 +0100
+++ new/watchdog-0.9.0/src/watchdog/watchmedo.py        2018-08-27 
23:46:08.000000000 +0200
@@ -418,6 +418,9 @@
      default=False,
      help="Ignore events that occur while command is still being executed " \
           "to avoid multiple simultaneous instances")
+@arg('--debug-force-polling',
+     default=False,
+     help='[debug] forces polling')
 @expects_obj
 def shell_command(args):
     """
@@ -426,12 +429,16 @@
     :param args:
         Command line argument options.
     """
-    from watchdog.observers import Observer
     from watchdog.tricks import ShellCommandTrick
 
     if not args.command:
         args.command = None
 
+    if args.debug_force_polling:
+        from watchdog.observers.polling import PollingObserver as Observer
+    else:
+        from watchdog.observers import Observer
+
     patterns, ignore_patterns = parse_patterns(args.patterns,
                                                args.ignore_patterns)
     handler = ShellCommandTrick(shell_command=args.command,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/src/watchdog.egg-info/PKG-INFO 
new/watchdog-0.9.0/src/watchdog.egg-info/PKG-INFO
--- old/watchdog-0.8.3/src/watchdog.egg-info/PKG-INFO   2015-02-11 
11:25:48.000000000 +0100
+++ new/watchdog-0.9.0/src/watchdog.egg-info/PKG-INFO   2018-08-28 
22:42:19.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: watchdog
-Version: 0.8.3
+Version: 0.9.0
 Summary: Filesystem events monitoring
 Home-page: http://github.com/gorakhargosh/watchdog
 Author: Yesudeep Mangalapilly
@@ -174,7 +174,7 @@
         
             pip install pytest
             pip install -e .
-            py.tests tests
+            py.test tests
         
         
         Supported Platforms
@@ -317,7 +317,16 @@
 Classifier: Operating System :: Microsoft :: Windows :: Windows NT/2000
 Classifier: Operating System :: OS Independent
 Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
 Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.2
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: Implementation :: PyPy
 Classifier: Programming Language :: C
 Classifier: Topic :: Software Development :: Libraries
 Classifier: Topic :: System :: Monitoring
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/src/watchdog.egg-info/SOURCES.txt 
new/watchdog-0.9.0/src/watchdog.egg-info/SOURCES.txt
--- old/watchdog-0.8.3/src/watchdog.egg-info/SOURCES.txt        2015-02-11 
11:25:48.000000000 +0100
+++ new/watchdog-0.9.0/src/watchdog.egg-info/SOURCES.txt        2018-08-28 
22:42:19.000000000 +0200
@@ -64,6 +64,7 @@
 tests/test_delayed_queue.py
 tests/test_emitter.py
 tests/test_inotify_buffer.py
+tests/test_inotify_c.py
 tests/test_observer.py
 tests/test_skip_repeats_queue.py
 tests/test_snapshot_diff.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/src/watchdog.egg-info/requires.txt 
new/watchdog-0.9.0/src/watchdog.egg-info/requires.txt
--- old/watchdog-0.8.3/src/watchdog.egg-info/requires.txt       2015-02-11 
11:25:48.000000000 +0100
+++ new/watchdog-0.9.0/src/watchdog.egg-info/requires.txt       2018-08-28 
22:42:19.000000000 +0200
@@ -1,3 +1,3 @@
-PyYAML >=3.10
-argh >=0.24.1
-pathtools >=0.1.1
\ No newline at end of file
+PyYAML>=3.10
+argh>=0.24.1
+pathtools>=0.1.1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/tests/__init__.py 
new/watchdog-0.9.0/tests/__init__.py
--- old/watchdog-0.8.3/tests/__init__.py        2015-02-11 10:54:50.000000000 
+0100
+++ new/watchdog-0.9.0/tests/__init__.py        2018-08-28 02:40:39.000000000 
+0200
@@ -14,14 +14,7 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-
-import os
-import pytest
-from . import shell
 from sys import version_info
-from functools import partial
-
-__all__ = ['unittest', 'Queue', 'tmpdir', 'p']
 
 if version_info < (2, 7):
     import unittest2 as unittest
@@ -33,20 +26,4 @@
 except ImportError:
     from queue import Queue  # Python 3
 
-
[email protected]()
-def tmpdir(request):
-    path = os.path.realpath(shell.mkdtemp())
-    def finalizer():
-        shell.rm(path, recursive=True)
-    request.addfinalizer(finalizer)
-    return path
-
-
[email protected]()
-def p(tmpdir, *args):
-    """
-    Convenience function to join the temporary directory path
-    with the provided arguments.
-    """
-    return partial(os.path.join, tmpdir)
+__all__ = ["unittest", "Queue"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/tests/legacy/test_watchdog_events.py 
new/watchdog-0.9.0/tests/legacy/test_watchdog_events.py
--- old/watchdog-0.8.3/tests/legacy/test_watchdog_events.py     2015-02-11 
10:54:50.000000000 +0100
+++ new/watchdog-0.9.0/tests/legacy/test_watchdog_events.py     2018-08-28 
02:55:59.000000000 +0200
@@ -19,13 +19,10 @@
 
 from tests import unittest
 
-from utils import list_attributes
 from watchdog.utils import has_attribute
 from pathtools.patterns import filter_paths
 
 from watchdog.events import (
-    FileSystemEvent,
-    FileSystemMovedEvent,
     FileDeletedEvent,
     FileModifiedEvent,
     FileCreatedEvent,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/watchdog-0.8.3/tests/legacy/test_watchdog_observers_polling.py 
new/watchdog-0.9.0/tests/legacy/test_watchdog_observers_polling.py
--- old/watchdog-0.8.3/tests/legacy/test_watchdog_observers_polling.py  
2015-02-11 10:54:50.000000000 +0100
+++ new/watchdog-0.9.0/tests/legacy/test_watchdog_observers_polling.py  
2018-08-28 02:13:03.000000000 +0200
@@ -18,7 +18,6 @@
 
 
 import os
-import sys
 from tests import unittest
 
 try:
@@ -134,6 +133,35 @@
 
         got = set()
         while True:
+            try:
+                event, _ = self.event_queue.get_nowait()
+                got.add(event)
+            except queue.Empty:
+                break
+
+        self.assertEqual(expected, got)
+
+    def test_delete_watched_dir(self):
+        SLEEP_TIME = 0.4
+        self.emitter.start()
+        rm(p(''), recursive=True)
+        sleep(SLEEP_TIME)
+        self.emitter.stop()
+
+        # What we need here for the tests to pass is a collection type
+        # that is:
+        #   * unordered
+        #   * non-unique
+        # A multiset! Python's collections.Counter class seems appropriate.
+        expected = set(
+            [
+
+                DirDeletedEvent(os.path.dirname(p(''))),
+            ]
+        )
+
+        got = set()
+        while True:
             try:
                 event, _ = self.event_queue.get_nowait()
                 got.add(event)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/tests/shell.py 
new/watchdog-0.9.0/tests/shell.py
--- old/watchdog-0.8.3/tests/shell.py   2015-02-11 10:54:50.000000000 +0100
+++ new/watchdog-0.9.0/tests/shell.py   2018-08-28 03:15:12.000000000 +0200
@@ -28,7 +28,6 @@
 import tempfile
 import shutil
 import errno
-import time
 
 
 # def tree(path='.', show_files=False):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/tests/test_emitter.py 
new/watchdog-0.9.0/tests/test_emitter.py
--- old/watchdog-0.8.3/tests/test_emitter.py    2015-02-11 10:54:50.000000000 
+0100
+++ new/watchdog-0.9.0/tests/test_emitter.py    2018-08-28 02:49:20.000000000 
+0200
@@ -24,7 +24,15 @@
 from .shell import mkdir, touch, mv, rm, mkdtemp
 from watchdog.utils import platform
 from watchdog.utils.unicode_paths import str_cls
-from watchdog.events import *
+from watchdog.events import (
+    FileDeletedEvent,
+    FileModifiedEvent,
+    FileCreatedEvent,
+    FileMovedEvent,
+    DirDeletedEvent,
+    DirModifiedEvent,
+    DirCreatedEvent,
+)
 from watchdog.observers.api import ObservedWatch
 
 pytestmark = pytest.mark.skipif(not platform.is_linux() and not 
platform.is_darwin(), reason="")
@@ -32,8 +40,10 @@
     from watchdog.observers.inotify import InotifyEmitter as Emitter
 elif platform.is_darwin():
     from watchdog.observers.fsevents2 import FSEventsEmitter as Emitter
+from watchdog.observers.inotify import InotifyFullEmitter
 
 logging.basicConfig(level=logging.DEBUG)
+logger = logging.getLogger(__name__)
 
 
 def setup_function(function):
@@ -43,10 +53,14 @@
     event_queue = Queue()
 
 
-def start_watching(path=None):
+def start_watching(path=None, use_full_emitter=False):
     path = p('') if path is None else path
     global emitter
-    emitter = Emitter(event_queue, ObservedWatch(path, recursive=True))
+    if platform.is_linux() and use_full_emitter:
+        emitter = InotifyFullEmitter(event_queue, ObservedWatch(path, 
recursive=True))
+    else:
+        emitter = Emitter(event_queue, ObservedWatch(path, recursive=True))
+
     if platform.is_darwin():
         # FSEvents will report old evens (like create for mkdtemp in test
         # setup. Waiting for a considerable time seems to 'flush' the events.
@@ -131,6 +145,16 @@
     assert isinstance(event, FileCreatedEvent)
     assert event.src_path == p('dir2', 'b')
 
+def test_move_to_full():
+    mkdir(p('dir1'))
+    mkdir(p('dir2'))
+    touch(p('dir1', 'a'))
+    start_watching(p('dir2'), use_full_emitter=True)
+    mv(p('dir1', 'a'), p('dir2', 'b'))
+    event = event_queue.get(timeout=5)[0]
+    assert isinstance(event, FileMovedEvent)
+    assert event.dest_path == p('dir2', 'b')
+    assert event.src_path == None #Should equal none since the path was not 
watched
 
 def test_move_from():
     mkdir(p('dir1'))
@@ -142,7 +166,17 @@
     event = event_queue.get(timeout=5)[0]
     assert isinstance(event, FileDeletedEvent)
     assert event.src_path == p('dir1', 'a')
-
+ 
+def test_move_from_full():
+    mkdir(p('dir1'))
+    mkdir(p('dir2'))
+    touch(p('dir1', 'a'))
+    start_watching(p('dir1'), use_full_emitter=True)
+    mv(p('dir1', 'a'), p('dir2', 'b'))
+    event = event_queue.get(timeout=5)[0]
+    assert isinstance(event, FileMovedEvent)
+    assert event.src_path == p('dir1', 'a')
+    assert event.dest_path == None #Should equal None since path not watched
 
 def test_separate_consecutive_moves():
     mkdir(p('dir1'))
@@ -175,6 +209,34 @@
     event_queue.get(timeout=5)[0]
 
 
+def test_fast_subdirectory_creation_deletion():
+    root_dir = p('dir1')
+    sub_dir = p('dir1', 'subdir1')
+    times = 30
+    mkdir(root_dir)
+    start_watching(root_dir)
+    for unused in range(times):
+        mkdir(sub_dir)
+        rm(sub_dir, True)
+    count = {DirCreatedEvent: 0,
+             DirModifiedEvent: 0,
+             DirDeletedEvent: 0}
+    etype_for_dir = {DirCreatedEvent: sub_dir,
+                     DirModifiedEvent: root_dir,
+                     DirDeletedEvent: sub_dir}
+    for unused in range(times * 4):
+        event = event_queue.get(timeout=5)[0]
+        logger.debug(event)
+        etype = type(event)
+        count[etype] += 1
+        assert event.src_path == etype_for_dir[etype]
+        assert count[DirCreatedEvent] >= count[DirDeletedEvent]
+        assert count[DirCreatedEvent] + count[DirDeletedEvent] >= 
count[DirModifiedEvent]
+    assert count == {DirCreatedEvent: times,
+                     DirModifiedEvent: times * 2,
+                     DirDeletedEvent: times}
+
+
 def test_passing_unicode_should_give_unicode():
     start_watching(p(''))
     touch(p('a'))
@@ -186,4 +248,4 @@
     start_watching(p('').encode())
     touch(p('a'))
     event = event_queue.get(timeout=5)[0]
-    assert isinstance(event.src_path, bytes)
+    assert isinstance(event.src_path, bytes)
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/tests/test_inotify_buffer.py 
new/watchdog-0.9.0/tests/test_inotify_buffer.py
--- old/watchdog-0.8.3/tests/test_inotify_buffer.py     2015-02-11 
10:54:50.000000000 +0100
+++ new/watchdog-0.9.0/tests/test_inotify_buffer.py     2018-08-28 
02:49:24.000000000 +0200
@@ -18,14 +18,11 @@
 import os
 import random
 import pytest
-from tests import tmpdir, p  # pytest magic
-from .shell import mkdir, touch, mv
-from watchdog.observers.api import ObservedWatch
+from .shell import mkdir, touch, mv, rm
 from watchdog.utils import platform
 
 pytestmark = pytest.mark.skipif(not platform.is_linux(), reason="")
 if platform.is_linux():
-    from watchdog.observers.inotify import InotifyEmitter
     from watchdog.observers.inotify_buffer import InotifyBuffer
 
 
@@ -104,6 +101,19 @@
     inotify.close()
 
 
[email protected](5)
+def test_delete_watched_directory(p):
+    mkdir(p('dir'))
+    inotify = InotifyBuffer(p('dir').encode())
+    rm(p('dir'), recursive=True)
+
+    # Wait for the event to be picked up
+    inotify.read_event()
+
+    # Ensure InotifyBuffer shuts down cleanly without raising an exception
+    inotify.close()
+
+
 def test_close_should_terminate_thread(p):
     inotify = InotifyBuffer(p('').encode(), recursive=True)
     assert inotify.is_alive()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/tests/test_inotify_c.py 
new/watchdog-0.9.0/tests/test_inotify_c.py
--- old/watchdog-0.8.3/tests/test_inotify_c.py  1970-01-01 01:00:00.000000000 
+0100
+++ new/watchdog-0.9.0/tests/test_inotify_c.py  2018-08-27 23:46:08.000000000 
+0200
@@ -0,0 +1,117 @@
+from __future__ import unicode_literals
+import os
+import pytest
+import logging
+import contextlib
+from tests import Queue
+from functools import partial
+from .shell import rm, mkdtemp
+from watchdog.utils import platform
+from watchdog.events import DirCreatedEvent, DirDeletedEvent, DirModifiedEvent
+from watchdog.observers.api import ObservedWatch
+
+if platform.is_linux():
+    from watchdog.observers.inotify import InotifyFullEmitter, InotifyEmitter
+
+
+logging.basicConfig(level=logging.DEBUG)
+logger = logging.getLogger(__name__)
+
+
+def setup_function(function):
+    global p, event_queue
+    tmpdir = os.path.realpath(mkdtemp())
+    p = partial(os.path.join, tmpdir)
+    event_queue = Queue()
+
+
[email protected]
+def watching(path=None, use_full_emitter=False):
+    path = p('') if path is None else path
+    global emitter
+    Emitter = InotifyFullEmitter if use_full_emitter else InotifyEmitter
+    emitter = Emitter(event_queue, ObservedWatch(path, recursive=True))
+    emitter.start()
+    yield
+    emitter.stop()
+    emitter.join(5)
+
+
+def teardown_function(function):
+    rm(p(''), recursive=True)
+    assert not emitter.is_alive()
+
+
[email protected](not platform.is_linux(),
+                    reason="Testing with inotify messages (Linux only)")
+def test_late_double_deletion(monkeypatch):
+    inotify_fd = type(str("FD"), (object,), {})() # Empty object
+    inotify_fd.last = 0
+    inotify_fd.wds = []
+
+    # CREATE DELETE CREATE DELETE DELETE_SELF IGNORE DELETE_SELF IGNORE
+    inotify_fd.buf = (
+      # IN_CREATE|IS_DIR (wd = 1, path = subdir1)
+      b"\x01\x00\x00\x00\x00\x01\x00\x40\x00\x00\x00\x00\x10\x00\x00\x00"
+      b"\x73\x75\x62\x64\x69\x72\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+      # IN_DELETE|IS_DIR (wd = 1, path = subdir1)
+      b"\x01\x00\x00\x00\x00\x02\x00\x40\x00\x00\x00\x00\x10\x00\x00\x00"
+      b"\x73\x75\x62\x64\x69\x72\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+    ) * 2 + (
+      # IN_DELETE_SELF (wd = 2)
+      b"\x02\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+      # IN_IGNORE (wd = 2)
+      b"\x02\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+      # IN_DELETE_SELF (wd = 3)
+      b"\x03\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+      # IN_IGNORE (wd = 3)
+      b"\x03\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+    )
+
+    os_read_bkp = os.read
+    def fakeread(fd, length):
+        if fd is inotify_fd:
+            result, fd.buf = fd.buf[:length], fd.buf[length:]
+            return result
+        return os_read_bkp(fd, length)
+
+    os_close_bkp = os.close
+    def fakeclose(fd):
+        if fd is not inotify_fd:
+            os_close_bkp(fd)
+
+    def inotify_init():
+        return inotify_fd
+
+    def inotify_add_watch(fd, path, mask):
+        fd.last += 1
+        logger.debug("New wd = %d" % fd.last)
+        fd.wds.append(fd.last)
+        return fd.last
+
+    def inotify_rm_watch(fd, wd):
+        logger.debug("Removing wd = %d" % wd)
+        fd.wds.remove(wd)
+        return 0
+
+    # Mocks the API!
+    from watchdog.observers import inotify_c
+    monkeypatch.setattr(os, "read", fakeread)
+    monkeypatch.setattr(os, "close", fakeclose)
+    monkeypatch.setattr(inotify_c, "inotify_init", inotify_init)
+    monkeypatch.setattr(inotify_c, "inotify_add_watch", inotify_add_watch)
+    monkeypatch.setattr(inotify_c, "inotify_rm_watch", inotify_rm_watch)
+
+    with watching(p('')):
+        # Watchdog Events
+        for evt_cls in [DirCreatedEvent, DirDeletedEvent] * 2:
+            event = event_queue.get(timeout=5)[0]
+            assert isinstance(event, evt_cls)
+            assert event.src_path == p('subdir1')
+            event = event_queue.get(timeout=5)[0]
+            assert isinstance(event, DirModifiedEvent)
+            assert event.src_path == p('').rstrip(os.path.sep)
+
+    assert inotify_fd.last == 3 # Number of directories
+    assert inotify_fd.buf == b"" # Didn't miss any event
+    assert inotify_fd.wds == [2, 3] # Only 1 is removed explicitly
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/watchdog-0.8.3/tests/test_snapshot_diff.py 
new/watchdog-0.9.0/tests/test_snapshot_diff.py
--- old/watchdog-0.8.3/tests/test_snapshot_diff.py      2015-02-11 
10:54:50.000000000 +0100
+++ new/watchdog-0.9.0/tests/test_snapshot_diff.py      2018-08-28 
02:55:21.000000000 +0200
@@ -15,7 +15,6 @@
 # limitations under the License.
 
 import time
-from tests import tmpdir, p  # pytest magic
 from .shell import mkdir, touch, mv
 from watchdog.utils.dirsnapshot import DirectorySnapshot
 from watchdog.utils.dirsnapshot import DirectorySnapshotDiff


Reply via email to