1from __future__ import annotations
2
3from watchdog.events import (
4    EVENT_TYPE_CLOSED,
5    EVENT_TYPE_CLOSED_NO_WRITE,
6    EVENT_TYPE_CREATED,
7    EVENT_TYPE_DELETED,
8    EVENT_TYPE_MODIFIED,
9    EVENT_TYPE_MOVED,
10    EVENT_TYPE_OPENED,
11    DirCreatedEvent,
12    DirDeletedEvent,
13    DirModifiedEvent,
14    DirMovedEvent,
15    FileClosedEvent,
16    FileClosedNoWriteEvent,
17    FileCreatedEvent,
18    FileDeletedEvent,
19    FileModifiedEvent,
20    FileMovedEvent,
21    FileOpenedEvent,
22    FileSystemEventHandler,
23)
24
25path_1 = "/path/xyz"
26path_2 = "/path/abc"
27
28
29def test_file_deleted_event():
30    event = FileDeletedEvent(path_1)
31    assert path_1 == event.src_path
32    assert event.event_type == EVENT_TYPE_DELETED
33    assert not event.is_directory
34    assert not event.is_synthetic
35
36
37def test_file_delete_event_is_directory():
38    # Inherited properties.
39    event = FileDeletedEvent(path_1)
40    assert not event.is_directory
41    assert not event.is_synthetic
42
43
44def test_file_modified_event():
45    event = FileModifiedEvent(path_1)
46    assert path_1 == event.src_path
47    assert event.event_type == EVENT_TYPE_MODIFIED
48    assert not event.is_directory
49    assert not event.is_synthetic
50
51
52def test_file_modified_event_is_directory():
53    # Inherited Properties
54    event = FileModifiedEvent(path_1)
55    assert not event.is_directory
56    assert not event.is_synthetic
57
58
59def test_file_created_event():
60    event = FileCreatedEvent(path_1)
61    assert path_1 == event.src_path
62    assert event.event_type == EVENT_TYPE_CREATED
63    assert not event.is_directory
64    assert not event.is_synthetic
65
66
67def test_file_moved_event():
68    event = FileMovedEvent(path_1, path_2)
69    assert path_1 == event.src_path
70    assert path_2 == event.dest_path
71    assert event.event_type == EVENT_TYPE_MOVED
72    assert not event.is_directory
73    assert not event.is_synthetic
74
75
76def test_file_closed_event():
77    event = FileClosedEvent(path_1)
78    assert path_1 == event.src_path
79    assert event.event_type == EVENT_TYPE_CLOSED
80    assert not event.is_directory
81    assert not event.is_synthetic
82
83
84def test_file_closed_no_write_event():
85    event = FileClosedNoWriteEvent(path_1)
86    assert path_1 == event.src_path
87    assert event.event_type == EVENT_TYPE_CLOSED_NO_WRITE
88    assert not event.is_directory
89    assert not event.is_synthetic
90
91
92def test_file_opened_event():
93    event = FileOpenedEvent(path_1)
94    assert path_1 == event.src_path
95    assert event.event_type == EVENT_TYPE_OPENED
96    assert not event.is_directory
97    assert not event.is_synthetic
98
99
100def test_dir_deleted_event():
101    event = DirDeletedEvent(path_1)
102    assert path_1 == event.src_path
103    assert event.event_type == EVENT_TYPE_DELETED
104    assert event.is_directory
105    assert not event.is_synthetic
106
107
108def test_dir_modified_event():
109    event = DirModifiedEvent(path_1)
110    assert path_1 == event.src_path
111    assert event.event_type == EVENT_TYPE_MODIFIED
112    assert event.is_directory
113    assert not event.is_synthetic
114
115
116def test_dir_created_event():
117    event = DirCreatedEvent(path_1)
118    assert path_1 == event.src_path
119    assert event.event_type == EVENT_TYPE_CREATED
120    assert event.is_directory
121    assert not event.is_synthetic
122
123
124def test_file_system_event_handler_dispatch():
125    dir_del_event = DirDeletedEvent("/path/blah.py")
126    file_del_event = FileDeletedEvent("/path/blah.txt")
127    dir_cre_event = DirCreatedEvent("/path/blah.py")
128    file_cre_event = FileCreatedEvent("/path/blah.txt")
129    file_cls_event = FileClosedEvent("/path/blah.txt")
130    file_cls_nw_event = FileClosedNoWriteEvent("/path/blah.txt")
131    file_opened_event = FileOpenedEvent("/path/blah.txt")
132    dir_mod_event = DirModifiedEvent("/path/blah.py")
133    file_mod_event = FileModifiedEvent("/path/blah.txt")
134    dir_mov_event = DirMovedEvent("/path/blah.py", "/path/blah")
135    file_mov_event = FileMovedEvent("/path/blah.txt", "/path/blah")
136
137    all_events = [
138        dir_mod_event,
139        dir_del_event,
140        dir_cre_event,
141        dir_mov_event,
142        file_mod_event,
143        file_del_event,
144        file_cre_event,
145        file_mov_event,
146        file_cls_event,
147        file_cls_nw_event,
148        file_opened_event,
149    ]
150
151    checkpoint = 0
152
153    class TestableEventHandler(FileSystemEventHandler):
154        def on_any_event(self, event):
155            nonlocal checkpoint
156            checkpoint += 1
157
158        def on_modified(self, event):
159            nonlocal checkpoint
160            checkpoint += 1
161            assert event.event_type == EVENT_TYPE_MODIFIED
162
163        def on_deleted(self, event):
164            nonlocal checkpoint
165            checkpoint += 1
166            assert event.event_type == EVENT_TYPE_DELETED
167
168        def on_moved(self, event):
169            nonlocal checkpoint
170            checkpoint += 1
171            assert event.event_type == EVENT_TYPE_MOVED
172
173        def on_created(self, event):
174            nonlocal checkpoint
175            checkpoint += 1
176            assert event.event_type == EVENT_TYPE_CREATED
177
178        def on_closed(self, event):
179            nonlocal checkpoint
180            checkpoint += 1
181            assert event.event_type == EVENT_TYPE_CLOSED
182
183        def on_closed_no_write(self, event):
184            nonlocal checkpoint
185            checkpoint += 1
186            assert event.event_type == EVENT_TYPE_CLOSED_NO_WRITE
187
188        def on_opened(self, event):
189            nonlocal checkpoint
190            checkpoint += 1
191            assert event.event_type == EVENT_TYPE_OPENED
192
193    handler = TestableEventHandler()
194
195    for event in all_events:
196        assert not event.is_synthetic
197        handler.dispatch(event)
198
199    assert checkpoint == len(all_events) * 2  # `on_any_event()` + specific `on_XXX()`
200
201
202def test_event_comparison():
203    creation1 = FileCreatedEvent("foo")
204    creation2 = FileCreatedEvent("foo")
205    creation3 = FileCreatedEvent("bar")
206    assert creation1 == creation2
207    assert creation1 != creation3
208    assert creation2 != creation3
209
210    move1 = FileMovedEvent("a", "b")
211    move2 = FileMovedEvent("a", "b")
212    move3 = FileMovedEvent("a", "c")
213    move4 = FileMovedEvent("b", "a")
214    assert creation1 != move1  # type: ignore[comparison-overlap]
215    assert move1 == move2
216    assert move1 != move3
217    assert move1 != move4
218    assert move2 != move3
219    assert move2 != move4
220    assert move3 != move4
221