From 11c64d67c3c35f4830352500047feadcbeef6099 Mon Sep 17 00:00:00 2001 From: Max Vilimpoc Date: Thu, 10 Apr 2014 02:09:04 +0200 Subject: [PATCH] Add --smoothing parameter for watchmedo --command to ignore smooth over / ignore multiple triggering events. --- src/watchdog/observers/api.py | 17 ++++++++++++++++- src/watchdog/observers/fsevents.py | 8 +++++--- src/watchdog/observers/inotify.py | 8 +++++--- src/watchdog/observers/kqueue.py | 7 ++++--- src/watchdog/observers/polling.py | 7 ++++--- .../observers/read_directory_changes.py | 8 +++++--- src/watchdog/watchmedo.py | 6 +++++- 7 files changed, 44 insertions(+), 17 deletions(-) diff --git a/src/watchdog/observers/api.py b/src/watchdog/observers/api.py index 22f7fe577..87334b12b 100644 --- a/src/watchdog/observers/api.py +++ b/src/watchdog/observers/api.py @@ -51,6 +51,7 @@ from __future__ import with_statement import threading +import time try: import queue # IGNORE:F0401 @@ -62,6 +63,7 @@ DEFAULT_EMITTER_TIMEOUT = 1 # in seconds. DEFAULT_OBSERVER_TIMEOUT = 1 # in seconds. +DEFAULT_SMOOTHING_TIMEOUT = 0 # in seconds. # Collection classes @@ -247,7 +249,7 @@ class BaseObserver(EventDispatcher): """Base observer.""" - def __init__(self, emitter_class, timeout=DEFAULT_OBSERVER_TIMEOUT): + def __init__(self, emitter_class, timeout=DEFAULT_OBSERVER_TIMEOUT, smoothing=DEFAULT_SMOOTHING_TIMEOUT): EventDispatcher.__init__(self, timeout) self._emitter_class = emitter_class self._lock = threading.Lock() @@ -255,6 +257,7 @@ def __init__(self, emitter_class, timeout=DEFAULT_OBSERVER_TIMEOUT): self._handlers = dict() self._emitters = set() self._emitter_for_watch = dict() + self._smoothing = smoothing def _add_emitter(self, emitter): self._emitter_for_watch[emitter.watch] = emitter @@ -404,6 +407,18 @@ def _dispatch_event(self, event, watch): def dispatch_events(self, event_queue, timeout): event, watch = event_queue.get(block=True, timeout=timeout) + + # Sleep for the specified amount of time, then clean out the + # event queue, and then dispatch the event. + if self._smoothing > 0: + time.sleep(self._smoothing) + + if not event_queue.empty(): + print("Smoothing over / ignoring {0} filesystem events that arrived after the triggering event.".format(event_queue.qsize())) + + while not event_queue.empty(): + event_queue.get_nowait() + try: self._dispatch_event(event, watch) except KeyError: diff --git a/src/watchdog/observers/fsevents.py b/src/watchdog/observers/fsevents.py index 674814800..9b4b0848d 100644 --- a/src/watchdog/observers/fsevents.py +++ b/src/watchdog/observers/fsevents.py @@ -46,7 +46,8 @@ BaseObserver, EventEmitter, DEFAULT_EMITTER_TIMEOUT, - DEFAULT_OBSERVER_TIMEOUT + DEFAULT_OBSERVER_TIMEOUT, + DEFAULT_SMOOTHING_TIMEOUT ) @@ -143,9 +144,10 @@ def callback(pathnames, flags, emitter=self): class FSEventsObserver(BaseObserver): - def __init__(self, timeout=DEFAULT_OBSERVER_TIMEOUT): + def __init__(self, timeout=DEFAULT_OBSERVER_TIMEOUT, smoothing=DEFAULT_SMOOTHING_TIMEOUT): BaseObserver.__init__(self, emitter_class=FSEventsEmitter, - timeout=timeout) + timeout=timeout, + smoothing=smoothing) def schedule(self, event_handler, path, recursive=False): # Python 2/3 compat diff --git a/src/watchdog/observers/inotify.py b/src/watchdog/observers/inotify.py index f89702ff8..33cf9b31a 100644 --- a/src/watchdog/observers/inotify.py +++ b/src/watchdog/observers/inotify.py @@ -77,7 +77,8 @@ EventEmitter, BaseObserver, DEFAULT_EMITTER_TIMEOUT, - DEFAULT_OBSERVER_TIMEOUT + DEFAULT_OBSERVER_TIMEOUT, + DEFAULT_SMOOTHING_TIMEOUT ) from watchdog.events import ( @@ -183,6 +184,7 @@ class InotifyObserver(BaseObserver): calls to event handlers. """ - def __init__(self, timeout=DEFAULT_OBSERVER_TIMEOUT): + def __init__(self, timeout=DEFAULT_OBSERVER_TIMEOUT, smoothing=DEFAULT_SMOOTHING_TIMEOUT): BaseObserver.__init__(self, emitter_class=InotifyEmitter, - timeout=timeout) + timeout=timeout, + smoothing=smoothing) diff --git a/src/watchdog/observers/kqueue.py b/src/watchdog/observers/kqueue.py index 9ace92321..8224ac348 100644 --- a/src/watchdog/observers/kqueue.py +++ b/src/watchdog/observers/kqueue.py @@ -100,7 +100,8 @@ BaseObserver, EventEmitter, DEFAULT_OBSERVER_TIMEOUT, - DEFAULT_EMITTER_TIMEOUT + DEFAULT_EMITTER_TIMEOUT, + DEFAULT_SMOOTHING_TIMEOUT ) from watchdog.utils.dirsnapshot import DirectorySnapshot @@ -722,5 +723,5 @@ class KqueueObserver(BaseObserver): calls to event handlers. """ - def __init__(self, timeout=DEFAULT_OBSERVER_TIMEOUT): - BaseObserver.__init__(self, emitter_class=KqueueEmitter, timeout=timeout) + def __init__(self, timeout=DEFAULT_OBSERVER_TIMEOUT, smoothing=DEFAULT_SMOOTHING_TIMEOUT): + BaseObserver.__init__(self, emitter_class=KqueueEmitter, timeout=timeout, smoothing=DEFAULT_SMOOTHING_TIMEOUT) diff --git a/src/watchdog/observers/polling.py b/src/watchdog/observers/polling.py index 3039ceb36..cc23e3a8a 100644 --- a/src/watchdog/observers/polling.py +++ b/src/watchdog/observers/polling.py @@ -44,7 +44,8 @@ EventEmitter, BaseObserver, DEFAULT_OBSERVER_TIMEOUT, - DEFAULT_EMITTER_TIMEOUT + DEFAULT_EMITTER_TIMEOUT, + DEFAULT_SMOOTHING_TIMEOUT ) from watchdog.events import ( @@ -119,8 +120,8 @@ class PollingObserver(BaseObserver): system changes. """ - def __init__(self, timeout=DEFAULT_OBSERVER_TIMEOUT): - BaseObserver.__init__(self, emitter_class=PollingEmitter, timeout=timeout) + def __init__(self, timeout=DEFAULT_OBSERVER_TIMEOUT, smoothing=DEFAULT_SMOOTHING_TIMEOUT): + BaseObserver.__init__(self, emitter_class=PollingEmitter, timeout=timeout, smoothing=smoothing) class PollingObserverVFS(BaseObserver): diff --git a/src/watchdog/observers/read_directory_changes.py b/src/watchdog/observers/read_directory_changes.py index d51966182..52f876d7c 100644 --- a/src/watchdog/observers/read_directory_changes.py +++ b/src/watchdog/observers/read_directory_changes.py @@ -47,7 +47,8 @@ EventEmitter, BaseObserver, DEFAULT_OBSERVER_TIMEOUT, - DEFAULT_EMITTER_TIMEOUT + DEFAULT_EMITTER_TIMEOUT, + DEFAULT_SMOOTHING_TIMEOUT ) from watchdog.events import ( @@ -138,10 +139,11 @@ class WindowsApiObserver(BaseObserver): calls to event handlers. """ - def __init__(self, timeout=DEFAULT_OBSERVER_TIMEOUT): + def __init__(self, timeout=DEFAULT_OBSERVER_TIMEOUT, smoothing=DEFAULT_SMOOTHING_TIMEOUT): BaseObserver.__init__(self, emitter_class=WindowsApiEmitter, - timeout=timeout) + timeout=timeout, + smoothing=smoothing) def _generate_sub_created_events_for(src_dir_path): diff --git a/src/watchdog/watchmedo.py b/src/watchdog/watchmedo.py index 756c88d13..ef871452b 100755 --- a/src/watchdog/watchmedo.py +++ b/src/watchdog/watchmedo.py @@ -417,6 +417,10 @@ def log(args): action='store_true', default=False, help="Ignore events that happen while the previous process is still running") +@arg('-s', '--smoothing', + dest='smoothing', + default=0, + help='gather and ignore this many seconds worth of filesystem events after the initial event before running the shell command') def shell_command(args): """ Subcommand to execute shell commands in response to file system events. @@ -438,7 +442,7 @@ def shell_command(args): ignore_directories=args.ignore_directories, wait_for_process=args.wait_for_process, no_parallel_processes=args.no_parallel_processes) - observer = Observer(timeout=args.timeout) + observer = Observer(timeout=args.timeout, smoothing=args.smoothing) observe_with(observer, handler, args.directories, args.recursive)