Merge lp:~nataliabidart/ubuntuone-control-panel/simpler-devices-backend into lp:ubuntuone-control-panel
- simpler-devices-backend
- Merge into trunk
Proposed by
Natalia Bidart
Status: | Merged |
---|---|
Approved by: | Natalia Bidart |
Approved revision: | 168 |
Merged at revision: | 167 |
Proposed branch: | lp:~nataliabidart/ubuntuone-control-panel/simpler-devices-backend |
Merge into: | lp:ubuntuone-control-panel |
Diff against target: |
391 lines (+192/-55) 3 files modified
ubuntuone/controlpanel/backend.py (+86/-45) ubuntuone/controlpanel/tests/__init__.py (+28/-2) ubuntuone/controlpanel/tests/test_backend.py (+78/-8) |
To merge this branch: | bzr merge lp:~nataliabidart/ubuntuone-control-panel/simpler-devices-backend |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Roberto Alsina (community) | Approve | ||
John Lenton (community) | Approve | ||
Review via email: mp+65368@code.launchpad.net |
Commit message
- Backend now provides a simpler device query method: device_names_info (LP: #798413).
Description of the change
To post a comment you must log in.
Revision history for this message
John Lenton (chipaca) : | # |
review:
Approve
- 168. By Natalia Bidart
-
Merged trunk in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'ubuntuone/controlpanel/backend.py' |
2 | --- ubuntuone/controlpanel/backend.py 2011-06-17 21:11:45 +0000 |
3 | +++ ubuntuone/controlpanel/backend.py 2011-06-21 16:37:25 +0000 |
4 | @@ -46,6 +46,7 @@ |
5 | SHOW_ALL_NOTIFICATIONS_KEY = 'show_all_notifications' |
6 | SHARE_AUTOSUBSCRIBE_KEY = 'share_autosubscribe' |
7 | UDF_AUTOSUBSCRIBE_KEY = 'udf_autosubscribe' |
8 | +LIMIT_BW_KEY = 'limit_bandwidth' |
9 | UPLOAD_KEY = "max_upload_speed" |
10 | DOWNLOAD_KEY = "max_download_speed" |
11 | |
12 | @@ -191,17 +192,20 @@ |
13 | _set_status_changed_handler) |
14 | |
15 | @inlineCallbacks |
16 | - def _process_device_web_info(self, devices, enabled, limit_bw, limits, |
17 | - autoconnect, show_notifs, |
18 | - share_autosubscribe, udf_autosubscribe): |
19 | - """Return a lis of processed devices.""" |
20 | + def _process_device_web_info(self, devices, |
21 | + enabled=None, limit_bw=None, limits=None, autoconnect=None, |
22 | + show_notifs=None, share_autosubscribe=None, udf_autosubscribe=None): |
23 | + """Return a lis of processed devices. |
24 | + |
25 | + If all the file sync settings are None, do not attach that info. |
26 | + |
27 | + """ |
28 | result = [] |
29 | for d in devices: |
30 | di = {} |
31 | di["type"] = d["kind"] |
32 | di["name"] = d["description"] if d["description"] \ |
33 | else self.NAME_NOT_SET |
34 | - di["configurable"] = False |
35 | if di["type"] == DEVICE_TYPE_COMPUTER: |
36 | di["device_id"] = di["type"] + d["token"] |
37 | if di["type"] == DEVICE_TYPE_PHONE: |
38 | @@ -209,12 +213,22 @@ |
39 | |
40 | is_local = yield self.device_is_local(di["device_id"]) |
41 | di["is_local"] = is_local |
42 | + |
43 | + if is_local: # prepend the local device! |
44 | + result.insert(0, di) |
45 | + else: |
46 | + result.append(di) |
47 | + |
48 | + if enabled is None: |
49 | + # without knowing if file sync is enabled or not, |
50 | + # we can't add any extra info about the device. |
51 | + continue |
52 | + |
53 | # currently, only local devices are configurable. |
54 | - # eventually, more devices will be configurable. |
55 | di["configurable"] = is_local and enabled |
56 | |
57 | if di["configurable"]: |
58 | - di["limit_bandwidth"] = limit_bw |
59 | + di[LIMIT_BW_KEY] = limit_bw |
60 | di[AUTOCONNECT_KEY] = autoconnect |
61 | di[SHOW_ALL_NOTIFICATIONS_KEY] = show_notifs |
62 | di[SHARE_AUTOSUBSCRIBE_KEY] = share_autosubscribe |
63 | @@ -222,20 +236,41 @@ |
64 | di[UPLOAD_KEY] = limits["upload"] |
65 | di[DOWNLOAD_KEY] = limits["download"] |
66 | |
67 | - # date_added is not in the webservice yet (LP: #673668) |
68 | - # di["date_added"] = "" |
69 | - |
70 | - # missing values (LP: #673668) |
71 | - # di["available_services"] = "" |
72 | - # di["enabled_services"] = "" |
73 | - |
74 | - if is_local: # prepend the local device! |
75 | - result.insert(0, di) |
76 | - else: |
77 | - result.append(di) |
78 | - |
79 | returnValue(result) |
80 | |
81 | + @inlineCallbacks |
82 | + def _process_device_local_info(self, |
83 | + enabled=None, limit_bw=None, limits=None, autoconnect=None, |
84 | + show_notifs=None, share_autosubscribe=None, udf_autosubscribe=None): |
85 | + """Return the information for the local device. |
86 | + |
87 | + If all the file sync settings are None, do not attach that info. |
88 | + |
89 | + """ |
90 | + credentials = yield login_client.get_credentials() |
91 | + |
92 | + local_device = {} |
93 | + local_device["type"] = DEVICE_TYPE_COMPUTER |
94 | + local_device["name"] = credentials['name'] |
95 | + device_id = local_device["type"] + credentials["token"] |
96 | + local_device["device_id"] = device_id |
97 | + local_device["is_local"] = True |
98 | + |
99 | + if enabled is not None: |
100 | + local_device["configurable"] = enabled |
101 | + if local_device["configurable"]: |
102 | + local_device[LIMIT_BW_KEY] = limit_bw |
103 | + local_device[AUTOCONNECT_KEY] = autoconnect |
104 | + local_device[SHOW_ALL_NOTIFICATIONS_KEY] = show_notifs |
105 | + local_device[SHARE_AUTOSUBSCRIBE_KEY] = share_autosubscribe |
106 | + local_device[UDF_AUTOSUBSCRIBE_KEY] = udf_autosubscribe |
107 | + upload = limits["upload"] |
108 | + download = limits["download"] |
109 | + local_device[UPLOAD_KEY] = upload |
110 | + local_device[DOWNLOAD_KEY] = download |
111 | + |
112 | + returnValue(local_device) |
113 | + |
114 | def _process_path(self, path): |
115 | """Trim 'path' so the '~' is removed.""" |
116 | home = os.path.expanduser('~') |
117 | @@ -329,33 +364,39 @@ |
118 | result = yield self._process_device_web_info(devices, enabled, |
119 | limit_bw, limits, autoconnect, show_notifs, |
120 | share_autosubscribe, udf_autosubscribe) |
121 | + |
122 | if result is None: |
123 | - logger.info('devices_info: result is None after calling ' |
124 | - 'devices/ API, building the local device.') |
125 | - credentials = yield login_client.get_credentials() |
126 | - local_device = {} |
127 | - local_device["type"] = DEVICE_TYPE_COMPUTER |
128 | - local_device["name"] = credentials['name'] |
129 | - device_id = local_device["type"] + credentials["token"] |
130 | - local_device["device_id"] = device_id |
131 | - local_device["is_local"] = True |
132 | - local_device["configurable"] = enabled |
133 | - if local_device["configurable"]: |
134 | - local_device["limit_bandwidth"] = limit_bw |
135 | - local_device[AUTOCONNECT_KEY] = autoconnect |
136 | - local_device[SHOW_ALL_NOTIFICATIONS_KEY] = show_notifs |
137 | - local_device[SHARE_AUTOSUBSCRIBE_KEY] = share_autosubscribe |
138 | - local_device[UDF_AUTOSUBSCRIBE_KEY] = udf_autosubscribe |
139 | - upload = limits["upload"] |
140 | - download = limits["download"] |
141 | - local_device[UPLOAD_KEY] = upload |
142 | - local_device[DOWNLOAD_KEY] = download |
143 | - logger.debug('devices_info: local device built: %r.', local_device) |
144 | + local_device = yield self._process_device_local_info(enabled, |
145 | + limit_bw, limits, autoconnect, show_notifs, |
146 | + share_autosubscribe, udf_autosubscribe) |
147 | result = [local_device] |
148 | + |
149 | + logger.info('devices_info: result is %r', |
150 | + filter_field(result, field='device_id')) |
151 | + |
152 | + returnValue(result) |
153 | + |
154 | + @log_call(logger.debug) |
155 | + @process_unauthorized |
156 | + @inlineCallbacks |
157 | + def device_names_info(self): |
158 | + """Get the user devices info, only list names and kind.""" |
159 | + result = None |
160 | + try: |
161 | + devices = yield self.wc.call_api(DEVICES_API) |
162 | + except UnauthorizedError: |
163 | + raise |
164 | + except WebClientError: |
165 | + logger.exception('device_names_info: web client failure:') |
166 | else: |
167 | - logger.info('devices_info: result is not None after calling ' |
168 | - 'devices/ API: %r', |
169 | - filter_field(result, field='device_id')) |
170 | + result = yield self._process_device_web_info(devices) |
171 | + |
172 | + if result is None: |
173 | + local_device = yield self._process_device_local_info() |
174 | + result = [local_device] |
175 | + |
176 | + logger.info('device_names_info: result is %r', |
177 | + filter_field(result, field='device_id')) |
178 | |
179 | returnValue(result) |
180 | |
181 | @@ -379,8 +420,8 @@ |
182 | else: |
183 | yield sd_client.enable_show_all_notifications() |
184 | |
185 | - if is_local and "limit_bandwidth" in settings: |
186 | - if not settings["limit_bandwidth"]: |
187 | + if is_local and LIMIT_BW_KEY in settings: |
188 | + if not settings[LIMIT_BW_KEY]: |
189 | yield sd_client.disable_bandwidth_throttling() |
190 | else: |
191 | yield sd_client.enable_bandwidth_throttling() |
192 | |
193 | === modified file 'ubuntuone/controlpanel/tests/__init__.py' |
194 | --- ubuntuone/controlpanel/tests/__init__.py 2011-06-14 20:18:30 +0000 |
195 | +++ ubuntuone/controlpanel/tests/__init__.py 2011-06-21 16:37:25 +0000 |
196 | @@ -20,6 +20,10 @@ |
197 | |
198 | from ubuntuone.devtools.testcase import TestCase as BaseTestCase |
199 | |
200 | +from ubuntuone.controlpanel.backend import ( |
201 | + DEVICE_TYPE_COMPUTER, DEVICE_TYPE_PHONE, |
202 | +) |
203 | + |
204 | |
205 | TOKEN = {u'consumer_key': u'xQ7xDAz', |
206 | u'consumer_secret': u'KzCJWCTNbbntwfyCKKjomJDzlgqxLy', |
207 | @@ -141,19 +145,41 @@ |
208 | { |
209 | "device_id": "ComputerABCDEF01234token", |
210 | "name": "Ubuntu One @ darkstar", |
211 | - "type": "Computer", |
212 | + "type": DEVICE_TYPE_COMPUTER, |
213 | "is_local": False, |
214 | "configurable": False, |
215 | }, |
216 | { |
217 | "device_id": "Phone1000", |
218 | "name": "Nokia E65", |
219 | - "type": "Phone", |
220 | + "type": DEVICE_TYPE_PHONE, |
221 | "configurable": False, |
222 | "is_local": False, |
223 | }, |
224 | ] |
225 | |
226 | +# note that local computer should be first, do not change! |
227 | +EXPECTED_DEVICE_NAMES_INFO = [ |
228 | + { |
229 | + 'device_id': 'ComputerABCDEF01234-localtoken', |
230 | + 'name': 'Ubuntu One @ localhost', |
231 | + 'type': DEVICE_TYPE_COMPUTER, |
232 | + 'is_local': True, |
233 | + }, |
234 | + { |
235 | + 'device_id': 'ComputerABCDEF01234token', |
236 | + 'name': 'Ubuntu One @ darkstar', |
237 | + 'type': DEVICE_TYPE_COMPUTER, |
238 | + 'is_local': False, |
239 | + }, |
240 | + { |
241 | + 'device_id': 'Phone1000', |
242 | + 'name': 'Nokia E65', |
243 | + 'type': DEVICE_TYPE_PHONE, |
244 | + 'is_local': False, |
245 | + }, |
246 | +] |
247 | + |
248 | SAMPLE_FOLDERS = [ |
249 | {u'generation': u'2', |
250 | u'node_id': u'341da068-81d8-437a-8f75-5bb9d86455ba', |
251 | |
252 | === modified file 'ubuntuone/controlpanel/tests/test_backend.py' |
253 | --- ubuntuone/controlpanel/tests/test_backend.py 2011-06-17 21:11:45 +0000 |
254 | +++ ubuntuone/controlpanel/tests/test_backend.py 2011-06-21 16:37:25 +0000 |
255 | @@ -48,6 +48,7 @@ |
256 | EMPTY_DESCRIPTION_JSON, |
257 | EXPECTED_ACCOUNT_INFO, |
258 | EXPECTED_ACCOUNT_INFO_WITH_CURRENT_PLAN, |
259 | + EXPECTED_DEVICE_NAMES_INFO, |
260 | EXPECTED_DEVICES_INFO, |
261 | LOCAL_DEVICE, |
262 | ROOT_PATH, |
263 | @@ -440,7 +441,7 @@ |
264 | yield d |
265 | |
266 | @inlineCallbacks |
267 | - def test_devices_info_if_files_disable(self): |
268 | + def test_devices_info_if_files_disabled(self): |
269 | """The devices_info returns device only info if files is disabled.""" |
270 | yield self.be.disable_files() |
271 | status = yield self.be.file_sync_status() |
272 | @@ -485,6 +486,75 @@ |
273 | self.assertTrue(device_id_logged) |
274 | |
275 | @inlineCallbacks |
276 | + def test_device_names_info(self): |
277 | + """The device_names_info returns the correct info.""" |
278 | + self.be.wc.results[DEVICES_API] = SAMPLE_DEVICES_JSON |
279 | + result = yield self.be.device_names_info() |
280 | + self.assertEqual(result, EXPECTED_DEVICE_NAMES_INFO) |
281 | + |
282 | + @inlineCallbacks |
283 | + def test_device_names_info_fails(self): |
284 | + """The device_names_info method exercises its errback.""" |
285 | + def fail(*args, **kwargs): |
286 | + """Raise any error other than WebClientError.""" |
287 | + raise ValueError(args) |
288 | + |
289 | + self.patch(self.be.wc, 'call_api', fail) |
290 | + yield self.assertFailure(self.be.device_names_info(), ValueError) |
291 | + |
292 | + @inlineCallbacks |
293 | + def test_device_names_info_with_webclient_error(self): |
294 | + """The device_names_info returns local info if webclient error.""" |
295 | + MockWebClient.failure = 404 |
296 | + result = yield self.be.device_names_info() |
297 | + |
298 | + device = LOCAL_DEVICE.copy() |
299 | + device.pop('configurable', None) |
300 | + device.pop('limit_bandwidth', None) |
301 | + device.pop(backend.DOWNLOAD_KEY, None) |
302 | + device.pop(backend.UPLOAD_KEY, None) |
303 | + device.pop(backend.AUTOCONNECT_KEY, None) |
304 | + device.pop(backend.SHOW_ALL_NOTIFICATIONS_KEY, None) |
305 | + device.pop(backend.SHARE_AUTOSUBSCRIBE_KEY, None) |
306 | + device.pop(backend.UDF_AUTOSUBSCRIBE_KEY, None) |
307 | + self.assertEqual(result, [device]) |
308 | + self.assertTrue(self.memento.check_error('device_names_info', |
309 | + 'web client failure')) |
310 | + |
311 | + @inlineCallbacks |
312 | + def test_device_names_info_fails_with_unauthorized(self): |
313 | + """The device_names_info clears the credentials on unauthorized.""" |
314 | + MockWebClient.failure = 401 |
315 | + d = defer.Deferred() |
316 | + self.patch(backend.login_client, 'clear_credentials', |
317 | + lambda: d.callback('called')) |
318 | + yield self.assertFailure(self.be.device_names_info(), |
319 | + backend.UnauthorizedError) |
320 | + yield d |
321 | + |
322 | + @inlineCallbacks |
323 | + def test_device_names_info_when_token_name_is_empty(self): |
324 | + """The device_names_info can handle empty token names.""" |
325 | + self.be.wc.results[DEVICES_API] = EMPTY_DESCRIPTION_JSON |
326 | + result = yield self.be.device_names_info() |
327 | + expected = {'device_id': 'ComputerABCDEF01234token', |
328 | + 'is_local': False, 'name': self.be.NAME_NOT_SET, |
329 | + 'type': DEVICE_TYPE_COMPUTER} |
330 | + self.assertEqual(result, [expected]) |
331 | + |
332 | + @inlineCallbacks |
333 | + def test_device_names_info_does_not_log_device_id(self): |
334 | + """The device_names_info does not log the device_id.""" |
335 | + self.be.wc.results[DEVICES_API] = SAMPLE_DEVICES_JSON |
336 | + yield self.be.device_names_info() |
337 | + |
338 | + dids = (d['device_id'] for d in EXPECTED_DEVICES_INFO) |
339 | + device_id_logged = all(all(did not in r.getMessage() |
340 | + for r in self.memento.records) |
341 | + for did in dids) |
342 | + self.assertTrue(device_id_logged) |
343 | + |
344 | + @inlineCallbacks |
345 | def test_remove_device(self): |
346 | """The remove_device method calls the right api.""" |
347 | dtype, did = DEVICE_TYPE_COMPUTER, "SAMPLE-TOKEN" |
348 | @@ -549,10 +619,10 @@ |
349 | """The device settings are updated.""" |
350 | backend.sd_client.throttling = False |
351 | yield self.be.change_device_settings(self.local_token, |
352 | - {"limit_bandwidth": True}) |
353 | + {backend.LIMIT_BW_KEY: True}) |
354 | self.assertEqual(backend.sd_client.throttling, True) |
355 | yield self.be.change_device_settings(self.local_token, |
356 | - {"limit_bandwidth": False}) |
357 | + {backend.LIMIT_BW_KEY: False}) |
358 | self.assertEqual(backend.sd_client.throttling, False) |
359 | |
360 | @inlineCallbacks |
361 | @@ -560,7 +630,7 @@ |
362 | """The device settings are updated.""" |
363 | backend.sd_client.limits = {"download": -1, "upload": -1} |
364 | yield self.be.change_device_settings(self.local_token, |
365 | - {"max_upload_speed": 1111}) |
366 | + {backend.UPLOAD_KEY: 1111}) |
367 | self.assertEqual(backend.sd_client.limits["upload"], 1111) |
368 | self.assertEqual(backend.sd_client.limits["download"], -1) |
369 | |
370 | @@ -569,7 +639,7 @@ |
371 | """The device settings are updated.""" |
372 | backend.sd_client.limits = {"download": -1, "upload": -1} |
373 | yield self.be.change_device_settings(self.local_token, |
374 | - {"max_download_speed": 99}) |
375 | + {backend.DOWNLOAD_KEY: 99}) |
376 | self.assertEqual(backend.sd_client.limits["upload"], -1) |
377 | self.assertEqual(backend.sd_client.limits["download"], 99) |
378 | |
379 | @@ -579,9 +649,9 @@ |
380 | backend.sd_client.throttling = False |
381 | backend.sd_client.limits = {"download": -1, "upload": -1} |
382 | new_settings = { |
383 | - "max_download_speed": 99, |
384 | - "max_upload_speed": 99, |
385 | - "limit_bandwidth": True, |
386 | + backend.DOWNLOAD_KEY: 99, |
387 | + backend.UPLOAD_KEY: 99, |
388 | + backend.LIMIT_BW_KEY: True, |
389 | } |
390 | yield self.be.change_device_settings("wrong token!", new_settings) |
391 | self.assertEqual(backend.sd_client.throttling, False) |
+1