Merge lp:~mandel/ubuntuone-client/windows_sdtool into lp:ubuntuone-client

Proposed by Manuel de la Peña
Status: Merged
Approved by: Natalia Bidart
Approved revision: 1061
Merged at revision: 1019
Proposed branch: lp:~mandel/ubuntuone-client/windows_sdtool
Merge into: lp:ubuntuone-client
Diff against target: 1771 lines (+1721/-3)
4 files modified
tests/platform/windows/test_ipc.py (+1/-1)
tests/platform/windows/test_tools.py (+1043/-0)
ubuntuone/platform/windows/ipc_client.py (+107/-2)
ubuntuone/platform/windows/tools.py (+570/-0)
To merge this branch: bzr merge lp:~mandel/ubuntuone-client/windows_sdtool
Reviewer Review Type Date Requested Status
Natalia Bidart (community) Approve
Alejandro J. Cura (community) Approve
Review via email: mp+65493@code.launchpad.net

Commit message

Provides an SDTool implementation that works on windows.

Description of the change

Provides an SDTool implementation that works on windows. In order to run the tests please do:

python C:\Python27\Scripts\u1trial tests\platform\windows\test_tools.py

To post a comment you must log in.
Revision history for this message
Natalia Bidart (nataliabidart) wrote :

* In order to really handle all the possible errors in UbuntuOneClient.connect, please add to it the inlineCallbacks decorator and change:

            d = self.factory.getRootObject()
            d.addCallback(self._request_remote_objects)
            return d

for:

            yield self.factory.getRootObject()
            yield self._request_remote_objects

* We need tests for the SDTool...

review: Needs Fixing
1056. By Manuel de la Peña

Added the tests to ensure that the sdtool works as expected.

1057. By Manuel de la Peña

Merged with previous changes made on linux.

1058. By Manuel de la Peña

Fixed a number of lint issues

1059. By Manuel de la Peña

Use inlineCallbacks in the connect method.

1060. By Manuel de la Peña

Added forgotten test file.

1061. By Manuel de la Peña

Fixed lint issues and comments from reviews.

Revision history for this message
Natalia Bidart (nataliabidart) :
review: Approve
Revision history for this message
Alejandro J. Cura (alecu) wrote :

As we discussed on IRC, it would make sense to have the functions that create and return a deferred use inlineCallbacks instead. Please fix this and remove the self.bus that's not defined anywhere.

Good branch otherwise, thanks!

review: Needs Fixing
Revision history for this message
Natalia Bidart (nataliabidart) wrote :

Marking as Needs Fixing to track what Alejandro asked.

review: Needs Fixing
Revision history for this message
Alejandro J. Cura (alecu) wrote :

I'm changing the review to approve, pending the fixes that nessita will check.

review: Approve
Revision history for this message
Natalia Bidart (nataliabidart) wrote :

Filed bug #801685 so Manuel can make the improvements later, without blocking this branch.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'tests/platform/windows/test_ipc.py'
--- tests/platform/windows/test_ipc.py 2011-06-22 14:30:55 +0000
+++ tests/platform/windows/test_ipc.py 2011-06-23 16:46:29 +0000
@@ -2131,6 +2131,7 @@
2131 return d2131 return d
2132 2132
2133 def test_enable_bandwidth_throttling(self):2133 def test_enable_bandwidth_throttling(self):
2134 """Enable bandwidth throttling."""
2134 reply_handler = lambda: None2135 reply_handler = lambda: None
2135 error_handler = lambda: None2136 error_handler = lambda: None
2136 2137
@@ -2148,7 +2149,6 @@
2148 d.addCallback(test_execution)2149 d.addCallback(test_execution)
2149 # pylint: enable=E11012150 # pylint: enable=E1101
2150 return d2151 return d
2151 """Enable bandwidth throttling."""
2152 2152
2153 def test_disable_bandwidth_throttling(self):2153 def test_disable_bandwidth_throttling(self):
2154 """Disable bandwidth throttling."""2154 """Disable bandwidth throttling."""
21552155
=== added file 'tests/platform/windows/test_tools.py'
--- tests/platform/windows/test_tools.py 1970-01-01 00:00:00 +0000
+++ tests/platform/windows/test_tools.py 2011-06-23 16:46:29 +0000
@@ -0,0 +1,1043 @@
1# tests.platform.windows.test_tools - test tools for SyncDaemon
2#
3# Author: Manuel de la Pena <manuel@canonical.com>
4#
5# Copyright 2011 Canonical Ltd.
6#
7# This program is free software: you can redistribute it and/or modify it
8# under the terms of the GNU General Public License version 3, as published
9# by the Free Software Foundation.
10#
11# This program is distributed in the hope that it will be useful, but
12# WITHOUT ANY WARRANTY; without even the implied warranties of
13# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
14# PURPOSE. See the GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with this program. If not, see <http://www.gnu.org/licenses/>.
18
19from mocker import Mocker, ANY
20
21from twisted.trial.unittest import TestCase
22from twisted.internet import defer, reactor
23from twisted.spread.pb import (
24 PBServerFactory,
25 Root)
26
27from ubuntuone.platform.windows.tools import SyncDaemonTool
28from ubuntuone.platform.windows.ipc import (
29 Config,
30 Events,
31 Folders,
32 FileSystem,
33 PublicFiles,
34 Shares,
35 Status,
36 SyncDaemon,
37 NAMED_PIPE_URL)
38
39
40class SaveProtocolServerFactory(PBServerFactory):
41 """A PBServerFactory that saves the latest connected client."""
42
43 protocolInstance = None
44
45 def clientConnectionMade(self, protocol):
46 """Keep track of the given protocol."""
47 self.protocolInstance = protocol
48
49
50class FakeRoot(Root):
51 """Root object that exposes the diff referenceable objects."""
52
53 def __init__(self, status, events, sync_daemon, file_system, shares,
54 config, folders, public_files):
55 """Create a new instance that will expose the objects."""
56 self._status = status
57 self._events = events
58 self._sync_daemon = sync_daemon
59 self._file_system = file_system
60 self._shares = shares
61 self._config = config
62 self._folders = folders
63 self._public_files = public_files
64
65 def remote_get_status(self):
66 """Return the status remote object."""
67 return self._status
68
69 def remote_get_events(self):
70 """Return the events remote object."""
71 return self._events
72
73 def remote_get_sync_daemon(self):
74 """Return the sync daemon remote object."""
75 return self._sync_daemon
76
77 def remote_get_file_system(self):
78 """Return the file system remote object."""
79 return self._file_system
80
81 def remote_get_shares(self):
82 """Return the shares remote object."""
83 return self._shares
84
85 def remote_get_config(self):
86 """Return the config remote object."""
87 return self._config
88
89 def remote_get_folders(self):
90 """Return the folders remote object."""
91 return self._folders
92
93 def remote_get_public_files(self):
94 """Return the public files remote object."""
95 return self._public_files
96
97
98class TestSyncDaemonTool(TestCase):
99 """Various utility methods to test/play with the SyncDaemon."""
100
101 def setUp(self):
102 """Set up the different tests."""
103 super(TestSyncDaemonTool, self).setUp()
104 self.pipe = NAMED_PIPE_URL % 'test_stdtool'
105 self.mocker = Mocker()
106 self.root = self.mocker.mock()
107 self.status = Status(None, None, None)
108 self.status.syncdaemon_status = self.root
109 self.events = Events(None)
110 self.events.events = self.root
111 self.daemon = SyncDaemon(None, None, None, None)
112 self.daemon.service = self.root
113 self.fs = FileSystem(None, None)
114 self.fs.syncdaemon_filesystem = self.root
115 self.shares = Shares(None, None)
116 self.shares.syncdaemon_shares = self.root
117 self.config = Config(None, None)
118 self.config.syncdaemon_config = self.root
119 self.folders = Folders(None, None)
120 self.folders.syncdaemon_folders = self.root
121 self.files = PublicFiles(None, None)
122 self.files.syncdaemon_public_files = self.root
123 self.is_running = self.mocker.replace(
124 'ubuntuone.platform.windows.tools.is_running')
125 # start pb
126 self.syncdaemon_root = FakeRoot(self.status, self.events, self.daemon,
127 self.fs, self.shares, self.config,
128 self.folders, self.files)
129 self.server_factory = SaveProtocolServerFactory(self.syncdaemon_root)
130 # pylint: disable=E1101
131 self.listener = reactor.listenPipe(self.pipe, self.server_factory)
132 self.sdtool = SyncDaemonTool(named_pipe=self.pipe)
133
134 def tearDown(self):
135 """Clean reactor."""
136 if self.server_factory.protocolInstance is not None:
137 self.server_factory.protocolInstance.transport.loseConnection()
138 return defer.gatherResults([self._tearDownServer(),
139 self._tearDownClient()])
140
141 def _tearDownServer(self):
142 """Teardown the server."""
143 return defer.maybeDeferred(self.listener.stopListening)
144
145 def _tearDownClient(self):
146 """Tear down the client."""
147 self.sdtool.client.disconnect()
148 return defer.succeed(None)
149
150 @defer.inlineCallbacks
151 def _connect(self):
152 """Connect to the running service."""
153 yield self.sdtool.client.connect(self.pipe)
154 defer.returnValue(self.sdtool)
155
156 def test_wait_connected(self):
157 """Test that we wait until we connect to the server."""
158
159 def test_get_current_downloads(self):
160 """Test gettting the current downloads."""
161 downloads = [dict(name='name', id='id'),
162 dict(name='name', id='id')]
163
164 @defer.inlineCallbacks
165 def test_execution(sdtool):
166 """Actual test."""
167 self.root.current_downloads()
168 self.mocker.result(downloads)
169 self.mocker.replay()
170 result = yield sdtool.get_current_downloads()
171 self.mocker.verify()
172 self.assertEqual(downloads, result)
173
174 d = self._connect()
175 # pylint: disable=E1101
176 d.addCallback(test_execution)
177 # pylint: enable=E1101
178 return d
179
180 def test_get_current_uploads(self):
181 """Test that we get all the current uploads."""
182 uploads = [dict(name='name', id='id'),
183 dict(name='name', id='id')]
184
185 @defer.inlineCallbacks
186 def test_execution(sdtool):
187 """Actual test."""
188 self.root.current_uploads()
189 self.mocker.replay()
190 self.mocker.result(uploads)
191 result = yield sdtool.get_current_uploads()
192 self.mocker.verify()
193 self.assertEqual(uploads, result)
194
195 d = self._connect()
196 # pylint: disable=E1101
197 d.addCallback(test_execution)
198 # pylint: enable=E1101
199 return d
200
201 def test_wait_for_nirvana(self, last_event_interval=5, verbose=False):
202 """Test that we can reach nirvana."""
203 last_event_interval = 5
204
205 @defer.inlineCallbacks
206 def test_execution(sdtool):
207 """Actual test."""
208 self.root.wait_for_nirvana(last_event_interval, ANY, ANY)
209 self.mocker.replay()
210 yield sdtool.wait_for_nirvana()
211 self.mocker.verify()
212
213 d = self._connect()
214 # pylint: disable=E1101
215 d.addCallback(test_execution)
216 # pylint: enable=E1101
217 return d
218
219 def test_accept_share(self):
220 """Test that we do accept the share."""
221 share_id = 'share_id'
222
223 @defer.inlineCallbacks
224 def test_execution(sdtool):
225 """Actual test."""
226 self.root.accept_share(share_id, ANY, ANY)
227 self.mocker.replay()
228 yield sdtool.accept_share(share_id)
229 self.mocker.verify()
230
231 d = self._connect()
232 # pylint: disable=E1101
233 d.addCallback(test_execution)
234 # pylint: enable=E1101
235 return d
236
237 def test_reject_share(self):
238 """Test that we do reject the share."""
239 share_id = 'share_id'
240
241 @defer.inlineCallbacks
242 def test_execution(sdtool):
243 """Actual test."""
244 self.root.reject_share(share_id, ANY, ANY)
245 self.mocker.replay()
246 yield sdtool.reject_share(share_id)
247 self.mocker.verify()
248
249 d = self._connect()
250 # pylint: disable=E1101
251 d.addCallback(test_execution)
252 # pylint: enable=E1101
253 return d
254
255 def test_subscribe_share(self):
256 """Test that we subscribe to the share."""
257 share_id = 'share_id'
258
259 @defer.inlineCallbacks
260 def test_execution(sdtool):
261 """Actual test."""
262 self.root.subscribe(share_id)
263 self.mocker.replay()
264 yield sdtool.subscribe_share(share_id)
265 self.mocker.verify()
266
267 d = self._connect()
268 # pylint: disable=E1101
269 d.addCallback(test_execution)
270 # pylint: enable=E1101
271 return d
272
273 def test_unsubscribe_share(self):
274 """Unsubscribe from a share given its id."""
275 share_id = 'share_id'
276
277 @defer.inlineCallbacks
278 def test_execution(sdtool):
279 """Actual test."""
280 self.root.unsubscribe(share_id)
281 self.mocker.replay()
282 yield sdtool.unsubscribe_share(share_id)
283 self.mocker.verify()
284
285 d = self._connect()
286 # pylint: disable=E1101
287 d.addCallback(test_execution)
288 # pylint: enable=E1101
289 return d
290
291 def test_get_shares(self):
292 """Test that we get the list of shares."""
293 shares = [dict(name='name', id='id'),
294 dict(name='name', id='id')]
295
296 @defer.inlineCallbacks
297 def test_execution(sdtool):
298 """Actual test."""
299 self.root.get_shares()
300 self.mocker.result(shares)
301 self.mocker.replay()
302 yield sdtool.get_shares()
303 self.mocker.verify()
304
305 d = self._connect()
306 # pylint: disable=E1101
307 d.addCallback(test_execution)
308 # pylint: enable=E1101
309 return d
310
311 def test_refresh_shares(self):
312 """Test that we can refresh the shares."""
313
314 @defer.inlineCallbacks
315 def test_execution(sdtool):
316 """Actual test."""
317 self.root.refresh_shares()
318 self.mocker.replay()
319 yield sdtool.refresh_shares()
320 self.mocker.verify()
321
322 d = self._connect()
323 # pylint: disable=E1101
324 d.addCallback(test_execution)
325 # pylint: enable=E1101
326 return d
327
328 def test_offer_share(self):
329 """Test that we can indeed offer a share."""
330 path = 'path'
331 username = 'username'
332 name = 'name'
333 access_level = 'level'
334
335 @defer.inlineCallbacks
336 def test_execution(sdtool):
337 """Actual test."""
338 self.root.create_share(path, username, name, access_level)
339 self.mocker.replay()
340 yield sdtool.offer_share(path, username, name, access_level)
341 self.mocker.verify()
342
343 d = self._connect()
344 # pylint: disable=E1101
345 d.addCallback(test_execution)
346 # pylint: enable=E1101
347 return d
348
349 def test_list_shared(self):
350 """Test that we can list the shared."""
351 shares = [dict(name='name', id='id'),
352 dict(name='name', id='id')]
353
354 @defer.inlineCallbacks
355 def test_execution(sdtool):
356 """Actual test."""
357 self.root.get_shared()
358 self.mocker.result(shares)
359 self.mocker.replay()
360 yield sdtool.list_shared()
361 self.mocker.verify()
362
363 d = self._connect()
364 # pylint: disable=E1101
365 d.addCallback(test_execution)
366 # pylint: enable=E1101
367 return d
368
369 def test_create_folder(self):
370 """Test that we can create a folder."""
371 path = 'path'
372
373 @defer.inlineCallbacks
374 def test_execution(sdtool):
375 """Actual test."""
376 self.root.create(path)
377 self.mocker.replay()
378 yield sdtool.create_folder(path)
379 self.mocker.verify()
380
381 d = self._connect()
382 # pylint: disable=E1101
383 d.addCallback(test_execution)
384 # pylint: enable=E1101
385 return d
386
387 def test_delete_folder(self):
388 """Test that we can delete a folder."""
389 folder_id = 'folder_id'
390
391 @defer.inlineCallbacks
392 def test_execution(sdtool):
393 """Actual test."""
394 self.root.delete(folder_id)
395 self.mocker.replay()
396 yield sdtool.delete_folder(folder_id)
397 self.mocker.verify()
398
399 d = self._connect()
400 # pylint: disable=E1101
401 d.addCallback(test_execution)
402 # pylint: enable=E1101
403 return d
404
405 def test_subscribe_folder(self):
406 """Test that we can subscribe to a folder."""
407 folder_id = 'folder_id'
408
409 @defer.inlineCallbacks
410 def test_execution(sdtool):
411 """Actual test."""
412 self.root.subscribe(folder_id )
413 self.mocker.replay()
414 yield sdtool.subscribe_folder(folder_id )
415 self.mocker.verify()
416
417 d = self._connect()
418 # pylint: disable=E1101
419 d.addCallback(test_execution)
420 # pylint: enable=E1101
421 return d
422
423 def test_unsubscribe_folder(self):
424 """Test that we can unsubscribe to a folder."""
425 folder_id = 'folder_id'
426
427 @defer.inlineCallbacks
428 def test_execution(sdtool):
429 """Actual test."""
430 self.root.unsubscribe(folder_id)
431 self.mocker.replay()
432 yield sdtool.unsubscribe_folder(folder_id)
433 self.mocker.verify()
434
435 d = self._connect()
436 # pylint: disable=E1101
437 d.addCallback(test_execution)
438 # pylint: enable=E1101
439 return d
440
441 def test_get_folders(self):
442 """Test that we can get the folders."""
443 folders = [dict(name='name', id='id'),
444 dict(name='name', id='id')]
445
446 @defer.inlineCallbacks
447 def test_execution(sdtool):
448 """Actual test."""
449 self.root.get_folders()
450 self.mocker.result(folders)
451 self.mocker.replay()
452 yield sdtool.get_folders()
453 self.mocker.verify()
454
455 d = self._connect()
456 # pylint: disable=E1101
457 d.addCallback(test_execution)
458 # pylint: enable=E1101
459 return d
460
461 def test_get_folder_info(self):
462 """Test that we can get the info of a folder."""
463 path = 'path'
464
465 @defer.inlineCallbacks
466 def test_execution(client):
467 """Actual test."""
468 self.root.get_info(path)
469 self.mocker.replay()
470 yield client.get_folder_info(path)
471 self.mocker.verify()
472
473 d = self._connect()
474 # pylint: disable=E1101
475 d.addCallback(test_execution)
476 # pylint: enable=E1101
477 return d
478
479 def test_get_metadata(self):
480 """Test that we can get the metadata."""
481 path = 'path'
482
483 @defer.inlineCallbacks
484 def test_execution(sdtool):
485 """Actual test."""
486 self.root.get_metadata(path)
487 self.mocker.replay()
488 yield sdtool.get_metadata(path)
489 self.mocker.verify()
490
491 d = self._connect()
492 # pylint: disable=E1101
493 d.addCallback(test_execution)
494 # pylint: enable=E1101
495 return d
496
497 def test_change_public_access(self):
498 """Test that we can change the public access."""
499 path = 'path'
500 share_id = 'share_id'
501 node_id = 'node_id'
502 is_public = False
503 metadata = dict(share_id=share_id, node_id=node_id)
504
505 @defer.inlineCallbacks
506 def test_execution(sdtool):
507 """Actual test."""
508 self.root.get_metadata(path)
509 self.mocker.result(metadata)
510 self.root.change_public_access(share_id, node_id, is_public)
511 self.mocker.replay()
512 yield sdtool.change_public_access(path, is_public)
513 self.mocker.verify()
514
515 d = self._connect()
516 # pylint: disable=E1101
517 d.addCallback(test_execution)
518 # pylint: enable=E1101
519 return d
520
521 def test_quit(self):
522 """Test that we can quit."""
523
524 @defer.inlineCallbacks
525 def test_execution(sdtool):
526 """Actual test."""
527 self.is_running()
528 self.mocker.result(True)
529 self.root.quit(None, None)
530 self.mocker.replay()
531 yield sdtool.quit()
532 self.mocker.verify()
533
534 d = self._connect()
535 # pylint: disable=E1101
536 d.addCallback(test_execution)
537 # pylint: enable=E1101
538 return d
539
540 def test_connect(self):
541 """Test we can connect."""
542
543 @defer.inlineCallbacks
544 def test_execution(sdtool):
545 """Actual test."""
546 self.root.connect()
547 self.mocker.replay()
548 yield sdtool.connect()
549 self.mocker.verify()
550
551 d = self._connect()
552 # pylint: disable=E1101
553 d.addCallback(test_execution)
554 # pylint: enable=E1101
555 return d
556
557 def test_disconnect(self):
558 """Test we can disconnect."""
559
560 @defer.inlineCallbacks
561 def test_execution(sdtool):
562 """Actual test."""
563 self.root.disconnect()
564 self.mocker.replay()
565 yield sdtool.disconnect()
566 self.mocker.verify()
567
568 d = self._connect()
569 # pylint: disable=E1101
570 d.addCallback(test_execution)
571 # pylint: enable=E1101
572 return d
573
574 def test_get_status(self):
575 """Test we can get the status."""
576 status = dict(is_error=False, is_online=True, is_connected=True)
577
578 @defer.inlineCallbacks
579 def test_execution(sdtool):
580 """Actual test."""
581 self.root.current_status()
582 self.mocker.result(status)
583 self.mocker.replay()
584 yield sdtool.get_status()
585 self.mocker.verify()
586
587 d = self._connect()
588 # pylint: disable=E1101
589 d.addCallback(test_execution)
590 # pylint: enable=E1101
591 return d
592
593 def test_waiting(self):
594 """Test that we get the info of what is waitig."""
595
596 @defer.inlineCallbacks
597 def test_execution(sdtool):
598 """Actual test."""
599 self.root.waiting()
600 self.mocker.result({})
601 self.mocker.replay()
602 yield sdtool.waiting()
603 self.mocker.verify()
604
605 d = self._connect()
606 # pylint: disable=E1101
607 d.addCallback(test_execution)
608 # pylint: enable=E1101
609 return d
610
611 def test_waiting_metadata(self):
612 """Test that we can get the waiting metadata."""
613
614 @defer.inlineCallbacks
615 def test_execution(sdtool):
616 """Actual test."""
617 self.root.waiting_metadata()
618 self.mocker.replay()
619 yield sdtool.waiting_metadata()
620 self.mocker.verify()
621
622 d = self._connect()
623 # pylint: disable=E1101
624 d.addCallback(test_execution)
625 # pylint: enable=E1101
626 return d
627
628 def test_waiting_content(self):
629 """Test that we get the waiting content."""
630
631 @defer.inlineCallbacks
632 def test_execution(sdtool):
633 """Actual test."""
634 self.root.waiting_content()
635 self.mocker.replay()
636 yield sdtool.waiting_content()
637 self.mocker.verify()
638
639 d = self._connect()
640 # pylint: disable=E1101
641 d.addCallback(test_execution)
642 # pylint: enable=E1101
643 return d
644
645 def test_get_throttling_limits(self):
646 """Test that we get the throttling limits."""
647
648 @defer.inlineCallbacks
649 def test_execution(sdtool):
650 """Actual test."""
651 self.root.get_throttling_limits(ANY, ANY)
652 self.mocker.replay()
653 yield sdtool.get_throttling_limits()
654 self.mocker.verify()
655
656 d = self._connect()
657 # pylint: disable=E1101
658 d.addCallback(test_execution)
659 # pylint: enable=E1101
660 return d
661
662 def test_set_throttling_limits(self):
663 """Test that we can set the limits."""
664 download = 'download'
665 upload = 'upload'
666
667 @defer.inlineCallbacks
668 def test_execution(sdtool):
669 """Actual test."""
670 self.root.set_throttling_limits(download, upload, ANY, ANY)
671 self.mocker.replay()
672 yield sdtool.set_throttling_limits(download, upload)
673 self.mocker.verify()
674
675 d = self._connect()
676 # pylint: disable=E1101
677 d.addCallback(test_execution)
678 # pylint: enable=E1101
679 return d
680
681 def test_is_throttling_enabled(self):
682 """Test that we get the bool stating if they are active."""
683
684 @defer.inlineCallbacks
685 def test_execution(sdtool):
686 """Actual test."""
687 self.root.bandwidth_throttling_enabled(ANY, ANY)
688 self.mocker.result(True)
689 self.mocker.replay()
690 result = yield sdtool.is_throttling_enabled()
691 self.mocker.verify()
692 self.assertTrue(result)
693
694 d = self._connect()
695 # pylint: disable=E1101
696 d.addCallback(test_execution)
697 # pylint: enable=E1101
698 return d
699
700 def test_enable_throttling_true(self):
701 """Test that we can set them."""
702
703 @defer.inlineCallbacks
704 def test_execution(sdtool):
705 """Actual test."""
706 self.root.enable_bandwidth_throttling(ANY, ANY)
707 self.mocker.replay()
708 yield sdtool.enable_throttling(True)
709 self.mocker.verify()
710
711 d = self._connect()
712 # pylint: disable=E1101
713 d.addCallback(test_execution)
714 # pylint: enable=E1101
715 return d
716
717 def test_enable_throttling_false(self):
718 """Test that we can set them."""
719
720 @defer.inlineCallbacks
721 def test_execution(sdtool):
722 """Actual test."""
723 self.root.disable_bandwidth_throttling(ANY, ANY)
724 self.mocker.replay()
725 yield sdtool.enable_throttling(False)
726 self.mocker.verify()
727
728 d = self._connect()
729 # pylint: disable=E1101
730 d.addCallback(test_execution)
731 # pylint: enable=E1101
732 return d
733
734 def test_is_autoconnect_enabled(self):
735 """Test that we can read the config."""
736
737 @defer.inlineCallbacks
738 def test_execution(sdtool):
739 """Actual test."""
740 self.root.autoconnect_enabled()
741 self.mocker.replay()
742 self.mocker.result(True)
743 result = yield sdtool.is_autoconnect_enabled()
744 self.mocker.verify()
745 self.assertTrue(result)
746
747 d = self._connect()
748 # pylint: disable=E1101
749 d.addCallback(test_execution)
750 # pylint: enable=E1101
751 return d
752
753 def test_enable_autoconnect(self):
754 """Test that we can enable the autoconnect."""
755 enabled = False
756
757 @defer.inlineCallbacks
758 def test_execution(sdtool):
759 """Actual test."""
760 self.root.set_autoconnect_enabled(enabled)
761 self.mocker.replay()
762 yield sdtool.enable_autoconnect(enabled)
763 self.mocker.verify()
764
765 d = self._connect()
766 # pylint: disable=E1101
767 d.addCallback(test_execution)
768 # pylint: enable=E1101
769 return d
770
771 def test_is_show_all_notifications_enabled(self):
772 """Test if we can read the info."""
773
774 @defer.inlineCallbacks
775 def test_execution(sdtool):
776 """Actual test."""
777 self.root.show_all_notifications_enabled()
778 self.mocker.result(True)
779 self.mocker.replay()
780 result = yield sdtool.is_show_all_notifications_enabled()
781 self.mocker.verify()
782 self.assertTrue(result)
783
784 d = self._connect()
785 # pylint: disable=E1101
786 d.addCallback(test_execution)
787 # pylint: enable=E1101
788 return d
789
790 def test_enable_show_all_notifications_true(self):
791 """Enable/disable show_all_notifications."""
792
793 @defer.inlineCallbacks
794 def test_execution(sdtool):
795 """Actual test."""
796 self.root.enable_show_all_notifications()
797 self.mocker.replay()
798 yield sdtool.enable_show_all_notifications(True)
799 self.mocker.verify()
800
801 d = self._connect()
802 # pylint: disable=E1101
803 d.addCallback(test_execution)
804 # pylint: enable=E1101
805 return d
806
807 def test_enable_show_all_notifications_false(self):
808 """Enable/disable show_all_notifications."""
809
810 @defer.inlineCallbacks
811 def test_execution(sdtool):
812 """Actual test."""
813 self.root.disable_show_all_notifications()
814 self.mocker.replay()
815 yield sdtool.enable_show_all_notifications(False)
816 self.mocker.verify()
817
818 d = self._connect()
819 # pylint: disable=E1101
820 d.addCallback(test_execution)
821 # pylint: enable=E1101
822 return d
823
824 def test_is_share_autosubscribe_enabled(self):
825 """Test that we can get the config."""
826
827 @defer.inlineCallbacks
828 def test_execution(sdtool):
829 """Actual test."""
830 self.root.share_autosubscribe_enabled()
831 self.mocker.result(True)
832 self.mocker.replay()
833 result = yield sdtool.is_share_autosubscribe_enabled()
834 self.mocker.verify()
835 self.assertTrue(result)
836
837 d = self._connect()
838 # pylint: disable=E1101
839 d.addCallback(test_execution)
840 # pylint: enable=E1101
841 return d
842
843 def test_enable_share_autosubscribe_true(self):
844 """Enable/disable share_autosubscribe."""
845
846 @defer.inlineCallbacks
847 def test_execution(sdtool):
848 """Actual test."""
849 self.root.enable_share_autosubscribe()
850 self.mocker.replay()
851 yield sdtool.enable_share_autosubscribe(True)
852 self.mocker.verify()
853
854 d = self._connect()
855 # pylint: disable=E1101
856 d.addCallback(test_execution)
857 # pylint: enable=E1101
858 return d
859
860 def test_enable_share_autosubscribe_false(self):
861 """Enable/disable share_autosubscribe."""
862
863 @defer.inlineCallbacks
864 def test_execution(sdtool):
865 """Actual test."""
866 self.root.disable_share_autosubscribe()
867 self.mocker.replay()
868 yield sdtool.enable_share_autosubscribe(False)
869 self.mocker.verify()
870
871 d = self._connect()
872 # pylint: disable=E1101
873 d.addCallback(test_execution)
874 # pylint: enable=E1101
875 return d
876
877 def test_is_udf_autosubscribe_enabled(self):
878 """Test that we can get the config value."""
879
880 @defer.inlineCallbacks
881 def test_execution(sdtool):
882 """Actual test."""
883 self.root.udf_autosubscribe_enabled()
884 self.mocker.result(True)
885 self.mocker.replay()
886 result = yield sdtool.is_udf_autosubscribe_enabled()
887 self.mocker.verify()
888 self.assertTrue(result)
889
890 d = self._connect()
891 # pylint: disable=E1101
892 d.addCallback(test_execution)
893 # pylint: enable=E1101
894 return d
895
896 def test_enable_udf_autosubscribe_true(self):
897 """Test that we can get the config."""
898
899 @defer.inlineCallbacks
900 def test_execution(sdtool):
901 """Actual test."""
902 self.root.enable_udf_autosubscribe()
903 self.mocker.replay()
904 yield sdtool.enable_udf_autosubscribe(True)
905 self.mocker.verify()
906
907 d = self._connect()
908 # pylint: disable=E1101
909 d.addCallback(test_execution)
910 # pylint: enable=E1101
911 return d
912
913 def test_enable_udf_autosubscribe_false(self):
914 """Test that we can set the config."""
915
916 @defer.inlineCallbacks
917 def test_execution(sdtool):
918 """Actual test."""
919 self.root.disable_udf_autosubscribe()
920 self.mocker.replay()
921 yield sdtool.enable_udf_autosubscribe(False)
922 self.mocker.verify()
923
924 d = self._connect()
925 # pylint: disable=E1101
926 d.addCallback(test_execution)
927 # pylint: enable=E1101
928 return d
929
930 def test_refresh_volumes(self):
931 """Test that we can refresh the volumes."""
932
933 @defer.inlineCallbacks
934 def test_execution(sdtool):
935 """Actual test."""
936 self.root.refresh_volumes()
937 self.mocker.replay()
938 yield sdtool.refresh_volumes()
939 self.mocker.verify()
940
941 d = self._connect()
942 # pylint: disable=E1101
943 d.addCallback(test_execution)
944 # pylint: enable=E1101
945 return d
946
947 def test_rescan_from_scratch(self):
948 """Test that we can rescan from scratch."""
949 volume_id = 'volume_id'
950
951 @defer.inlineCallbacks
952 def test_execution(sdtool):
953 """Actual test."""
954 self.root.rescan_from_scratch(volume_id)
955 self.mocker.replay()
956 yield sdtool.rescan_from_scratch(volume_id)
957 self.mocker.verify()
958
959 d = self._connect()
960 # pylint: disable=E1101
961 d.addCallback(test_execution)
962 # pylint: enable=E1101
963 return d
964
965 def test_get_dirty_nodes(self):
966 """Test that we get the dirty nodes."""
967 dirty_nodes = ['node_1', 'node_2', 'node_3']
968
969 @defer.inlineCallbacks
970 def test_execution(sdtool):
971 """Actual test."""
972 self.root.get_dirty_nodes()
973 self.mocker.result(dirty_nodes)
974 self.mocker.replay()
975 result = yield sdtool.get_dirty_nodes()
976 self.mocker.verify()
977 self.assertEqual(dirty_nodes, result)
978
979 d = self._connect()
980 # pylint: disable=E1101
981 d.addCallback(test_execution)
982 # pylint: enable=E1101
983 return d
984
985 def test_get_root_dir(self):
986 """Test that we get the root dir."""
987 root = '/path/to/root'
988
989 @defer.inlineCallbacks
990 def test_execution(sdtool):
991 """Actual test."""
992 self.root.get_rootdir()
993 self.mocker.result(root)
994 self.mocker.replay()
995 result = yield sdtool.get_root_dir()
996 self.mocker.verify()
997 self.assertEqual(root, result)
998
999 d = self._connect()
1000 # pylint: disable=E1101
1001 d.addCallback(test_execution)
1002 # pylint: enable=E1101
1003 return d
1004
1005 def test_get_shares_dir(self):
1006 """Test that we get the shares dir."""
1007 shares_dir = '/path/to/shares'
1008
1009 @defer.inlineCallbacks
1010 def test_execution(sdtool):
1011 """Actual test."""
1012 self.root.get_sharesdir()
1013 self.mocker.result(shares_dir)
1014 self.mocker.replay()
1015 result = yield sdtool.get_shares_dir()
1016 self.mocker.verify()
1017 self.assertEqual(shares_dir, result)
1018
1019 d = self._connect()
1020 # pylint: disable=E1101
1021 d.addCallback(test_execution)
1022 # pylint: enable=E1101
1023 return d
1024
1025 def test_get_shares_dir_link(self):
1026 """Test that we get the link dir."""
1027 link = 'path/to/link'
1028
1029 @defer.inlineCallbacks
1030 def test_execution(sdtool):
1031 """Actual test."""
1032 self.root.get_sharesdir_link()
1033 self.mocker.result(link)
1034 self.mocker.replay()
1035 result = yield sdtool.get_shares_dir_link()
1036 self.mocker.verify()
1037 self.assertEqual(link, result)
1038
1039 d = self._connect()
1040 # pylint: disable=E1101
1041 d.addCallback(test_execution)
1042 # pylint: enable=E1101
1043 return d
01044
=== modified file 'ubuntuone/platform/windows/ipc_client.py'
--- ubuntuone/platform/windows/ipc_client.py 2011-05-04 13:39:41 +0000
+++ ubuntuone/platform/windows/ipc_client.py 2011-06-23 16:46:29 +0000
@@ -18,13 +18,26 @@
18"""Client lib to simplify the ipc client code."""18"""Client lib to simplify the ipc client code."""
1919
20import logging20import logging
21
21from functools import wraps22from functools import wraps
22from twisted.spread.pb import Referenceable23from win32api import GetUserNameEx
23from ubuntuone.platform.windows.ipc import RemoteMeta24from win32con import NameSamCompatible
25from twisted.internet import defer, reactor
26from twisted.spread.pb import Referenceable, PBClientFactory
27
28from ubuntuone.platform.windows.ipc import RemoteMeta, NAMED_PIPE_URL
2429
25logger = logging.getLogger("ubuntuone.SyncDaemon.Client")30logger = logging.getLogger("ubuntuone.SyncDaemon.Client")
2631
2732
33class SyncDaemonClientError(Exception):
34 """Error ocurred when trying to be a client."""
35
36
37class SyncDaemonClientConnectionError(SyncDaemonClientError):
38 """Error ocurrend when trying to connect."""
39
40
28def remote(function):41def remote(function):
29 """Decorate the function to make the remote call."""42 """Decorate the function to make the remote call."""
30 @wraps(function)43 @wraps(function)
@@ -660,3 +673,95 @@
660 @signal673 @signal
661 def on_public_files_list_error(self, error):674 def on_public_files_list_error(self, error):
662 """Emit the PublicFilesListError signal."""675 """Emit the PublicFilesListError signal."""
676
677class UbuntuOneClient(object):
678 """Root object that provides access to all the remote objects."""
679
680 def __init__(self):
681 """Create a new instance."""
682 self.status = None
683 self.events = None
684 self.sync_daemon = None
685 self.file_system = None
686 self.shares = None
687 self.config = None
688 self.folders = None
689 self.public_files = None
690 self.factory = None
691 self.client = None
692
693 @defer.inlineCallbacks
694 def _request_remote_objects(self, root):
695 """Request all the diff remote objects used for the communication."""
696 status = yield root.callRemote('get_status')
697 self.status = StatusClient(status)
698
699 events = yield root.callRemote('get_events')
700 self.events = EventsClient(events)
701
702 sync_daemon = yield root.callRemote('get_sync_daemon')
703 self.sync_daemon = SyncDaemonClient(sync_daemon)
704
705 file_system = yield root.callRemote('get_file_system')
706 self.file_system = FileSystemClient(file_system)
707
708 shares = yield root.callRemote('get_shares')
709 self.shares = SharesClient(shares)
710
711 config = yield root.callRemote('get_config')
712 self.config = ConfigClient(config)
713
714 folders = yield root.callRemote('get_folders')
715 self.folders = FoldersClient(folders)
716
717 public_files = yield root.callRemote('get_public_files')
718 self.public_files = PublicFilesClient(public_files)
719
720 defer.returnValue(self)
721
722 @defer.inlineCallbacks
723 def connect(self, pipe=None):
724 """Connect to the sso service."""
725 # pylint: disable=W0702
726 try:
727 if pipe is None:
728 pipe = NAMED_PIPE_URL % GetUserNameEx(NameSamCompatible)
729 # got the pipe, lets try and connect to it and get the diff
730 # remote objects for the wrappers
731 self.factory = PBClientFactory()
732 # the reactor does have a connectTCP method
733 # pylint: disable=E1101
734 self.client = reactor.connectPipe(pipe, self.factory)
735 # pylint: enable=E1101
736 yield self.factory.getRootObject()
737 yield self._request_remote_objects()
738 except:
739 raise SyncDaemonClientConnectionError(
740 'Could not connect to the syncdaemon on pipe %.',
741 pipe)
742 # pylint: disable=W0702
743
744 @defer.inlineCallbacks
745 def register_to_signals(self):
746 """Register the different clients to the signals."""
747 for client in [self.status, self.events, self.sync_daemon, self.shares,
748 self.folders, self.public_files]:
749 register = getattr(client, 'register_to_signals', None)
750 if register is not None:
751 yield register()
752 defer.returnValue(self)
753
754 @defer.inlineCallbacks
755 def unregister_to_signals(self):
756 """Unregister from the diff signals."""
757 for client in [self.status, self.events, self.sync_daemon, self.shares,
758 self.folders, self.public_files]:
759 unregister = getattr(client, 'unregister_to_signals', None)
760 if unregister is not None:
761 yield unregister()
762 defer.returnValue(self)
763
764 def disconnect(self):
765 """Disconnect from the process."""
766 if self.client:
767 self.client.disconnect()
663768
=== added file 'ubuntuone/platform/windows/tools.py'
--- ubuntuone/platform/windows/tools.py 1970-01-01 00:00:00 +0000
+++ ubuntuone/platform/windows/tools.py 2011-06-23 16:46:29 +0000
@@ -0,0 +1,570 @@
1# ubuntuone.syncdaemon.tools - tools for SyncDaemon
2#
3# Author: Guillermo Gonzalez <guillermo.gonzalez@canonical.com>
4# Manuel de la Pena <manuel@canonical.com>
5#
6# Copyright 2011 Canonical Ltd.
7#
8# This program is free software: you can redistribute it and/or modify it
9# under the terms of the GNU General Public License version 3, as published
10# by the Free Software Foundation.
11#
12# This program is distributed in the hope that it will be useful, but
13# WITHOUT ANY WARRANTY; without even the implied warranties of
14# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
15# PURPOSE. See the GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License along
18# with this program. If not, see <http://www.gnu.org/licenses/>.
19
20"""SyncDaemon Tools."""
21
22import logging
23import time
24import sys
25
26from win32api import GetUserNameEx
27from win32con import NameSamCompatible
28from win32pipe import CallNamedPipe
29from twisted.internet import defer, reactor
30
31from ubuntuone.syncdaemon.config import get_user_config
32from ubuntuone.platform.windows.ipc import NAMED_PIPE_URL
33from ubuntuone.platform.windows.ipc_client import UbuntuOneClient
34
35
36def is_running(bus=None):
37 """Check if there is a syncdaemon instance running.
38
39 Running means the name is registered in the given bus.
40
41 """
42 pipe = NAMED_PIPE_URL % GetUserNameEx(NameSamCompatible)
43 try:
44 CallNamedPipe(pipe, '', 512, 0)
45 return True
46 except:
47 return False
48
49
50class SyncDaemonTool(object):
51 """Various utility methods to test/play with the SyncDaemon."""
52
53 def __init__(self, named_pipe=None):
54 self.named_pipe = named_pipe
55 self.client = UbuntuOneClient()
56 self.last_event = 0
57 self.delayed_call = None
58 self.log = logging.getLogger('ubuntuone.SyncDaemon.SDTool')
59
60
61 def _get_dict(self, a_dict):
62 """Converts a dict returned by the IPC to a dict of strings."""
63 str_dict = {}
64 for key in a_dict:
65 str_dict[key] = unicode(a_dict[key])
66 return str_dict
67
68 def wait_connected(self):
69 """Wait until syncdaemon is connected to the server."""
70 self.log.debug('wait_connected')
71 d = defer.Deferred()
72
73 def check_connection_status():
74 """Check if the daemon is up and running."""
75 # check if the syncdaemon is running
76 # catch all errors, pylint: disable-msg=W0703
77 try:
78 self.client.connect(pipe=self.named_pipe)
79 d.callback(True)
80 except Exception, e:
81 self.log.debug('Not connected: %s', e)
82 d.errback()
83
84 reactor.callLater(.5, check_connection_status)
85 return d
86
87 def get_current_downloads(self):
88 """Return a deferred that will be fired with the current downloads."""
89 d = defer.Deferred()
90
91 def reply_handler(downloads, d):
92 """Current downloads callback."""
93 downloads_str = []
94 for download in downloads:
95 downloads_str.append(self._get_dict(download))
96 d.callback(downloads_str)
97
98 downloads_d = self.client.status.current_downloads()
99 downloads_d.addCallback(lambda downloads: reply_handler(downloads, d))
100 return d
101
102 def wait_all_downloads(self, verbose=False):
103 """Wait until there is no more pending downloads."""
104 self.log.debug('wait_all_downloads')
105 d = self.get_current_downloads()
106
107 def reply_handler(downloads):
108 """Check if the are downloads in progress.
109
110 If so, reschelude a new check if there is at least one.
111
112 """
113 if verbose:
114 sys.stdout.write(', %s' % str(len(downloads)))
115 sys.stdout.flush()
116 if len(downloads) > 0:
117 self.log.debug('wait_all_downloads: %d', len(downloads))
118 return self.get_current_downloads()
119 else:
120 self.log.debug('wait_all_downloads: No more downloads')
121 return True
122
123 if verbose:
124 sys.stdout.write('\nchecking current downloads')
125 sys.stdout.flush()
126 d.addCallback(reply_handler)
127 return d
128
129 def get_current_uploads(self):
130 """Return a deferred that will be called with the current uploads."""
131 d = defer.Deferred()
132
133 def reply_handler(uploads, d):
134 """Reply handler."""
135 uploads_str = []
136 for upload in uploads:
137 uploads_str.append(self._get_dict(upload))
138 d.callback(uploads_str)
139
140 uploads_d = self.client.status.current_uploads()
141 uploads_d.addCallback(lambda uploads: reply_handler(uploads, d))
142 return d
143
144 def wait_all_uploads(self, verbose=False):
145 """Wait until there is no more pending uploads."""
146 self.log.debug('wait_all_uploads')
147 d = self.get_current_uploads()
148
149 def reply_handler(uploads):
150 """Check if the are downloads in progress.
151
152 If so, reschelude a new check if there is at least one.
153
154 """
155 if verbose:
156 sys.stdout.write(', %s' % str(len(uploads)))
157 sys.stdout.flush()
158 if len(uploads) > 0:
159 self.log.debug('wait_all_uploads: %d', len(uploads))
160 return self.get_current_uploads()
161 else:
162 self.log.debug('wait_all_uploads: No more uploads')
163 return True
164
165 if verbose:
166 sys.stdout.write('\nchecking current uploads')
167 sys.stdout.flush()
168
169 d.addCallback(reply_handler)
170 return d
171
172 def wait_no_more_events(self, last_event_interval, verbose=False):
173 """Wait until no more events are fired by the syncdaemon."""
174 self.log.debug('wait_no_more_events')
175 d = defer.Deferred()
176
177 def check_last_event():
178 """Check time!
179
180 Check if the daemon is connected and didn't received event
181 in the last_event_interval.
182 """
183 current_time = time.time()
184 if self.last_event and \
185 current_time - self.last_event < last_event_interval:
186 # keep it running in case this is the last event
187 self.log.debug('rescheduling wait_no_more_events')
188 if not self.delayed_call.active():
189 self.delayed_call = reactor.callLater(last_event_interval,
190 check_last_event)
191 else:
192 self.delayed_call.reset(last_event_interval)
193 else:
194 self.log.debug('wait_no_more_events: No more events!')
195 d.callback(True)
196
197 if verbose:
198 sys.stdout.write("Listening events")
199 sys.stdout.flush()
200
201 def event_handler(event_dict):
202 """Update last_event and run checks."""
203 self.last_event = time.time()
204 self.log.debug('wait_no_more_events - new event: %s - %s',
205 event_dict['event_name'], str(self.last_event))
206 if verbose:
207 sys.stdout.write('.')
208 sys.stdout.flush()
209 if self.delayed_call.active():
210 self.delayed_call.reset(last_event_interval)
211
212 self.client.events.on_event_cb = event_handler
213
214 def cleanup(result):
215 """Remove the signal handler."""
216 self.client.events.on_event_cb = None
217 return result
218 d.addBoth(cleanup)
219
220 # in case the daemon already reached nirvana
221 self.delayed_call = reactor.callLater(last_event_interval,
222 check_last_event)
223 return d
224
225 def wait_for_nirvana(self, last_event_interval=5, verbose=False):
226 """Wait until the syncdaemon reachs nirvana.
227
228 This is when there are:
229 - the syncdaemon is connected
230 - 0 transfers inprogress
231 - no more events are fired in the event queue
232 @param last_event_interval: the seconds to wait to determine that there
233 is no more events in the queue and the daemon reached nirvana
234 """
235 self.log.debug('wait_for_nirvana')
236 return self.client.sync_daemon.wait_for_nirvana(last_event_interval)
237
238 def accept_share(self, share_id):
239 """Accept the share with id: share_id."""
240 self.log.debug('accept_share(%s)', share_id)
241 self.client.shares.on_share_answer_response = lambda info:\
242 info['volume_id']==share_id
243 return self.client.shares.accept_share(share_id)
244
245 def reject_share(self, share_id):
246 """Reject the share with id: share_id."""
247 self.log.debug('reject_share(%s)', share_id)
248 self.client.shares.on_share_answer_response = lambda info:\
249 info['volume_id']==share_id
250 return self.client.shares.reject_share(share_id)
251
252 def subscribe_share(self, share_id):
253 """Subscribe to a share given its id."""
254 self.log.debug('subscribe_share: %r', share_id)
255 return self.client.shares.subscribe(share_id)
256
257 def unsubscribe_share(self, share_id):
258 """Unsubscribe from a share given its id."""
259 self.log.debug('unsubscribe_share: %r', share_id)
260 return self.client.shares.unsubscribe(share_id)
261
262 def get_shares(self):
263 """Get the list of shares (accepted or not)."""
264 self.log.debug('get_shares')
265 d = defer.Deferred()
266
267 def reply_handler(results):
268 """Get_shares reply handler."""
269 shares = []
270 for result in results:
271 shares.append(self._get_dict(result))
272 self.log.debug('shares: %r', shares)
273 d.callback(shares)
274
275 shares_d = self.client.shares.get_shares()
276 shares_d.addCallback(reply_handler)
277 return d
278
279 def refresh_shares(self):
280 """Call refresh_shares method via DBus.
281
282 Request a refresh of share list to the server.
283
284 """
285 self.log.debug('refresh_shares')
286 return self.client.shares.refresh_shares()
287
288 def offer_share(self, path, username, name, access_level):
289 """Offer a share at the specified path to user with id: username."""
290 self.log.debug('offer_share(%s, %s, %s, %s)',
291 path, username, name, access_level)
292 return self.client.shares.create_share(path, username, name,
293 access_level)
294
295 def list_shared(self):
296 """Get the list of the shares "shared"/created/offered."""
297 self.log.debug('list_shared')
298 d = defer.Deferred()
299
300 def reply_handler(results):
301 """Get_shares reply handler."""
302 shares = []
303 for result in results:
304 shares.append(self._get_dict(result))
305 self.log.debug('shared: %r', shares)
306 d.callback(shares)
307
308 shared_d = self.client.shares.get_shared()
309 shared_d.addCallback(reply_handler)
310 return d
311
312 def wait_for_signals(self, signal_ok, signal_error,
313 dbus_iface=None):
314 """Wait for one of the specified signals, return a deferred.
315
316 @param signal_ok: this will fire the deferred's callback
317 @param signal_error: the will fire the deferred's errback
318 @param dbus_iface: the interface the signal belongs to
319 """
320 raise NotImplementedError('Not implemented yet!')
321
322 def create_folder(self, path):
323 """Create a user defined folder in the specified path."""
324 self.log.debug('create_folder')
325 return self.client.folders.create(path)
326
327 def delete_folder(self, folder_id):
328 """Delete a user defined folder given its id."""
329 self.log.debug('delete_folder')
330 return self.client.folders.delete(folder_id)
331
332 def subscribe_folder(self, folder_id):
333 """Subscribe to a user defined folder given its id."""
334 self.log.debug('subscribe_folder')
335 return self.client.folders.subscribe(folder_id)
336
337 def unsubscribe_folder(self, folder_id):
338 """Unsubscribe from a user defined folder given its id."""
339 self.log.debug('unsubscribe_folder')
340 return self.client.folders.unsubscribe(folder_id)
341
342 def get_folders(self):
343 """Return the list of folders (a list of dicts)."""
344 self.log.debug('get_folders')
345 d = defer.Deferred()
346
347 def reply_handler(results):
348 """Get_folders reply handler."""
349 folders = []
350 for result in results:
351 folders.append(self._get_dict(result))
352 self.log.debug('folders: %r', folders)
353 d.callback(folders)
354
355 folders_d = self.client.folders.get_folders()
356 folders_d.addCallback(reply_handler)
357 return d
358
359 def get_folder_info(self, path):
360 """Call the get_info method for a UDF path."""
361 self.log.debug('get_info')
362 return self.client.folders.get_info(path)
363
364 def get_metadata(self, path):
365 """Call the exposed mtehod FileSystem.get_metadata using DBus."""
366 self.log.debug('get_metadata(%s)', path)
367 return self.client.file_system.get_metadata(path)
368
369 @defer.inlineCallbacks
370 def change_public_access(self, path, is_public):
371 """Change the public access for a given path."""
372 self.log.debug('change_public_access(%s)', path)
373 metadata = yield self.client.file_system.get_metadata(path)
374 file_info = yield self.client.public_files.change_public_access(
375 metadata['share_id'],
376 metadata['node_id'],
377 is_public)
378 defer.returnValue(file_info)
379
380 def quit(self):
381 """Quit the syncdaemon."""
382 self.log.debug('quit')
383 # avoid triggering dbus activation while calling quit
384 if not is_running():
385 return defer.succeed(None)
386
387 def check(r):
388 """Wait 0.5 sec to return, to allow syncdaemon to shutdown."""
389 d1 = defer.Deferred()
390 reactor.callLater(0.5, d1.callback, r)
391 return d1
392
393 d = self.client.sync_daemon.quit()
394 d.addCallback(check)
395 return d
396
397 def wait_for_signal(self, signal_name, filter):
398 """Wait for the specified DBus signal (the first received).
399
400 @param signal_name: the signal name
401 @param filter: a callable to filter signal, must return True, and is
402 used to fire the deferred callback.
403
404 """
405 raise NotImplementedError('Not implemented.')
406
407 def connect(self):
408 """Connect syncdaemon."""
409 return self.client.sync_daemon.connect()
410
411 def disconnect(self):
412 """Disconnect syncdaemon."""
413 return self.client.sync_daemon.disconnect()
414
415 def get_status(self):
416 """Get the current_status dict."""
417
418 d = defer.Deferred()
419 def reply_handler(status):
420 """The reply handler"""
421 state_dict = self._get_dict(status)
422 state_dict['is_connected'] = bool(state_dict['is_connected'])
423 state_dict['is_online'] = bool(state_dict['is_online'])
424 state_dict['is_error'] = bool(state_dict['is_error'])
425 d.callback(state_dict)
426 status_d = self.client.status.current_status()
427 status_d.addCallback(reply_handler)
428 status_d.addErrback(d.errback)
429 return d
430
431 def waiting(self):
432 """Return a description of the waiting queue elements."""
433 return self.client.status.waiting()
434
435 def waiting_metadata(self):
436 """Return a description of the waiting metadata queue elements."""
437 return self.client.status.waiting_metadata()
438
439 def waiting_content(self):
440 """Return the waiting content queue elements."""
441 return self.client.status.waiting_content()
442
443 def start(self):
444 """Start syncdaemon if it's not running."""
445 if not is_running(self.bus):
446 raise Exception('Not implemented yet!')
447 else:
448 return defer.succeed(None)
449
450 def get_throttling_limits(self):
451 """Return a dict with the read and write limits."""
452 return self.client.config.get_throttling_limits()
453
454 def set_throttling_limits(self, read_limit, write_limit):
455 """Set the read and write limits."""
456 return self.client.config.set_throttling_limits(read_limit,
457 write_limit)
458
459 def is_throttling_enabled(self):
460 """Check if throttling is enabled."""
461 return self.client.config.bandwidth_throttling_enabled()
462
463 def enable_throttling(self, enabled):
464 """Enable/disable throttling."""
465 if enabled:
466 return self.client.config.enable_bandwidth_throttling()
467 else:
468 return self.client.config.disable_bandwidth_throttling()
469
470 def is_files_sync_enabled(self):
471 """Check if files sync is enabled."""
472 self.log.debug('is_files_sync_enabled')
473 return get_user_config().get_files_sync_enabled()
474
475 @defer.inlineCallbacks
476 def enable_files_sync(self, enabled):
477 """Enable/disable files sync."""
478 config = get_user_config()
479 was_enabled = config.get_files_sync_enabled()
480 self.log.debug('enable_files_sync: enable? %r was enabled? %r',
481 enabled, was_enabled)
482 if was_enabled:
483 yield self.client.config.set_files_sync_enabled(enabled)
484 config.set_files_sync_enabled(enabled)
485 if not enabled:
486 # User requested the service to be disabled
487 self.quit()
488 else:
489 if enabled:
490 config.set_files_sync_enabled(True)
491 config.save()
492 self.start()
493
494 def is_autoconnect_enabled(self):
495 """Check if autoconnect is enabled."""
496 return self.client.config.autoconnect_enabled()
497
498 def enable_autoconnect(self, enabled):
499 """Enable/disable autoconnect."""
500 return self.client.config.set_autoconnect_enabled(enabled)
501
502 def is_show_all_notifications_enabled(self):
503 """Check if show_all_notifications is enabled."""
504 return self.client.config.show_all_notifications_enabled()
505
506 def enable_show_all_notifications(self, enabled):
507 """Enable/disable show_all_notifications."""
508 if enabled:
509 return self.client.config.enable_show_all_notifications()
510 else:
511 return self.client.config.disable_show_all_notifications()
512
513 def is_share_autosubscribe_enabled(self):
514 """Check if share_autosubscribe is enabled."""
515 return self.client.config.share_autosubscribe_enabled()
516
517 def enable_share_autosubscribe(self, enabled):
518 """Enable/disable share_autosubscribe."""
519 if enabled:
520 return self.client.config.enable_share_autosubscribe()
521 else:
522 return self.client.config.disable_share_autosubscribe()
523
524 def is_udf_autosubscribe_enabled(self):
525 """Check if udf_autosubscribe is enabled."""
526 return self.client.config.udf_autosubscribe_enabled()
527
528 def enable_udf_autosubscribe(self, enabled):
529 """Enable/disable udf_autosubscribe."""
530 if enabled:
531 return self.client.config.enable_udf_autosubscribe()
532 else:
533 return self.client.config.disable_udf_autosubscribe()
534
535 def refresh_volumes(self):
536 """Call refresh_volumes method via DBus.
537
538 Request the volumes list to the server.
539 """
540 self.log.debug('refresh_volumes')
541 return self.client.folders.refresh_volumes()
542
543 def rescan_from_scratch(self, volume_id):
544 """Call rescan_from_scratch via DBus.
545
546 Request a rescan from scratch for volume_id.
547 """
548 self.log.debug('rescan_from_scratch %r', volume_id)
549 return self.client.sync_daemon.rescan_from_scratch(volume_id)
550
551 def get_dirty_nodes(self):
552 """Call get_dirty_nodes via DBus.
553
554 Return the list of dirty nodes.
555 """
556 self.log.debug('get_dirty_nodes')
557 return self.client.file_system.get_dirty_nodes()
558
559 def get_root_dir(self):
560 """Return the root directory."""
561 return self.client.sync_daemon.get_rootdir()
562
563 def get_shares_dir(self):
564 """Return the shares directory."""
565 return self.client.sync_daemon.get_sharesdir()
566
567 def get_shares_dir_link(self):
568 """Return the shares link directory."""
569 return self.client.sync_daemon.get_sharesdir_link()
570

Subscribers

People subscribed via source and target branches