Skip to content

Commit 350ec37

Browse files
committed
Inotify's symlink follow with recursive option
* Using symlink follow now working as intended with recursive (used to be shallow only) * Add test for recursive + follow symlink for Inotify observer * Improve test for recursive cases : in case of recursive Inotify directory open event always triggers
1 parent 9df81ab commit 350ec37

File tree

2 files changed

+26
-3
lines changed

2 files changed

+26
-3
lines changed

src/watchdog/observers/inotify_c.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ def _add_dir_watch(self, path: bytes, mask: int, *, recursive: bool) -> None:
408408
raise OSError(errno.ENOTDIR, os.strerror(errno.ENOTDIR), path)
409409
self._add_watch(path, mask)
410410
if recursive:
411-
for root, dirnames, _ in os.walk(path):
411+
for root, dirnames, _ in os.walk(path, followlinks=self._follow_symlink):
412412
for dirname in dirnames:
413413
full_path = os.path.join(root, dirname)
414414
if not self._follow_symlink and os.path.islink(full_path):

tests/test_inotify_buffer.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
import random
1212
import time
1313

14-
from watchdog.observers.inotify_buffer import InotifyBuffer
14+
from watchdog.observers.inotify_c import InotifyConstants
15+
from watchdog.observers.inotify_buffer import InotifyBuffer, InotifyEvent
1516

1617
from .shell import mkdir, mount_tmpfs, mv, rm, symlink, touch, unmount
1718

@@ -126,7 +127,29 @@ def test_delete_watched_directory_symlink_followed(p):
126127
rm(p("dir", "dir2"), recursive=True)
127128

128129
# Wait for the event to be picked up
129-
inotify.read_event()
130+
event = inotify.read_event()
131+
while not isinstance(event, InotifyEvent) or (
132+
event.mask != (InotifyConstants.IN_DELETE | InotifyConstants.IN_ISDIR)):
133+
event = inotify.read_event()
134+
135+
# Ensure InotifyBuffer shuts down cleanly without raising an exception
136+
inotify.close()
137+
138+
139+
@pytest.mark.timeout(5)
140+
def test_delete_watched_directory_symlink_followed_recursive(p):
141+
mkdir(p("dir"), parents=True)
142+
mkdir(p("dir2", "dir3", "dir4"), parents=True)
143+
symlink(p("dir2"), p("dir", "symdir"), target_is_directory=True)
144+
145+
inotify = InotifyBuffer(p("dir").encode(), follow_symlink=True, recursive=True)
146+
rm(p("dir2", "dir3", "dir4"), recursive=True)
147+
148+
# Wait for the event to be picked up
149+
event = inotify.read_event()
150+
while not isinstance(event, InotifyEvent) or (
151+
event.mask != (InotifyConstants.IN_DELETE | InotifyConstants.IN_ISDIR)):
152+
event = inotify.read_event()
130153

131154
# Ensure InotifyBuffer shuts down cleanly without raising an exception
132155
inotify.close()

0 commit comments

Comments
 (0)