Merge lp:~nataliabidart/ubuntuone-control-panel/decouple-devices into lp:ubuntuone-control-panel

Proposed by Natalia Bidart
Status: Merged
Approved by: Natalia Bidart
Approved revision: 120
Merged at revision: 117
Proposed branch: lp:~nataliabidart/ubuntuone-control-panel/decouple-devices
Merge into: lp:ubuntuone-control-panel
Diff against target: 254 lines (+127/-54)
3 files modified
ubuntuone/controlpanel/backend.py (+75/-40)
ubuntuone/controlpanel/tests/__init__.py (+14/-12)
ubuntuone/controlpanel/tests/test_backend.py (+38/-2)
To merge this branch: bzr merge lp:~nataliabidart/ubuntuone-control-panel/decouple-devices
Reviewer Review Type Date Requested Status
Manuel de la Peña (community) Approve
Alejandro J. Cura (community) Approve
Review via email: mp+55345@code.launchpad.net

Commit message

- Decoupled device list retrieved from the web from the local settings retrieved from syncdaemon (LP: #720704).

Description of the change

This change decouples the retrieval of the device info list from the retrieval of local settings from syncdaemon.

To test this, you should:

killall ubuntuone-control-panel-backend

In two terminals, run:

DEBUG=True PYTHONPATH=. bin/ubuntuone-control-panel-backend
DEBUG=True PYTHONPATH=. bin/ubuntuone-control-panel-gtk

The first test would be disconnecting your network connection and going to the devices tab, you should see a single device (your local device).

The second test is more complex, since it requires that syncdaemon is disabled. Due to bug bug #744980, you need to:

* u1sdtool -q
* edit ~/.config/ubuntuone/syncdaemon.conf and set files_sync_enabled = False
* re-run the control panel backend and frontend
* go to the devices tab and confirm that the device list is retrieved, but no local settings are offered

To post a comment you must log in.
119. By Natalia Bidart

Fixed typo.

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

Nice branch!

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

Work fine with me to small remarks:

1. 'more the devices will be configurable.' - I guess is either 'more devices' or 'more of the devices'

2. I'm confused about this:
118 + show_notifs = bool_str(show_notifs)
119 + local_device["show_all_notifications"] = show_notifs

Why reassigning show_notifs and then storing it in the local_devices dict. What about just assigning it to the dict directly?

Since I don't consider the two above things to be lowering the quality of the code I approve and will trust the committer to the right thing.

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

> Work fine with me to small remarks:
>
> 1. 'more the devices will be configurable.' - I guess is either 'more devices'
> or 'more of the devices'

Fixed, thanks for the attention to detail!

> 2. I'm confused about this:
> 118 + show_notifs = bool_str(show_notifs)
> 119 + local_device["show_all_notifications"] = show_notifs
>
> Why reassigning show_notifs and then storing it in the local_devices dict.
> What about just assigning it to the dict directly?

Because otherwise it fells over the 80-columns width. I personally prefer assigning to a local variable that chopping off the line with = \.

120. By Natalia Bidart

Another typo, thanks mandel!

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-03-28 17:25:21 +0000
3+++ ubuntuone/controlpanel/backend.py 2011-03-29 17:12:42 +0000
4@@ -26,7 +26,7 @@
5 from ubuntuone.controlpanel import dbus_client
6 from ubuntuone.controlpanel import replication_client
7 from ubuntuone.controlpanel.logger import setup_logging, log_call
8-from ubuntuone.controlpanel.webclient import WebClient
9+from ubuntuone.controlpanel.webclient import WebClient, WebClientError
10
11
12 logger = setup_logging('backend')
13@@ -143,6 +143,49 @@
14 _set_status_changed_handler)
15
16 @inlineCallbacks
17+ def _process_device_web_info(self, devices, enabled, limit_bw, limits,
18+ show_notifs):
19+ """Return a lis of processed devices."""
20+ result = []
21+ for d in devices:
22+ di = {}
23+ di["type"] = d["kind"]
24+ di["name"] = d["description"]
25+ di["configurable"] = ''
26+ if di["type"] == DEVICE_TYPE_COMPUTER:
27+ di["device_id"] = di["type"] + d["token"]
28+ if di["type"] == DEVICE_TYPE_PHONE:
29+ di["device_id"] = di["type"] + str(d["id"])
30+
31+ is_local = yield self.device_is_local(di["device_id"])
32+ di["is_local"] = bool_str(is_local)
33+ # currently, only local devices are configurable.
34+ # eventually, more devices will be configurable.
35+ di["configurable"] = bool_str(is_local and enabled)
36+
37+ if bool(di["configurable"]):
38+ di["limit_bandwidth"] = bool_str(limit_bw)
39+ di["show_all_notifications"] = bool_str(show_notifs)
40+ upload = limits["upload"]
41+ download = limits["download"]
42+ di[UPLOAD_KEY] = str(upload)
43+ di[DOWNLOAD_KEY] = str(download)
44+
45+ # date_added is not in the webservice yet (LP: #673668)
46+ # di["date_added"] = ""
47+
48+ # missing values (LP: #673668)
49+ # di["available_services"] = ""
50+ # di["enabled_services"] = ""
51+
52+ if is_local: # prepend the local device!
53+ result.insert(0, di)
54+ else:
55+ result.append(di)
56+
57+ returnValue(result)
58+
59+ @inlineCallbacks
60 def get_token(self):
61 """Return the token from the credentials."""
62 credentials = yield dbus_client.get_credentials()
63@@ -188,47 +231,39 @@
64 @inlineCallbacks
65 def devices_info(self):
66 """Get the user devices info."""
67- result = []
68- limit_bw = yield dbus_client.bandwidth_throttling_enabled()
69- show_all_notif = yield dbus_client.show_all_notifications_enabled()
70- limits = yield dbus_client.get_throttling_limits()
71-
72- devices = yield self.wc.call_api(DEVICES_API)
73- for d in devices:
74- di = {}
75- di["type"] = d["kind"]
76- di["name"] = d["description"]
77- di["configurable"] = ''
78- if di["type"] == DEVICE_TYPE_COMPUTER:
79- di["device_id"] = di["type"] + d["token"]
80- if di["type"] == DEVICE_TYPE_PHONE:
81- di["device_id"] = di["type"] + str(d["id"])
82-
83- is_local = yield self.device_is_local(di["device_id"])
84- di["is_local"] = bool_str(is_local)
85- # currently, only local devices are configurable.
86- # eventually, more the devices will be configurable.
87- di["configurable"] = bool_str(is_local)
88-
89- if bool(di["configurable"]):
90- di["limit_bandwidth"] = bool_str(limit_bw)
91- di["show_all_notifications"] = bool_str(show_all_notif)
92+ result = limit_bw = limits = show_notifs = None
93+ enabled = yield dbus_client.files_sync_enabled()
94+ if enabled:
95+ limit_bw = yield dbus_client.bandwidth_throttling_enabled()
96+ show_notifs = yield dbus_client.show_all_notifications_enabled()
97+ limits = yield dbus_client.get_throttling_limits()
98+
99+ try:
100+ devices = yield self.wc.call_api(DEVICES_API)
101+ except WebClientError:
102+ logger.exception('devices_info: web client failure:')
103+ else:
104+ result = yield self._process_device_web_info(devices, enabled,
105+ limit_bw, limits,
106+ show_notifs)
107+ if result is None:
108+ credentials = yield dbus_client.get_credentials()
109+ local_device = {}
110+ local_device["type"] = DEVICE_TYPE_COMPUTER
111+ local_device["name"] = credentials['name']
112+ device_id = local_device["type"] + credentials["token"]
113+ local_device["device_id"] = device_id
114+ local_device["is_local"] = bool_str(True)
115+ local_device["configurable"] = bool_str(enabled)
116+ if bool(local_device["configurable"]):
117+ local_device["limit_bandwidth"] = bool_str(limit_bw)
118+ show_notifs = bool_str(show_notifs)
119+ local_device["show_all_notifications"] = show_notifs
120 upload = limits["upload"]
121 download = limits["download"]
122- di[UPLOAD_KEY] = str(upload)
123- di[DOWNLOAD_KEY] = str(download)
124-
125- # date_added is not in the webservice yet (LP: #673668)
126- # di["date_added"] = ""
127-
128- # missing values (LP: #673668)
129- # di["available_services"] = ""
130- # di["enabled_services"] = ""
131-
132- if is_local: # prepend the local device!
133- result.insert(0, di)
134- else:
135- result.append(di)
136+ local_device[UPLOAD_KEY] = str(upload)
137+ local_device[DOWNLOAD_KEY] = str(download)
138+ result = [local_device]
139
140 returnValue(result)
141
142
143=== modified file 'ubuntuone/controlpanel/tests/__init__.py'
144--- ubuntuone/controlpanel/tests/__init__.py 2011-03-02 19:54:09 +0000
145+++ ubuntuone/controlpanel/tests/__init__.py 2011-03-29 17:12:42 +0000
146@@ -23,7 +23,7 @@
147
148 TOKEN = {u'consumer_key': u'xQ7xDAz',
149 u'consumer_secret': u'KzCJWCTNbbntwfyCKKjomJDzlgqxLy',
150- u'token_name': u'test',
151+ u'name': u'Ubuntu One @ localhost',
152 u'token': u'ABCDEF01234-localtoken',
153 u'token_secret': u'qFYImEtlczPbsCnYyuwLoPDlPEnvNcIktZphPQklAWrvyfFMV'}
154
155@@ -110,19 +110,21 @@
156 ]
157 """
158
159+LOCAL_DEVICE = {
160+ 'is_local': 'True',
161+ 'configurable': 'True',
162+ 'device_id': 'ComputerABCDEF01234-localtoken',
163+ 'limit_bandwidth': '',
164+ 'show_all_notifications': 'True',
165+ 'max_download_speed': '-1',
166+ 'max_upload_speed': '-1',
167+ 'name': 'Ubuntu One @ localhost',
168+ 'type': 'Computer',
169+}
170+
171 # note that local computer should be first, do not change!
172 EXPECTED_DEVICES_INFO = [
173- {
174- 'is_local': 'True',
175- 'configurable': 'True',
176- 'device_id': 'ComputerABCDEF01234-localtoken',
177- 'limit_bandwidth': '',
178- 'show_all_notifications': 'True',
179- 'max_download_speed': '-1',
180- 'max_upload_speed': '-1',
181- 'name': 'Ubuntu One @ localhost',
182- 'type': 'Computer',
183- },
184+ LOCAL_DEVICE,
185 {
186 "device_id": "ComputerABCDEF01234token",
187 "name": "Ubuntu One @ darkstar",
188
189=== modified file 'ubuntuone/controlpanel/tests/test_backend.py'
190--- ubuntuone/controlpanel/tests/test_backend.py 2011-03-28 16:23:59 +0000
191+++ ubuntuone/controlpanel/tests/test_backend.py 2011-03-29 17:12:42 +0000
192@@ -44,6 +44,7 @@
193 EXPECTED_ACCOUNT_INFO,
194 EXPECTED_ACCOUNT_INFO_WITH_CURRENT_PLAN,
195 EXPECTED_DEVICES_INFO,
196+ LOCAL_DEVICE,
197 ROOT_PATH,
198 SAMPLE_ACCOUNT_NO_CURRENT_PLAN,
199 SAMPLE_ACCOUNT_WITH_CURRENT_PLAN,
200@@ -340,9 +341,43 @@
201 @inlineCallbacks
202 def test_devices_info_fails(self):
203 """The devices_info method exercises its errback."""
204+ def fail(*args, **kwargs):
205+ """Raise any error other than WebClientError."""
206+ raise ValueError(args)
207+
208+ self.patch(self.be.wc, 'call_api', fail)
209+ yield self.assertFailure(self.be.devices_info(), ValueError)
210+
211+ @inlineCallbacks
212+ def test_devices_info_with_webclient_error(self):
213+ """The devices_info returns local info if webclient error."""
214 # pylint: disable=E1101
215 self.be.wc.failure = 404
216- yield self.assertFailure(self.be.devices_info(), WebClientError)
217+ result = yield self.be.devices_info()
218+
219+ self.assertEqual(result, [LOCAL_DEVICE])
220+ self.assertTrue(self.memento.check_error('devices_info',
221+ 'web client failure'))
222+
223+ @inlineCallbacks
224+ def test_devices_info_if_files_disable(self):
225+ """The devices_info returns device only info if files is disabled."""
226+ yield self.be.disable_files()
227+ status = yield self.be.file_sync_status()
228+ assert status['status'] == backend.FILE_SYNC_DISABLED, status
229+
230+ # pylint: disable=E1101
231+ self.be.wc.results[DEVICES_API] = SAMPLE_DEVICES_JSON
232+ result = yield self.be.devices_info()
233+
234+ expected = EXPECTED_DEVICES_INFO[:]
235+ for device in expected:
236+ device.pop('limit_bandwidth', None)
237+ device.pop('max_download_speed', None)
238+ device.pop('max_upload_speed', None)
239+ device.pop('show_all_notifications', None)
240+ device['configurable'] = ''
241+ self.assertEqual(result, expected)
242
243 @inlineCallbacks
244 def test_remove_device(self):
245@@ -372,7 +407,8 @@
246 """The remove_device method fails as expected."""
247 # pylint: disable=E1101
248 self.be.wc.failure = 404
249- yield self.assertFailure(self.be.devices_info(), WebClientError)
250+ yield self.assertFailure(self.be.remove_device(self.local_token),
251+ WebClientError)
252
253 @inlineCallbacks
254 def test_change_show_all_notifications(self):

Subscribers

People subscribed via source and target branches