1from __future__ import annotations 2 3from watchdog.events import ( 4 EVENT_TYPE_CREATED, 5 EVENT_TYPE_DELETED, 6 EVENT_TYPE_MODIFIED, 7 EVENT_TYPE_MOVED, 8 DirCreatedEvent, 9 DirDeletedEvent, 10 DirModifiedEvent, 11 DirMovedEvent, 12 FileCreatedEvent, 13 FileDeletedEvent, 14 FileModifiedEvent, 15 FileMovedEvent, 16 LoggingEventHandler, 17 RegexMatchingEventHandler, 18) 19 20path_1 = "/path/xyz" 21path_2 = "/path/abc" 22g_allowed_regexes = [r".*\.py", r".*\.txt"] 23g_allowed_str_regexes = r".*\.py" 24g_ignore_regexes = [r".*\.pyc"] 25 26 27def test_dispatch(): 28 # Utilities. 29 regexes = [r".*\.py", r".*\.txt"] 30 ignore_regexes = [r".*\.pyc"] 31 32 def assert_regexes(handler, event): 33 paths = [event.src_path, event.dest_path] if hasattr(event, "dest_path") else [event.src_path] 34 filtered_paths = set() 35 for p in paths: 36 if any(r.match(p) for r in handler.regexes): 37 filtered_paths.add(p) 38 assert filtered_paths 39 40 dir_del_event_match = DirDeletedEvent("/path/blah.py") 41 dir_del_event_not_match = DirDeletedEvent("/path/foobar") 42 dir_del_event_ignored = DirDeletedEvent("/path/foobar.pyc") 43 file_del_event_match = FileDeletedEvent("/path/blah.txt") 44 file_del_event_not_match = FileDeletedEvent("/path/foobar") 45 file_del_event_ignored = FileDeletedEvent("/path/blah.pyc") 46 47 dir_cre_event_match = DirCreatedEvent("/path/blah.py") 48 dir_cre_event_not_match = DirCreatedEvent("/path/foobar") 49 dir_cre_event_ignored = DirCreatedEvent("/path/foobar.pyc") 50 file_cre_event_match = FileCreatedEvent("/path/blah.txt") 51 file_cre_event_not_match = FileCreatedEvent("/path/foobar") 52 file_cre_event_ignored = FileCreatedEvent("/path/blah.pyc") 53 54 dir_mod_event_match = DirModifiedEvent("/path/blah.py") 55 dir_mod_event_not_match = DirModifiedEvent("/path/foobar") 56 dir_mod_event_ignored = DirModifiedEvent("/path/foobar.pyc") 57 file_mod_event_match = FileModifiedEvent("/path/blah.txt") 58 file_mod_event_not_match = FileModifiedEvent("/path/foobar") 59 file_mod_event_ignored = FileModifiedEvent("/path/blah.pyc") 60 61 dir_mov_event_match = DirMovedEvent("/path/blah.py", "/path/blah") 62 dir_mov_event_not_match = DirMovedEvent("/path/foobar", "/path/blah") 63 dir_mov_event_ignored = DirMovedEvent("/path/foobar.pyc", "/path/blah") 64 file_mov_event_match = FileMovedEvent("/path/blah.txt", "/path/blah") 65 file_mov_event_not_match = FileMovedEvent("/path/foobar", "/path/blah") 66 file_mov_event_ignored = FileMovedEvent("/path/blah.pyc", "/path/blah") 67 68 all_dir_events = [ 69 dir_mod_event_match, 70 dir_mod_event_not_match, 71 dir_mod_event_ignored, 72 dir_del_event_match, 73 dir_del_event_not_match, 74 dir_del_event_ignored, 75 dir_cre_event_match, 76 dir_cre_event_not_match, 77 dir_cre_event_ignored, 78 dir_mov_event_match, 79 dir_mov_event_not_match, 80 dir_mov_event_ignored, 81 ] 82 all_file_events = [ 83 file_mod_event_match, 84 file_mod_event_not_match, 85 file_mod_event_ignored, 86 file_del_event_match, 87 file_del_event_not_match, 88 file_del_event_ignored, 89 file_cre_event_match, 90 file_cre_event_not_match, 91 file_cre_event_ignored, 92 file_mov_event_match, 93 file_mov_event_not_match, 94 file_mov_event_ignored, 95 ] 96 all_events = all_file_events + all_dir_events 97 98 def assert_check_directory(handler, event): 99 assert not (handler.ignore_directories and event.is_directory) 100 101 class TestableEventHandler(RegexMatchingEventHandler): 102 def on_any_event(self, event): 103 assert_check_directory(self, event) 104 105 def on_modified(self, event): 106 assert_check_directory(self, event) 107 assert event.event_type == EVENT_TYPE_MODIFIED 108 assert_regexes(self, event) 109 110 def on_deleted(self, event): 111 assert_check_directory(self, event) 112 assert event.event_type == EVENT_TYPE_DELETED 113 assert_regexes(self, event) 114 115 def on_moved(self, event): 116 assert_check_directory(self, event) 117 assert event.event_type == EVENT_TYPE_MOVED 118 assert_regexes(self, event) 119 120 def on_created(self, event): 121 assert_check_directory(self, event) 122 assert event.event_type == EVENT_TYPE_CREATED 123 assert_regexes(self, event) 124 125 no_dirs_handler = TestableEventHandler(regexes=regexes, ignore_regexes=ignore_regexes, ignore_directories=True) 126 handler = TestableEventHandler(regexes=regexes, ignore_regexes=ignore_regexes) 127 128 for event in all_events: 129 no_dirs_handler.dispatch(event) 130 for event in all_events: 131 handler.dispatch(event) 132 133 134def test_handler(): 135 handler1 = RegexMatchingEventHandler( 136 regexes=g_allowed_regexes, 137 ignore_regexes=g_ignore_regexes, 138 ignore_directories=True, 139 ) 140 handler2 = RegexMatchingEventHandler(regexes=g_allowed_regexes, ignore_regexes=g_ignore_regexes) 141 assert [r.pattern for r in handler1.regexes] == g_allowed_regexes 142 assert [r.pattern for r in handler1.ignore_regexes] == g_ignore_regexes 143 assert handler1.ignore_directories 144 assert not handler2.ignore_directories 145 146 147def test_ignore_directories(): 148 handler1 = RegexMatchingEventHandler( 149 regexes=g_allowed_regexes, 150 ignore_regexes=g_ignore_regexes, 151 ignore_directories=True, 152 ) 153 handler2 = RegexMatchingEventHandler(regexes=g_allowed_regexes, ignore_regexes=g_ignore_regexes) 154 assert handler1.ignore_directories 155 assert not handler2.ignore_directories 156 157 158def test_ignore_regexes(): 159 handler1 = RegexMatchingEventHandler( 160 regexes=g_allowed_regexes, 161 ignore_regexes=g_ignore_regexes, 162 ignore_directories=True, 163 ) 164 assert [r.pattern for r in handler1.ignore_regexes] == g_ignore_regexes 165 166 167def test_regexes(): 168 handler1 = RegexMatchingEventHandler( 169 regexes=g_allowed_regexes, 170 ignore_regexes=g_ignore_regexes, 171 ignore_directories=True, 172 ) 173 assert [r.pattern for r in handler1.regexes] == g_allowed_regexes 174 175 176def test_str_regexes(): 177 handler1 = RegexMatchingEventHandler( 178 regexes=g_allowed_str_regexes, 179 ignore_regexes=g_ignore_regexes, 180 case_sensitive=True, 181 ) 182 assert [r.pattern for r in handler1.regexes] == [g_allowed_str_regexes] 183 184 185def test_logging_event_handler_dispatch(): 186 class _TestableEventHandler(LoggingEventHandler): 187 def on_any_event(self, event): 188 pass 189 190 def on_modified(self, event): 191 super().on_modified(event) 192 assert event.event_type == EVENT_TYPE_MODIFIED 193 194 def on_deleted(self, event): 195 super().on_deleted(event) 196 assert event.event_type == EVENT_TYPE_DELETED 197 198 def on_moved(self, event): 199 super().on_moved(event) 200 assert event.event_type == EVENT_TYPE_MOVED 201 202 def on_created(self, event): 203 super().on_created(event) 204 assert event.event_type == EVENT_TYPE_CREATED 205 206 # Utilities. 207 dir_del_event = DirDeletedEvent("/path/blah.py") 208 file_del_event = FileDeletedEvent("/path/blah.txt") 209 dir_cre_event = DirCreatedEvent("/path/blah.py") 210 file_cre_event = FileCreatedEvent("/path/blah.txt") 211 dir_mod_event = DirModifiedEvent("/path/blah.py") 212 file_mod_event = FileModifiedEvent("/path/blah.txt") 213 dir_mov_event = DirMovedEvent("/path/blah.py", "/path/blah") 214 file_mov_event = FileMovedEvent("/path/blah.txt", "/path/blah") 215 216 all_events = [ 217 dir_mod_event, 218 dir_del_event, 219 dir_cre_event, 220 dir_mov_event, 221 file_mod_event, 222 file_del_event, 223 file_cre_event, 224 file_mov_event, 225 ] 226 227 handler = _TestableEventHandler() 228 for event in all_events: 229 handler.dispatch(event) 230