Skip to content

Commit

Permalink
Use absolute watch path in recursive check
Browse files Browse the repository at this point in the history
A watch path may be relative, while an event path is always absolute. Since the check for recursive events simply compared the watch path with the event path then that would fail in case the watch was set to a relative folder. This resolves the issue.

Fixes gorakhargosh#797
  • Loading branch information
CCP-Aporia committed May 18, 2021
1 parent a7aa848 commit c7b0d22
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 9 deletions.
5 changes: 3 additions & 2 deletions src/watchdog/observers/fsevents.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ def __init__(self, event_queue, watch, timeout=DEFAULT_EMITTER_TIMEOUT, suppress
self._start_time = 0.0
self._starting_state = None
self._lock = threading.Lock()
self._absolute_watch_path = os.path.abspath(self.watch.path)

def on_thread_stop(self):
_fsevents.remove_watch(self.watch)
Expand All @@ -104,14 +105,14 @@ def queue_event(self, event):

def _is_recursive_event(self, event):
src_path = event.src_path if event.is_directory else os.path.dirname(event.src_path)
if src_path == self._watch.path:
if src_path == self._absolute_watch_path:
return False

if isinstance(event, (FileMovedEvent, DirMovedEvent)):
# when moving something into the watch path we must always take the dirname,
# otherwise we miss out on `DirMovedEvent`s
dest_path = os.path.dirname(event.dest_path)
if dest_path == self._watch.path:
if dest_path == self._absolute_watch_path:
return False

return True
Expand Down
20 changes: 13 additions & 7 deletions tests/test_fsevents.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,37 +247,42 @@ def test_converting_cfstring_to_pyunicode():
emitter.stop()


def test_issue_797():
def test_recursive_check_accepts_relative_paths():
"""See https://github.com/gorakhargosh/watchdog/issues/797
The test code provided in the defect observes the current working directory
using ".". Since the watch path wasn't normalized then that failed.
This test emulates the scenario.
"""
from watchdog.events import (
PatternMatchingEventHandler,
DirCreatedEvent,
DirModifiedEvent,
FileCreatedEvent,
FileModifiedEvent
)

class TestEventHandler(PatternMatchingEventHandler):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# the TestEventHandler instance is set to ignore_directories,
# as such we won't get a DirModifiedEvent(p()) here.
self.expected_events = [
FileCreatedEvent(p('foo.json')),
FileModifiedEvent(p('foo.json'))
]
self.observed_events = set()

def on_any_event(self, event):
logger.info(event)
self.expected_events.remove(event)
self.observed_events.add(event)
# expected_event = self.expected_events.pop(0)
# assert expected_event == event

def done(self):
return not self.expected_events

cwd = os.getcwd()
os.chdir(p())
event_handler = TestEventHandler(patterns=["*.json"], ignore_patterns=[], ignore_directories=True)
observer = Observer()
observer.schedule(event_handler, p())
observer.schedule(event_handler, ".")
observer.start()
time.sleep(0.1)

Expand All @@ -289,6 +294,7 @@ def done(self):

assert event_handler.done()
finally:
os.chdir(cwd)
observer.stop()
observer.join()

Expand Down

0 comments on commit c7b0d22

Please sign in to comment.