From 0a3fd4065a45aacd294c8a2d48895d5ac3c6b7a1 Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Mon, 20 Dec 2021 00:58:41 +0100 Subject: [PATCH] Proper implementation for filesystem monitor filters The logic Watchdog applies to filter events based on `ignore_directories`, `ignore_patterns` and `ignore_regexes` isn't really sophisticated, and it doesn't check whether a partial directory/file name is used in one of the `ignore_*` patterns. The `file.monitor` backend should therefore implement this logic on its side. --- .../backend/file/monitor/entities/handlers.py | 43 +++++++++++++++++-- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/platypush/backend/file/monitor/entities/handlers.py b/platypush/backend/file/monitor/entities/handlers.py index 738bca56b..ef7930317 100644 --- a/platypush/backend/file/monitor/entities/handlers.py +++ b/platypush/backend/file/monitor/entities/handlers.py @@ -1,4 +1,5 @@ import os +import re from watchdog.events import FileSystemEventHandler, PatternMatchingEventHandler, RegexMatchingEventHandler @@ -16,14 +17,50 @@ class EventHandler(FileSystemEventHandler): resource.path = os.path.expanduser(resource.path) self.resource = resource + def _should_ignore_event(self, event) -> bool: + ignore_dirs = [ + os.path.expanduser( + _dir if os.path.expanduser(_dir).strip('/').startswith(self.resource.path) + else os.path.join(self.resource.path, _dir) + ) + for _dir in getattr(self.resource, 'ignore_directories', []) + ] + + ignore_patterns = getattr(self.resource, 'ignore_patterns', None) + ignore_regexes = getattr(self.resource, 'ignore_regexes', None) + + if ignore_dirs and any( + event.src_path.startswith(ignore_dir) for ignore_dir in ignore_dirs + ): + return True + + if ignore_patterns and any( + re.match(r'^{}$'.format(pattern.replace('*', '.*')), event.src_path) + for pattern in ignore_patterns + ): + return True + + if ignore_regexes and any( + re.match(regex, event.src_path) + for regex in ignore_patterns + ): + return True + + return False + + def _on_event(self, event, output_event_type): + if self._should_ignore_event(event): + return + get_bus().post(output_event_type(path=event.src_path, is_directory=event.is_directory)) + def on_created(self, event): - get_bus().post(FileSystemCreateEvent(path=event.src_path, is_directory=event.is_directory)) + self._on_event(event, FileSystemCreateEvent) def on_deleted(self, event): - get_bus().post(FileSystemDeleteEvent(path=event.src_path, is_directory=event.is_directory)) + self._on_event(event, FileSystemDeleteEvent) def on_modified(self, event): - get_bus().post(FileSystemModifyEvent(path=event.src_path, is_directory=event.is_directory)) + self._on_event(event, FileSystemModifyEvent) def on_moved(self, event): pass