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    PatternMatchingEventHandler,
17)
18from watchdog.utils.patterns import filter_paths
19
20path_1 = "/path/xyz"
21path_2 = "/path/abc"
22g_allowed_patterns = ["*.py", "*.txt"]
23g_ignore_patterns = ["*.foo"]
24
25
26def assert_patterns(event):
27    paths = [event.src_path, event.dest_path] if hasattr(event, "dest_path") else [event.src_path]
28    filtered_paths = filter_paths(
29        paths,
30        included_patterns=["*.py", "*.txt"],
31        excluded_patterns=["*.pyc"],
32        case_sensitive=False,
33    )
34    assert filtered_paths
35
36
37def test_dispatch():
38    # Utilities.
39    patterns = ["*.py", "*.txt"]
40    ignore_patterns = ["*.pyc"]
41
42    dir_del_event_match = DirDeletedEvent("/path/blah.py")
43    dir_del_event_not_match = DirDeletedEvent("/path/foobar")
44    dir_del_event_ignored = DirDeletedEvent("/path/foobar.pyc")
45    file_del_event_match = FileDeletedEvent("/path/blah.txt")
46    file_del_event_not_match = FileDeletedEvent("/path/foobar")
47    file_del_event_ignored = FileDeletedEvent("/path/blah.pyc")
48
49    dir_cre_event_match = DirCreatedEvent("/path/blah.py")
50    dir_cre_event_not_match = DirCreatedEvent("/path/foobar")
51    dir_cre_event_ignored = DirCreatedEvent("/path/foobar.pyc")
52    file_cre_event_match = FileCreatedEvent("/path/blah.txt")
53    file_cre_event_not_match = FileCreatedEvent("/path/foobar")
54    file_cre_event_ignored = FileCreatedEvent("/path/blah.pyc")
55
56    dir_mod_event_match = DirModifiedEvent("/path/blah.py")
57    dir_mod_event_not_match = DirModifiedEvent("/path/foobar")
58    dir_mod_event_ignored = DirModifiedEvent("/path/foobar.pyc")
59    file_mod_event_match = FileModifiedEvent("/path/blah.txt")
60    file_mod_event_not_match = FileModifiedEvent("/path/foobar")
61    file_mod_event_ignored = FileModifiedEvent("/path/blah.pyc")
62
63    dir_mov_event_match = DirMovedEvent("/path/blah.py", "/path/blah")
64    dir_mov_event_not_match = DirMovedEvent("/path/foobar", "/path/blah")
65    dir_mov_event_ignored = DirMovedEvent("/path/foobar.pyc", "/path/blah")
66    file_mov_event_match = FileMovedEvent("/path/blah.txt", "/path/blah")
67    file_mov_event_not_match = FileMovedEvent("/path/foobar", "/path/blah")
68    file_mov_event_ignored = FileMovedEvent("/path/blah.pyc", "/path/blah")
69
70    all_dir_events = [
71        dir_mod_event_match,
72        dir_mod_event_not_match,
73        dir_mod_event_ignored,
74        dir_del_event_match,
75        dir_del_event_not_match,
76        dir_del_event_ignored,
77        dir_cre_event_match,
78        dir_cre_event_not_match,
79        dir_cre_event_ignored,
80        dir_mov_event_match,
81        dir_mov_event_not_match,
82        dir_mov_event_ignored,
83    ]
84    all_file_events = [
85        file_mod_event_match,
86        file_mod_event_not_match,
87        file_mod_event_ignored,
88        file_del_event_match,
89        file_del_event_not_match,
90        file_del_event_ignored,
91        file_cre_event_match,
92        file_cre_event_not_match,
93        file_cre_event_ignored,
94        file_mov_event_match,
95        file_mov_event_not_match,
96        file_mov_event_ignored,
97    ]
98    all_events = all_file_events + all_dir_events
99
100    def assert_check_directory(handler, event):
101        assert not (handler.ignore_directories and event.is_directory)
102
103    class TestableEventHandler(PatternMatchingEventHandler):
104        def on_any_event(self, event):
105            assert_check_directory(self, event)
106
107        def on_modified(self, event):
108            assert_check_directory(self, event)
109            assert event.event_type == EVENT_TYPE_MODIFIED
110            assert_patterns(event)
111
112        def on_deleted(self, event):
113            assert_check_directory(self, event)
114            assert event.event_type == EVENT_TYPE_DELETED
115            assert_patterns(event)
116
117        def on_moved(self, event):
118            assert_check_directory(self, event)
119            assert event.event_type == EVENT_TYPE_MOVED
120            assert_patterns(event)
121
122        def on_created(self, event):
123            assert_check_directory(self, event)
124            assert event.event_type == EVENT_TYPE_CREATED
125            assert_patterns(event)
126
127    no_dirs_handler = TestableEventHandler(patterns=patterns, ignore_patterns=ignore_patterns, ignore_directories=True)
128    handler = TestableEventHandler(patterns=patterns, ignore_patterns=ignore_patterns)
129
130    for event in all_events:
131        no_dirs_handler.dispatch(event)
132    for event in all_events:
133        handler.dispatch(event)
134
135
136def test_handler():
137    handler1 = PatternMatchingEventHandler(
138        patterns=g_allowed_patterns,
139        ignore_patterns=g_ignore_patterns,
140        ignore_directories=True,
141    )
142    handler2 = PatternMatchingEventHandler(patterns=g_allowed_patterns, ignore_patterns=g_ignore_patterns)
143    assert handler1.patterns == g_allowed_patterns
144    assert handler1.ignore_patterns == g_ignore_patterns
145    assert handler1.ignore_directories
146    assert not handler2.ignore_directories
147
148
149def test_ignore_directories():
150    handler1 = PatternMatchingEventHandler(
151        patterns=g_allowed_patterns,
152        ignore_patterns=g_ignore_patterns,
153        ignore_directories=True,
154    )
155    handler2 = PatternMatchingEventHandler(patterns=g_allowed_patterns, ignore_patterns=g_ignore_patterns)
156    assert handler1.ignore_directories
157    assert not handler2.ignore_directories
158
159
160def test_ignore_patterns():
161    handler1 = PatternMatchingEventHandler(
162        patterns=g_allowed_patterns,
163        ignore_patterns=g_ignore_patterns,
164        ignore_directories=True,
165    )
166    assert handler1.ignore_patterns == g_ignore_patterns
167
168
169def test_patterns():
170    handler1 = PatternMatchingEventHandler(
171        patterns=g_allowed_patterns,
172        ignore_patterns=g_ignore_patterns,
173        ignore_directories=True,
174    )
175    assert handler1.patterns == g_allowed_patterns
176