Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the option to choose what events to listen to #911

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ as command-line arguments and logs events generated:
import logging
from watchdog.observers import Observer
from watchdog.events import LoggingEventHandler
from watchdog.observers.inotify_c import WATCHDOG_ALL_EVENTS

if __name__ == "__main__":
logging.basicConfig(level=logging.INFO,
Expand All @@ -33,7 +34,7 @@ as command-line arguments and logs events generated:
path = sys.argv[1] if len(sys.argv) > 1 else '.'
event_handler = LoggingEventHandler()
observer = Observer()
observer.schedule(event_handler, path, recursive=True)
observer.schedule(event_handler, path, recursive=True, event_mask=WATCHDOG_ALL_EVENTS)
observer.start()
try:
while True:
Expand Down
3 changes: 2 additions & 1 deletion docs/source/examples/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@

from watchdog.observers import Observer
from watchdog.tricks import LoggerTrick
from watchdog.observers.inotify_c import WATCHDOG_ALL_EVENTS

event_handler = LoggerTrick()
observer = Observer()
observer.schedule(event_handler, sys.argv[1], recursive=True)
observer.schedule(event_handler, sys.argv[1], recursive=True, event_mask=WATCHDOG_ALL_EVENTS)
observer.start()
try:
while True:
Expand Down
3 changes: 2 additions & 1 deletion docs/source/examples/patterns.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from watchdog.events import PatternMatchingEventHandler
from watchdog.observers import Observer
from watchdog.observers.inotify_c import WATCHDOG_ALL_EVENTS

import logging
logging.basicConfig(level=logging.DEBUG)
Expand All @@ -19,7 +20,7 @@ def on_any_event(self, event):
ignore_patterns=['version.py'],
ignore_directories=True)
observer = Observer()
observer.schedule(event_handler, sys.argv[1], recursive=True)
observer.schedule(event_handler, sys.argv[1], recursive=True, event_mask=WATCHDOG_ALL_EVENTS)
observer.start()
try:
while True:
Expand Down
3 changes: 2 additions & 1 deletion docs/source/examples/simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from watchdog.events import FileSystemEventHandler
from watchdog.observers import Observer
from watchdog.observers.inotify_c import WATCHDOG_ALL_EVENTS

logging.basicConfig(level=logging.DEBUG)

Expand All @@ -31,7 +32,7 @@ def on_modified(self, event):

event_handler = MyEventHandler()
observer = Observer()
observer.schedule(event_handler, path, recursive=True)
observer.schedule(event_handler, path, recursive=True, event_mask=WATCHDOG_ALL_EVENTS)
observer.start()
try:
while True:
Expand Down
3 changes: 2 additions & 1 deletion docs/source/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ file system changes and simply log them to the console::
import logging
from watchdog.observers import Observer
from watchdog.events import LoggingEventHandler
from watchdog.observers.inotify_c import WATCHDOG_ALL_EVENTS

if __name__ == "__main__":
logging.basicConfig(level=logging.INFO,
Expand All @@ -43,7 +44,7 @@ file system changes and simply log them to the console::
path = sys.argv[1] if len(sys.argv) > 1 else '.'
event_handler = LoggingEventHandler()
observer = Observer()
observer.schedule(event_handler, path, recursive=True)
observer.schedule(event_handler, path, recursive=True, event_mask=WATCHDOG_ALL_EVENTS)
observer.start()
try:
while observer.is_alive():
Expand Down
21 changes: 16 additions & 5 deletions src/watchdog/observers/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

from watchdog.utils import BaseThread
from watchdog.utils.bricks import SkipRepeatsQueue
from watchdog.observers.inotify_c import WATCHDOG_ALL_EVENTS
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it would make sense to define a generalised version of WATCHDOG_ALL_EVENTS in the public API instead of depending on implementation-specific constants for the inotify backend?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for sure!


DEFAULT_EMITTER_TIMEOUT = 1 # in seconds.
DEFAULT_OBSERVER_TIMEOUT = 1 # in seconds.
Expand All @@ -43,14 +44,17 @@ class ObservedWatch:
Path string.
:param recursive:
``True`` if watch is recursive; ``False`` otherwise.
:param event_mask:
Holds the event type to watch for.
"""

def __init__(self, path, recursive):
def __init__(self, path, recursive, event_mask):
if isinstance(path, Path):
self._path = str(path)
else:
self._path = path
self._is_recursive = recursive
self._event_mask = event_mask

@property
def path(self):
Expand All @@ -62,6 +66,11 @@ def is_recursive(self):
"""Determines whether subdirectories are watched for the path."""
return self._is_recursive

@property
def event_mask(self):
"""Determines what events to watch for."""
return self._event_mask

@property
def key(self):
return self.path, self.is_recursive
Expand All @@ -76,8 +85,8 @@ def __hash__(self):
return hash(self.key)

def __repr__(self):
return "<%s: path=%s, is_recursive=%s>" % (
type(self).__name__, self.path, self.is_recursive)
return "<%s: path=%s, is_recursive=%s, event_mask=%s>" % (
type(self).__name__, self.path, self.is_recursive, self.event_mask)


# Observer classes
Expand Down Expand Up @@ -265,7 +274,7 @@ def start(self):
raise
super().start()

def schedule(self, event_handler, path, recursive=False):
def schedule(self, event_handler, path, recursive=False, event_mask=WATCHDOG_ALL_EVENTS):
"""
Schedules watching a path and calls appropriate methods specified
in the given event handler in response to file system events.
Expand All @@ -285,12 +294,14 @@ def schedule(self, event_handler, path, recursive=False):
traversed recursively; ``False`` otherwise.
:type recursive:
``bool``
:param event_mask:
Holds the type of event to listen to
:return:
An :class:`ObservedWatch` object instance representing
a watch.
"""
with self._lock:
watch = ObservedWatch(path, recursive)
watch = ObservedWatch(path, recursive, event_mask)
self._add_handler_for_watch(event_handler, watch)

# If we don't have an emitter for this watch already, create it.
Expand Down
5 changes: 3 additions & 2 deletions src/watchdog/observers/fsevents.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
DEFAULT_OBSERVER_TIMEOUT
)
from watchdog.utils.dirsnapshot import DirectorySnapshot
from watchdog.observers.inotify_c import WATCHDOG_ALL_EVENTS

logger = logging.getLogger('fsevents')

Expand Down Expand Up @@ -339,9 +340,9 @@ class FSEventsObserver(BaseObserver):
def __init__(self, timeout=DEFAULT_OBSERVER_TIMEOUT):
super().__init__(emitter_class=FSEventsEmitter, timeout=timeout)

def schedule(self, event_handler, path, recursive=False):
def schedule(self, event_handler, path, recursive=False, event_mask=WATCHDOG_ALL_EVENTS):
# Fix for issue #26: Trace/BPT error when given a unicode path
# string. https://github.com/gorakhargosh/watchdog/issues#issue/26
if isinstance(path, str):
path = unicodedata.normalize('NFC', path)
return BaseObserver.schedule(self, event_handler, path, recursive)
return BaseObserver.schedule(self, event_handler, path, recursive, event_mask)
2 changes: 1 addition & 1 deletion src/watchdog/observers/inotify.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def __init__(self, event_queue, watch, timeout=DEFAULT_EMITTER_TIMEOUT):

def on_thread_start(self):
path = os.fsencode(self.watch.path)
self._inotify = InotifyBuffer(path, self.watch.is_recursive)
self._inotify = InotifyBuffer(path, self.watch.is_recursive, self.watch.event_mask)

def on_thread_stop(self):
if self._inotify:
Expand Down
9 changes: 6 additions & 3 deletions src/watchdog/observers/inotify_buffer.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
import logging
from watchdog.utils import BaseThread
from watchdog.utils.delayed_queue import DelayedQueue
from watchdog.observers.inotify_c import Inotify
from watchdog.observers.inotify_c import (
Inotify,
WATCHDOG_ALL_EVENTS
)

logger = logging.getLogger(__name__)

Expand All @@ -29,10 +32,10 @@ class InotifyBuffer(BaseThread):

delay = 0.5

def __init__(self, path, recursive=False):
def __init__(self, path, recursive=False, event_mask=WATCHDOG_ALL_EVENTS):
super().__init__()
self._queue = DelayedQueue(self.delay)
self._inotify = Inotify(path, recursive)
self._inotify = Inotify(path, recursive, event_mask)
self.start()

def read_event(self):
Expand Down
11 changes: 6 additions & 5 deletions tests/test_emitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
FileClosedEvent,
)
from watchdog.observers.api import ObservedWatch
from watchdog.observers.inotify_c import WATCHDOG_ALL_EVENTS, InotifyConstants

if platform.is_linux():
from watchdog.observers.inotify import (
Expand All @@ -56,7 +57,6 @@
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)


if platform.is_darwin():
# enable more verbose logs
fsevents_logger = logging.getLogger("fsevents")
Expand All @@ -76,14 +76,15 @@ def setup_teardown(tmpdir):
assert not emitter.is_alive()


def start_watching(path=None, use_full_emitter=False, recursive=True):
def start_watching(path=None, use_full_emitter=False, recursive=True, event_mask=WATCHDOG_ALL_EVENTS):
# todo: check if other platforms expect the trailing slash (e.g. `p('')`)
path = p() if path is None else path
global emitter
if platform.is_linux() and use_full_emitter:
emitter = InotifyFullEmitter(event_queue, ObservedWatch(path, recursive=recursive))
emitter = InotifyFullEmitter(event_queue,
ObservedWatch(path, recursive=recursive, event_mask=event_mask))
else:
emitter = Emitter(event_queue, ObservedWatch(path, recursive=recursive))
emitter = Emitter(event_queue, ObservedWatch(path, recursive=recursive, event_mask=event_mask))

if platform.is_darwin():
emitter.suppress_history = True
Expand Down Expand Up @@ -676,4 +677,4 @@ def test_file_lifecyle():
expect_event(FileDeletedEvent(p('b')))

if not platform.is_windows():
expect_event(DirModifiedEvent(p()))
expect_event(DirModifiedEvent(p()))
12 changes: 7 additions & 5 deletions tests/test_fsevents.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from watchdog.observers import Observer
from watchdog.observers.api import ObservedWatch
from watchdog.observers.fsevents import FSEventsEmitter
from watchdog.observers.inotify_c import WATCHDOG_ALL_EVENTS

from .shell import mkdtemp, rm, touch

Expand All @@ -46,10 +47,11 @@ def teardown_function(function):
rm(p(""), recursive=True)


def start_watching(path=None, recursive=True, use_full_emitter=False):
def start_watching(path=None, recursive=True, use_full_emitter=False, event_mask=WATCHDOG_ALL_EVENTS):
global emitter
path = p("") if path is None else path
emitter = FSEventsEmitter(event_queue, ObservedWatch(path, recursive=recursive), suppress_history=True)
emitter = FSEventsEmitter(event_queue, ObservedWatch(path, recursive=recursive, event_mask=event_mask),
suppress_history=True)
emitter.start()


Expand Down Expand Up @@ -92,7 +94,7 @@ def test_add_watch_twice(observer):
a = p("a")
mkdir(a)
h = FileSystemEventHandler()
w = ObservedWatch(a, recursive=False)
w = ObservedWatch(a, recursive=False, event_mask=WATCHDOG_ALL_EVENTS)

def callback(path, inodes, flags, ids):
pass
Expand Down Expand Up @@ -225,7 +227,7 @@ def on_thread_stop(self):
"""
a = p("a")
mkdir(a)
w = observer.schedule(FileSystemEventHandler(), a, recursive=False)
w = observer.schedule(FileSystemEventHandler(), a, recursive=False, event_mask=WATCHDOG_ALL_EVENTS)
rmdir(a)
time.sleep(0.1)
observer.unschedule(w)
Expand Down Expand Up @@ -319,7 +321,7 @@ def on_any_event(self, event):
observer = Observer()

watches = []
watches.append(observer.schedule(handler, str(p('')), recursive=True))
watches.append(observer.schedule(handler, str(p('')), recursive=True, event_mask=WATCHDOG_ALL_EVENTS))

try:
observer.start()
Expand Down
4 changes: 2 additions & 2 deletions tests/test_inotify_c.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from watchdog.events import DirCreatedEvent, DirDeletedEvent, DirModifiedEvent
from watchdog.observers.api import ObservedWatch
from watchdog.observers.inotify import InotifyFullEmitter, InotifyEmitter
from watchdog.observers.inotify_c import Inotify, InotifyConstants, InotifyEvent
from watchdog.observers.inotify_c import Inotify, InotifyConstants, InotifyEvent, WATCHDOG_ALL_EVENTS

from .shell import mkdtemp, rm

Expand All @@ -38,7 +38,7 @@ 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 = Emitter(event_queue, ObservedWatch(path, recursive=True, event_mask=WATCHDOG_ALL_EVENTS))
emitter.start()
yield
emitter.stop()
Expand Down
Loading