Merge lp:~mandel/ubuntuone-client/fix-rm-path into lp:ubuntuone-client
- fix-rm-path
- Merge into trunk
Proposed by
Manuel de la Peña
Status: | Merged |
---|---|
Approved by: | Natalia Bidart |
Approved revision: | 1107 |
Merged at revision: | 1078 |
Proposed branch: | lp:~mandel/ubuntuone-client/fix-rm-path |
Merge into: | lp:ubuntuone-client |
Prerequisite: | lp:~mandel/ubuntuone-client/remove_watcher_q |
Diff against target: |
381 lines (+188/-49) 2 files modified
tests/platform/windows/test_filesystem_notifications.py (+150/-18) ubuntuone/platform/windows/filesystem_notifications.py (+38/-31) |
To merge this branch: | bzr merge lp:~mandel/ubuntuone-client/fix-rm-path |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Natalia Bidart (community) | Approve | ||
Guillermo Gonzalez | Approve | ||
Review via email:
|
Commit message
Improved the implementation of the rm_path method so that it is simpler.
Description of the change
Improved the implementation of the rm_path method so that it is simpler.
To post a comment you must log in.
- 1102. By Manuel de la Peña
-
Merged remove_watcher_q into fix-rm-path.
- 1103. By Manuel de la Peña
-
Merged remove_watcher_q into fix-rm-path.
- 1104. By Manuel de la Peña
-
Merged with previous branch.
- 1105. By Manuel de la Peña
-
Merged remove_watcher_q into fix-rm-path.
- 1106. By Manuel de la Peña
-
Merged remove_watcher_q into fix-rm-path.
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Natalia Bidart (nataliabidart) wrote : | # |
Typo: test_undo_
Remove the "" from: self.log.
review:
Needs Fixing
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Natalia Bidart (nataliabidart) wrote : | # |
Also:
./tests/
632: local variable 'exclude_filter' is assigned to but never used
review:
Needs Fixing
- 1107. By Manuel de la Peña
-
Fixed some small typos and removed an unused var.
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Natalia Bidart (nataliabidart) wrote : | # |
All Clear!
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'tests/platform/windows/test_filesystem_notifications.py' |
2 | --- tests/platform/windows/test_filesystem_notifications.py 2011-07-28 20:13:00 +0000 |
3 | +++ tests/platform/windows/test_filesystem_notifications.py 2011-07-29 13:35:16 +0000 |
4 | @@ -448,13 +448,129 @@ |
5 | self.assertEqual(0, len(events)) |
6 | test_open_dir_muted.skip = "we must rethink this test." |
7 | |
8 | - |
9 | -class FakeEvent(): |
10 | - """A fake event.""" |
11 | - |
12 | - def __init__(self, path): |
13 | - """Create an event with the given path.""" |
14 | - self.pathname = path |
15 | + def test_ignore_path(self): |
16 | + """Test that events from a path are ignored.""" |
17 | + events = [] |
18 | + |
19 | + def fake_processor(event): |
20 | + """Memorize the processed events.""" |
21 | + events.append(event) |
22 | + |
23 | + path = u'\\\\?\\C:\\path' # a valid windows path |
24 | + child = u'child' |
25 | + watch = Watch(1, path, None, True, fake_processor) |
26 | + watch.ignore_path(os.path.join(path, child)) |
27 | + paths_to_ignore = [] |
28 | + for file_name in 'abcdef': |
29 | + paths_to_ignore.append((1, os.path.join(child, file_name))) |
30 | + # ensure that the watch is watching |
31 | + watch._watching = True |
32 | + watch._process_events(paths_to_ignore) |
33 | + self.assertEqual(0, len(events), |
34 | + 'All events should have been ignored.') |
35 | + |
36 | + def test_not_ignore_path(self): |
37 | + """Test that we do get the events when they do not match.""" |
38 | + events = [] |
39 | + |
40 | + def fake_processor(event): |
41 | + """Memorize the processed events.""" |
42 | + events.append(event) |
43 | + |
44 | + path = u'\\\\?\\C:\\path' # a valid windows path |
45 | + child = u'child' |
46 | + watch = Watch(1, path, None, True, fake_processor) |
47 | + watch.ignore_path(os.path.join(path, child)) |
48 | + paths_not_to_ignore = [] |
49 | + for file_name in 'abcdef': |
50 | + paths_not_to_ignore.append((1, os.path.join( |
51 | + child + file_name, file_name))) |
52 | + # ensure that the watch is watching |
53 | + watch._watching = True |
54 | + watch._process_events(paths_not_to_ignore) |
55 | + self.assertEqual(len(paths_not_to_ignore), len(events), |
56 | + 'No events should have been ignored.') |
57 | + |
58 | + def test_mixed_ignore_path(self): |
59 | + """Test that we do get the correct events.""" |
60 | + events = [] |
61 | + |
62 | + def fake_processor(event): |
63 | + """Memorize the processed events.""" |
64 | + events.append(event.pathname) |
65 | + |
66 | + child = u'child' |
67 | + path = u'\\\\?\\C:\\path\\' # a valid windows path |
68 | + watch = Watch(1, path, None, True, fake_processor) |
69 | + watch.ignore_path(os.path.join(path, child)) |
70 | + paths_not_to_ignore = [] |
71 | + paths_to_ignore = [] |
72 | + expected_events = [] |
73 | + for file_name in 'abcdef': |
74 | + valid = os.path.join(child + file_name, file_name) |
75 | + paths_to_ignore.append((1, os.path.join(child, file_name))) |
76 | + paths_not_to_ignore.append((1, valid)) |
77 | + expected_events.append(os.path.join('C:\\path', valid)) |
78 | + # ensure that the watch is watching |
79 | + watch._watching = True |
80 | + watch._process_events(paths_not_to_ignore) |
81 | + self.assertEqual(len(paths_not_to_ignore), len(events), |
82 | + 'Wrong number of events ignored.') |
83 | + self.assertTrue(all([event in expected_events for event in events]), |
84 | + 'Paths ignored that should have not been ignored.') |
85 | + |
86 | + def test_undo_ignore_path_ignored(self): |
87 | + """Test that we do deal with events from and old ignored path.""" |
88 | + events = [] |
89 | + |
90 | + def fake_processor(event): |
91 | + """Memorize the processed events.""" |
92 | + events.append(event) |
93 | + |
94 | + path = u'\\\\?\\C:\\path' # a valid windows path |
95 | + child = u'child' |
96 | + watch = Watch(1, path, None, True, fake_processor) |
97 | + watch.ignore_path(os.path.join(path, child)) |
98 | + watch.remove_ignored_path(os.path.join(path, child)) |
99 | + paths_not_to_ignore = [] |
100 | + for file_name in 'abcdef': |
101 | + paths_not_to_ignore.append((1, os.path.join(child, file_name))) |
102 | + # ensure that the watch is watching |
103 | + watch._watching = True |
104 | + watch._process_events(paths_not_to_ignore) |
105 | + self.assertEqual(len(paths_not_to_ignore), len(events), |
106 | + 'All events should have been accepted.') |
107 | + |
108 | + def test_undo_ignore_path_other_ignored(self): |
109 | + """Test that we can undo and the other path is ignored.""" |
110 | + events = [] |
111 | + |
112 | + def fake_processor(event): |
113 | + """Memorize the processed events.""" |
114 | + events.append(event.pathname) |
115 | + |
116 | + path = u'\\\\?\\C:\\path' # a valid windows path |
117 | + child_a = u'childa' |
118 | + child_b = u'childb' |
119 | + watch = Watch(1, path, None, True, fake_processor) |
120 | + watch.ignore_path(os.path.join(path, child_a)) |
121 | + watch.ignore_path(os.path.join(path, child_b)) |
122 | + watch.remove_ignored_path(os.path.join(path, child_a)) |
123 | + paths_to_ignore = [] |
124 | + paths_not_to_ignore = [] |
125 | + expected_events = [] |
126 | + for file_name in 'abcdef': |
127 | + paths_to_ignore.append((1, os.path.join(child_b, file_name))) |
128 | + valid = os.path.join(child_a, file_name) |
129 | + paths_not_to_ignore.append((1, valid)) |
130 | + expected_events.append(os.path.join('C:\\path', valid)) |
131 | + # ensure that the watch is watching |
132 | + watch._watching = True |
133 | + watch._process_events(paths_not_to_ignore) |
134 | + self.assertEqual(len(paths_not_to_ignore), len(events), |
135 | + 'All events should have been accepted.') |
136 | + self.assertTrue(all([event in expected_events for event in events]), |
137 | + 'Paths ignored that should have not been ignored.') |
138 | |
139 | |
140 | class TestWatchManager(BaseTwistedTestCase): |
141 | @@ -513,15 +629,12 @@ |
142 | |
143 | mask = 'bit_mask' |
144 | auto_add = True |
145 | - exclude_filter = lambda x: False |
146 | - self.manager.add_watch(self.path, mask, auto_add=auto_add, |
147 | - exclude_filter=exclude_filter) |
148 | + self.manager.add_watch(self.path, mask, auto_add=auto_add) |
149 | self.assertEqual(1, len(self.manager._wdm)) |
150 | self.assertTrue(self.was_called, 'The watch start was not called.') |
151 | - self.assertEqual(self.path, self.manager._wdm[0]._path) |
152 | + self.assertEqual(self.path + os.path.sep, self.manager._wdm[0]._path) |
153 | self.assertEqual(mask, self.manager._wdm[0]._mask) |
154 | self.assertEqual(auto_add, self.manager._wdm[0]._auto_add) |
155 | - self.assertEqual(exclude_filter, self.manager._wdm[0].exclude_filter) |
156 | |
157 | def test_update_present_watch(self): |
158 | """Test the update of a present watch.""" |
159 | @@ -531,7 +644,7 @@ |
160 | |
161 | def test_get_watch_present_wd(self): |
162 | """Test that the correct path is returned.""" |
163 | - self.assertEqual(self.path, self.manager.get_path(1)) |
164 | + self.assertEqual(self.path + os.path.sep, self.manager.get_path(1)) |
165 | |
166 | def test_get_watch_missing_wd(self): |
167 | """Test that the correct path is returned.""" |
168 | @@ -554,16 +667,35 @@ |
169 | |
170 | def test_rm_root_path(self): |
171 | """Test the removal of a root path.""" |
172 | + events = [] |
173 | + |
174 | + def fake_processor(event): |
175 | + """Memorize the processed events.""" |
176 | + events.append(event.pathname) |
177 | + |
178 | + self.watch._processor = fake_processor |
179 | self.manager.rm_path(self.path) |
180 | self.assertEqual(self.watch, self.manager._wdm.get(1)) |
181 | - event = FakeEvent(self.path) |
182 | - self.assertTrue(self.watch.exclude_filter(event)) |
183 | + self.watch._watching = True |
184 | + self.watch._process_events([(1, os.path.join(self.path, 'test'))]) |
185 | + self.assertEqual(0, len(events)) |
186 | |
187 | def test_rm_child_path(self): |
188 | """Test the removal of a child path.""" |
189 | + events = [] |
190 | + |
191 | + def fake_processor(event): |
192 | + """Memorize the processed events.""" |
193 | + events.append(event.pathname) |
194 | + |
195 | + self.watch._processor = fake_processor |
196 | child = os.path.join(self.path, u'child') |
197 | - event = FakeEvent(child) |
198 | self.manager.rm_path(child) |
199 | self.assertEqual(self.watch, self.manager._wdm[1]) |
200 | - # assert that the path is ignored |
201 | - self.assertTrue(self.watch.exclude_filter(event)) |
202 | + # assert that the correct event is ignored |
203 | + self.watch._watching = True |
204 | + self.watch._process_events([(1, os.path.join('child', 'test'))]) |
205 | + self.assertEqual(0, len(events)) |
206 | + # assert that other events are not ignored |
207 | + self.watch._process_events([(1, 'test')]) |
208 | + self.assertEqual(1, len(events)) |
209 | |
210 | === modified file 'ubuntuone/platform/windows/filesystem_notifications.py' |
211 | --- ubuntuone/platform/windows/filesystem_notifications.py 2011-07-28 19:04:19 +0000 |
212 | +++ ubuntuone/platform/windows/filesystem_notifications.py 2011-07-29 13:35:16 +0000 |
213 | @@ -122,7 +122,7 @@ |
214 | """Implement the same functions as pyinotify.Watch.""" |
215 | |
216 | def __init__(self, watch_descriptor, path, mask, auto_add, processor, |
217 | - exclude_filter=None, buf_size=8192): |
218 | + buf_size=8192): |
219 | super(Watch, self).__init__() |
220 | self.log = logging.getLogger('ubuntuone.SyncDaemon.platform.windows.' + |
221 | 'filesystem_notifications.Watch') |
222 | @@ -135,7 +135,7 @@ |
223 | self._watching = False |
224 | self._descriptor = watch_descriptor |
225 | self._auto_add = auto_add |
226 | - self.exclude_filter = exclude_filter |
227 | + self._ignore_paths = [] |
228 | self._cookie = None |
229 | self._source_pathname = None |
230 | self._process_thread = None |
231 | @@ -144,6 +144,8 @@ |
232 | self._subdirs = [] |
233 | # ensure that we work with an abspath and that we can deal with |
234 | # long paths over 260 chars. |
235 | + if not path.endswith(os.path.sep): |
236 | + path += os.path.sep |
237 | self._path = os.path.abspath(path) |
238 | self._mask = mask |
239 | # this deferred is fired when the watch has started monitoring |
240 | @@ -152,8 +154,7 @@ |
241 | |
242 | def _is_excluded(self, event): |
243 | """Return if an event is ignored.""" |
244 | - return (self.exclude_filter and self.exclude_filter(event)) or\ |
245 | - event.mask == IN_OPEN | IN_ISDIR |
246 | + return event.mask == IN_OPEN | IN_ISDIR |
247 | |
248 | # XXX: confirm is using this decorator is correct!!! (nessita) |
249 | @is_valid_windows_path(path_indexes=[1]) |
250 | @@ -184,6 +185,9 @@ |
251 | # we transform the events to be the same as the one in pyinotify |
252 | # and then use the proc_fun |
253 | for action, file_name in events: |
254 | + if any([file_name.startswith(path) |
255 | + for path in self._ignore_paths]): |
256 | + continue |
257 | # map the windows events to the pyinotify ones, tis is dirty but |
258 | # makes the multiplatform better, linux was first :P |
259 | syncdaemon_path = get_syncdaemon_valid_path( |
260 | @@ -279,6 +283,25 @@ |
261 | |
262 | CloseHandle(handle) |
263 | |
264 | + @is_valid_windows_path(path_indexes=[1]) |
265 | + def ignore_path(self, path): |
266 | + """Add the path of the events to ignore.""" |
267 | + if not path.endswith(os.path.sep): |
268 | + path += os.path.sep |
269 | + if path.startswith(self._path): |
270 | + path = path[len(self._path):] |
271 | + self._ignore_paths.append(path) |
272 | + |
273 | + @is_valid_windows_path(path_indexes=[1]) |
274 | + def remove_ignored_path(self, path): |
275 | + """Reaccept path.""" |
276 | + if not path.endswith(os.path.sep): |
277 | + path += os.path.sep |
278 | + if path.startswith(self._path): |
279 | + path = path[len(self._path):] |
280 | + if path in self._ignore_paths: |
281 | + self._ignore_paths.remove(path) |
282 | + |
283 | def start_watching(self): |
284 | """Tell the watch to start processing events.""" |
285 | for current_child in os.listdir(self._path): |
286 | @@ -322,7 +345,7 @@ |
287 | |
288 | """ |
289 | |
290 | - def __init__(self, processor, exclude_filter=lambda path: False): |
291 | + def __init__(self, processor): |
292 | """Init the manager to keep trak of the different watches.""" |
293 | super(WatchManager, self).__init__() |
294 | self._processor = processor |
295 | @@ -331,7 +354,6 @@ |
296 | self.log.setLevel(TRACE) |
297 | self._wdm = {} |
298 | self._wd_count = 0 |
299 | - self._exclude_filter = exclude_filter |
300 | self._ignored_paths = [] |
301 | |
302 | def stop(self): |
303 | @@ -356,20 +378,19 @@ |
304 | logging.error(str(e)) |
305 | |
306 | def _add_single_watch(self, path, mask, auto_add=False, |
307 | - quiet=True, exclude_filter=None): |
308 | + quiet=True): |
309 | if path in self._ignored_paths: |
310 | # simply removed it from the filter |
311 | self._ignored_paths.remove(path) |
312 | return |
313 | # we need to add a new watch |
314 | - self.log.debug('add_single_watch(%s, %s, %s, %s, %s)', path, mask, |
315 | - auto_add, quiet, exclude_filter) |
316 | + self.log.debug('add_single_watch(%s, %s, %s, %s)', path, mask, |
317 | + auto_add, quiet) |
318 | |
319 | # adjust the number of threads based on the UDFs watched |
320 | reactor.suggestThreadPoolSize(THREADPOOL_MAX + self._wd_count + 1) |
321 | self._wdm[self._wd_count] = Watch(self._wd_count, path, |
322 | - mask, auto_add, self._processor, |
323 | - exclude_filter=exclude_filter) |
324 | + mask, auto_add, self._processor) |
325 | d = self._wdm[self._wd_count].start_watching() |
326 | self._wd_count += 1 |
327 | self.log.debug('Watch count increased to %s', self._wd_count) |
328 | @@ -377,7 +398,7 @@ |
329 | |
330 | @is_valid_windows_path(path_indexes=[1]) |
331 | def add_watch(self, path, mask, auto_add=False, |
332 | - quiet=True, exclude_filter=None): |
333 | + quiet=True): |
334 | """Add a new path tp be watch. |
335 | |
336 | The method will ensure that the path is not already present. |
337 | @@ -387,8 +408,7 @@ |
338 | return defer.fail(e) |
339 | if self.get_wd(path) is None: |
340 | self.log.debug('Adding single watch on %r', path) |
341 | - return self._add_single_watch(path, mask, auto_add, quiet, |
342 | - exclude_filter) |
343 | + return self._add_single_watch(path, mask, auto_add, quiet) |
344 | else: |
345 | self.log.debug('Watch already exists on %r', path) |
346 | return defer.succeed(False) |
347 | @@ -400,6 +420,8 @@ |
348 | @is_valid_windows_path(path_indexes=[1]) |
349 | def get_wd(self, path): |
350 | """Return the watcher that is used to watch the given path.""" |
351 | + if not path.endswith(os.path.sep): |
352 | + path = path + os.path.sep |
353 | for current_wd in self._wdm: |
354 | watch_path = self._wdm[current_wd].path |
355 | if ((watch_path == path or ( |
356 | @@ -429,23 +451,8 @@ |
357 | """Remove a watch to the given path.""" |
358 | wd = self.get_wd(path) |
359 | if wd is not None: |
360 | - self.log.debug('Adding exclude filter for "%s"', path) |
361 | - # we have a watch that contains the path as a child path |
362 | - if not path in self._ignored_paths: |
363 | - self._ignored_paths.append(path) |
364 | - |
365 | - def ignore_path(event): |
366 | - """Ignore an event if it has a given path.""" |
367 | - for path in self._ignored_paths: |
368 | - if path in event.pathname: |
369 | - return True |
370 | - return False |
371 | - |
372 | - # FIXME: This assumes that we do not have other function |
373 | - # which in our usecase is correct, but what is we move this |
374 | - # to other project?!? Maybe using the manager |
375 | - # exclude_filter is better |
376 | - self._wdm[wd].exclude_filter = ignore_path |
377 | + self.log.debug('Adding exclude filter for %r', path) |
378 | + self._wdm[wd].ignore_path(path) |
379 | |
380 | |
381 | class NotifyProcessor(ProcessEvent): |
Looks ok, tests pass.