Merge lp:~diegosarmentero/ubuntuone-client/ubuntuone-client-syncstate into lp:ubuntuone-client

Proposed by Diego Sarmentero
Status: Merged
Approved by: Diego Sarmentero
Approved revision: 1332
Merged at revision: 1338
Proposed branch: lp:~diegosarmentero/ubuntuone-client/ubuntuone-client-syncstate
Merge into: lp:ubuntuone-client
Diff against target: 238 lines (+110/-21)
4 files modified
tests/platform/sync_menu/test_linux.py (+50/-15)
tests/status/test_aggregator.py (+30/-0)
ubuntuone/platform/sync_menu/linux.py (+16/-6)
ubuntuone/status/aggregator.py (+14/-0)
To merge this branch: bzr merge lp:~diegosarmentero/ubuntuone-client/ubuntuone-client-syncstate
Reviewer Review Type Date Requested Status
Manuel de la Peña (community) Approve
Roberto Alsina (community) Approve
Review via email: mp+128958@code.launchpad.net

Commit message

- Recceive notifications from aggregator when the status of syncdaemon change (LP: #1053631).

To post a comment you must log in.
1332. By Diego Sarmentero

fixing link

Revision history for this message
Roberto Alsina (ralsina) wrote :

Code looks good, running tests takes way too long here :-(

review: Approve
Revision history for this message
Manuel de la Peña (mandel) wrote :

Code looks good and tests pass. I have a small idea to make things a little nicer, what about doing the foSyncllowing:

SyncMenuStatus = namedtuple('SyncMenuStatus',
    ['_connected', 'ignore_status_event', 'connect_called', 'disconnect_called'], verbose=False)

def _assert_sync_status(self, expected):
    self.assertEqual(expected.connected, self.sync_menu._connected)
    self.assertEqual(expected.ignore_status_event, self.sync_menu._ignore_status_event)
    self.assertEqual(expected.connected_called, self.sync_menu._syncdaemon_service.connect_called)
    self.assertEqual(expected.disconnected_called, self.sync_menu._syncdaemon_service.disconnect_called)

and the we can have tests like the following (based on a current test):

def test_status_change_from_menu(self):
    """Check the behavior when the status is changed from the menu."""
    self.sync_menu.change_sync_status()
    self._assert_sync_status(SyncMenuStatus(connected=False, ignore_status_event=False,
                                            connect_called=False, disconnect_called=True))

    self.sync_menu._syncdaemon_service.disconnect_called = False
    self.sync_menu.change_sync_status()

    self._assert_sync_status(SyncMenuStatus(connected=True, ignore_status_event=False,
                                            connect_called=True, disconnect_called=True))
    self.assertTrue(self.sync_menu._connected)

instead of:

71 + def test_status_change_from_menu(self):
72 + """Check the behavior when the status is changed from the menu."""
73 + self.sync_menu.change_sync_status()
74 + self.assertFalse(self.sync_menu._connected)
75 + self.assertFalse(self.sync_menu._ignore_status_event)
76 + self.assertFalse(self.sync_menu._syncdaemon_service.connect_called)
77 + self.assertTrue(self.sync_menu._syncdaemon_service.disconnect_called)
78 +
79 + self.sync_menu._syncdaemon_service.disconnect_called = False
80 + self.sync_menu.change_sync_status()
81 + self.assertTrue(self.sync_menu._connected)
82 + self.assertFalse(self.sync_menu._ignore_status_event)
83 + self.assertTrue(self.sync_menu._syncdaemon_service.connect_called)
84 + self.assertFalse(self.sync_menu._syncdaemon_service.disconnect_called)

Of course you can remove the use of the named tuple and just define the assert_method as:

def _assert_sync_status(self, connected=False, ignore_status_event=False,
                              connect_called=False, disconnect_called=False):

Which ever you prefer :) (I felt funny using the namedtuple :P )

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'tests/platform/sync_menu/test_linux.py'
2--- tests/platform/sync_menu/test_linux.py 2012-10-05 15:14:55 +0000
3+++ tests/platform/sync_menu/test_linux.py 2012-10-10 15:00:35 +0000
4@@ -73,6 +73,18 @@
5 class FakeSyncdaemonService(object):
6 """Fake SyncdaemonService."""
7
8+ def __init__(self):
9+ self.connect_called = False
10+ self.disconnect_called = False
11+
12+ def connect(self):
13+ """Set connect to True."""
14+ self.connect_called = True
15+
16+ def disconnect(self):
17+ """Set connect to True."""
18+ self.disconnect_called = True
19+
20
21 class FakeSyncMenuApp(object):
22 """Fake SyncMenu."""
23@@ -95,6 +107,10 @@
24 """Fake connect."""
25 self.data['connect'] = (signal, callback)
26
27+ def set_paused(self, status):
28+ """Set the pause state."""
29+ self.data['paused'] = status
30+
31
32 class SyncMenuDummyTestCase(TestCase):
33 """Test the SyncMenu."""
34@@ -123,18 +139,9 @@
35 self.syncdaemon_service = FakeSyncdaemonService()
36 self.status_frontend = FakeStatusFrontend()
37 self._paused = False
38- self.patch(sync_menu.UbuntuOneSyncMenu, "change_sync_status",
39- self._change_sync_status)
40 self.sync_menu = sync_menu.UbuntuOneSyncMenu(self.status_frontend,
41 self.syncdaemon_service)
42
43- def _change_sync_status(self, *args):
44- """Fake change_sync_status."""
45- if self._paused:
46- self._paused = False
47- else:
48- self._paused = True
49-
50 def test_init(self):
51 """Check that the menu is properly initialized."""
52 self.assertIsInstance(FakeSyncMenuApp.data['server'],
53@@ -161,12 +168,6 @@
54 self.assertEqual(self.sync_menu.get_help.property_get(
55 linux.Dbusmenu.MENUITEM_PROP_LABEL), linux.GET_HELP)
56
57- self.assertEqual(self.sync_menu.app.data['connect'],
58- ("notify::paused", self.sync_menu.change_sync_status))
59- self.sync_menu.app.data['connect'][1]()
60- self.assertTrue(self._paused)
61- self.sync_menu.app.data['connect'][1]()
62- self.assertFalse(self._paused)
63 self.sync_menu.transfers.update_progress()
64 self.assertIsInstance(self.sync_menu.transfers.separator,
65 linux.Dbusmenu.Menuitem)
66@@ -386,3 +387,37 @@
67 self.sync_menu.next_update = time.time() * 2
68 self.sync_menu.update_transfers()
69 self.assertEqual(self.sync_menu.timer.delay, 3)
70+
71+ def test_status_change_from_menu(self):
72+ """Check the behavior when the status is changed from the menu."""
73+ self.sync_menu.change_sync_status()
74+ self.assertFalse(self.sync_menu._connected)
75+ self.assertFalse(self.sync_menu._ignore_status_event)
76+ self.assertFalse(self.sync_menu._syncdaemon_service.connect_called)
77+ self.assertTrue(self.sync_menu._syncdaemon_service.disconnect_called)
78+
79+ self.sync_menu._syncdaemon_service.disconnect_called = False
80+ self.sync_menu.change_sync_status()
81+ self.assertTrue(self.sync_menu._connected)
82+ self.assertFalse(self.sync_menu._ignore_status_event)
83+ self.assertTrue(self.sync_menu._syncdaemon_service.connect_called)
84+ self.assertFalse(self.sync_menu._syncdaemon_service.disconnect_called)
85+
86+ def test_ignore_status(self):
87+ """Check that neither connect or disconnect are called."""
88+ self.sync_menu._ignore_status_event = True
89+ self.assertTrue(self.sync_menu._ignore_status_event)
90+ self.sync_menu.change_sync_status()
91+ self.assertTrue(self.sync_menu._connected)
92+ self.assertFalse(self.sync_menu._ignore_status_event)
93+ self.assertFalse(self.sync_menu._syncdaemon_service.connect_called)
94+ self.assertFalse(self.sync_menu._syncdaemon_service.disconnect_called)
95+
96+ def test_sync_status_changed(self):
97+ """Check sync_status_changed behavior."""
98+ self.sync_menu.sync_status_changed(True)
99+ self.assertNotIn('paused', self.sync_menu.app.data)
100+ self.sync_menu.sync_status_changed(False)
101+ self.assertFalse(self.sync_menu._connected)
102+ self.assertTrue(self.sync_menu._ignore_status_event)
103+ self.assertTrue(self.sync_menu.app.data['paused'])
104\ No newline at end of file
105
106=== modified file 'tests/status/test_aggregator.py'
107--- tests/status/test_aggregator.py 2012-10-01 15:37:01 +0000
108+++ tests/status/test_aggregator.py 2012-10-10 15:00:35 +0000
109@@ -1330,6 +1330,36 @@
110 self.aggregator.register_progress_listener, [])
111 self.assertEqual(len(self.aggregator.progress_listeners), 0)
112
113+ def test_register_connection_listener(self):
114+ """Check that register listener handles properly additions."""
115+
116+ def fake_callback():
117+ """Do nothing."""
118+
119+ self.aggregator.register_connection_listener(fake_callback)
120+ self.assertEqual(len(self.aggregator.connection_listeners), 1)
121+
122+ def test_register_connection_listener_fail(self):
123+ """Check that register listener fails with not Callable objects."""
124+ self.assertRaises(TypeError,
125+ self.aggregator.register_connection_listener, [])
126+ self.assertEqual(len(self.aggregator.connection_listeners), 0)
127+
128+ def test_connection_notifications(self):
129+ """Check that the connection lister is notified."""
130+ data = {}
131+
132+ def fake_callback(status):
133+ """Register status."""
134+ data['status'] = status
135+
136+ self.aggregator.register_connection_listener(fake_callback)
137+ self.assertEqual(data, {})
138+ self.aggregator.connection_lost()
139+ self.assertFalse(data['status'])
140+ self.aggregator.connection_made()
141+ self.assertTrue(data['status'])
142+
143 def assertMiscCommandQueued(self, fc):
144 """Assert that some command was queued."""
145 self.assertEqual(len(self.aggregator.to_do), 1)
146
147=== modified file 'ubuntuone/platform/sync_menu/linux.py'
148--- ubuntuone/platform/sync_menu/linux.py 2012-10-09 14:31:11 +0000
149+++ ubuntuone/platform/sync_menu/linux.py 2012-10-10 15:00:35 +0000
150@@ -82,8 +82,9 @@
151 def __init__(self, status, syncdaemon_service):
152 """Initialize menu."""
153 self._syncdaemon_service = syncdaemon_service
154- self._paused = False
155+ self._connected = True
156 self.timer = None
157+ self._ignore_status_event = False
158 self.next_update = time.time()
159 self.root_menu = Dbusmenu.Menuitem()
160
161@@ -129,14 +130,23 @@
162 self.app.set_menu(self.server)
163 self.app.connect("notify::paused", self.change_sync_status)
164
165+ def sync_status_changed(self, status):
166+ """Listen to the changes for the sync status."""
167+ if status != self._connected:
168+ self._connected = status
169+ self._ignore_status_event = True
170+ self.app.set_paused(not self._connected)
171+
172 def change_sync_status(self, *args):
173 """Triggered when the sync status is changed fromm the menu."""
174- if self._paused:
175+ if self._ignore_status_event:
176+ self._ignore_status_event = False
177+ elif self._connected:
178+ self._syncdaemon_service.disconnect()
179+ self._connected = False
180+ else:
181 self._syncdaemon_service.connect()
182- self._paused = False
183- else:
184- self._syncdaemon_service.disconnect()
185- self._paused = True
186+ self._connected = True
187
188 def open_control_panel(self, *args):
189 """Open the Ubuntu One Control Panel."""
190
191=== modified file 'ubuntuone/status/aggregator.py'
192--- ubuntuone/status/aggregator.py 2012-10-01 15:37:01 +0000
193+++ ubuntuone/status/aggregator.py 2012-10-10 15:00:35 +0000
194@@ -616,6 +616,7 @@
195 self.progress = {}
196 self.to_do = {}
197 self.recent_transfers = deque(maxlen=5)
198+ self.connection_listeners = []
199 self.progress_listeners = []
200
201 def get_notification(self):
202@@ -654,6 +655,13 @@
203 else:
204 raise TypeError("Callable object expected.")
205
206+ def register_connection_listener(self, listener):
207+ """Register a callable object to be notified."""
208+ if isinstance(listener, Callable):
209+ self.connection_listeners.append(listener)
210+ else:
211+ raise TypeError("Callable object expected.")
212+
213 def get_discovery_message(self):
214 """Get the text for the discovery bubble."""
215 lines = []
216@@ -793,10 +801,14 @@
217 def connection_lost(self):
218 """The connection to the server was lost."""
219 self.file_discovery_bubble.connection_lost()
220+ for callback in self.connection_listeners:
221+ callback(False)
222
223 def connection_made(self):
224 """The connection to the server was made."""
225 self.file_discovery_bubble.connection_made()
226+ for callback in self.connection_listeners:
227+ callback(True)
228
229
230 class StatusFrontend(object):
231@@ -818,6 +830,8 @@
232 if self.syncdaemon_service is not None:
233 self.sync_menu = sync_menu.UbuntuOneSyncMenu(self,
234 self.syncdaemon_service)
235+ self.aggregator.register_connection_listener(
236+ self.sync_menu.sync_status_changed)
237 self.aggregator.register_progress_listener(
238 self.sync_menu.update_transfers)
239

Subscribers

People subscribed via source and target branches