Merge lp:~chipaca/ubuntuone-client/devices-tab into lp:ubuntuone-client
- devices-tab
- Merge into trunk
Status: | Superseded |
---|---|
Proposed branch: | lp:~chipaca/ubuntuone-client/devices-tab |
Merge into: | lp:ubuntuone-client |
Diff against target: |
917 lines (+514/-216) 3 files modified
bin/ubuntuone-preferences (+373/-163) tests/test_preferences.py (+139/-53) ubuntuone/syncdaemon/dbus_interface.py (+2/-0) |
To merge this branch: | bzr merge lp:~chipaca/ubuntuone-client/devices-tab |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Eric Casteleijn (community) | Needs Fixing | ||
Review via email: mp+20608@code.launchpad.net |
This proposal has been superseded by a proposal from 2010-03-05.
Commit message
Add other devices and management ui to Devices tab
Description of the change
Eric Casteleijn (thisfred) wrote : | # |
Eric Casteleijn (thisfred) wrote : | # |
=======
[ERROR]: tests.test_
Traceback (most recent call last):
File "/home/
result = test_method()
File "/home/
dialog = self.u1prefs.
File "/home/
self.
File "/home/
self.
File "/home/
token = get_access_token()
File "/home/
'oauth-
gnomekeyring.
=======
[ERROR]: tests.test_
Traceback (most recent call last):
File "/home/
result = test_method()
File "/home/
dialog = self.u1prefs.
File "/home/
self.
File "/home/
self.
File "/home/
token = get_access_token()
File "/home/
'oauth-
gnomekeyring.
=======
[ERROR]: tests.test_
Traceback (most recent call last):
File "/home/
result = test_method()
File "/home/
dialog = self.u1prefs.
File "/home/
self.
File "/home/
self.
File "/home/
token = get_access_token()
File "/home/
'oauth-
- 403. By John Lenton
-
merged with trunk
- 404. By John Lenton
-
merged with trunk (again)
- 405. By John Lenton
-
minor refactoring (to get tests working again) and tests. Still TODO: test the REST calls are done
- 406. By John Lenton
-
worked around a bug in the rest api
- 407. By John Lenton
-
fixed issues raised by dobey
- 408. By John Lenton
-
fixed issues raised by nessa
- 409. By John Lenton
-
more changed by dobey (and some older ones)
Unmerged revisions
Preview Diff
1 | === modified file 'bin/ubuntuone-preferences' | |||
2 | --- bin/ubuntuone-preferences 2010-03-01 22:10:22 +0000 | |||
3 | +++ bin/ubuntuone-preferences 2010-03-05 17:04:28 +0000 | |||
4 | @@ -23,6 +23,7 @@ | |||
5 | 23 | import pygtk | 23 | import pygtk |
6 | 24 | pygtk.require('2.0') | 24 | pygtk.require('2.0') |
7 | 25 | import gobject | 25 | import gobject |
8 | 26 | import glib | ||
9 | 26 | import gtk | 27 | import gtk |
10 | 27 | import os | 28 | import os |
11 | 28 | import gettext | 29 | import gettext |
12 | @@ -32,6 +33,11 @@ | |||
13 | 32 | from oauth import oauth | 33 | from oauth import oauth |
14 | 33 | from ubuntuone import clientdefs | 34 | from ubuntuone import clientdefs |
15 | 34 | from ubuntuone.syncdaemon.tools import SyncDaemonTool | 35 | from ubuntuone.syncdaemon.tools import SyncDaemonTool |
16 | 36 | from ubuntuone.syncdaemon.logger import LOGFOLDER | ||
17 | 37 | |||
18 | 38 | import logging | ||
19 | 39 | import sys | ||
20 | 40 | import httplib, urlparse, socket | ||
21 | 35 | 41 | ||
22 | 36 | import dbus.service | 42 | import dbus.service |
23 | 37 | from ConfigParser import ConfigParser | 43 | from ConfigParser import ConfigParser |
24 | @@ -39,6 +45,11 @@ | |||
25 | 39 | from dbus.mainloop.glib import DBusGMainLoop | 45 | from dbus.mainloop.glib import DBusGMainLoop |
26 | 40 | from xdg.BaseDirectory import xdg_config_home | 46 | from xdg.BaseDirectory import xdg_config_home |
27 | 41 | 47 | ||
28 | 48 | logging.basicConfig( | ||
29 | 49 | filename=os.path.join(LOGFOLDER, 'u1-prefs.log'), | ||
30 | 50 | level=logging.DEBUG, | ||
31 | 51 | format="%(asctime)s - %(name)s - %(levelname)s - %(message)s") | ||
32 | 52 | logger = logging.getLogger("ubuntuone-preferences") | ||
33 | 42 | DBusGMainLoop(set_as_default=True) | 53 | DBusGMainLoop(set_as_default=True) |
34 | 43 | 54 | ||
35 | 44 | _ = gettext.gettext | 55 | _ = gettext.gettext |
36 | @@ -65,10 +76,358 @@ | |||
37 | 65 | pass | 76 | pass |
38 | 66 | 77 | ||
39 | 67 | 78 | ||
40 | 79 | def get_access_token(keyring): | ||
41 | 80 | items = [] | ||
42 | 81 | items = keyring.find_items_sync( | ||
43 | 82 | keyring.ITEM_GENERIC_SECRET, | ||
44 | 83 | {'ubuntuone-realm': "https://ubuntuone.com", | ||
45 | 84 | 'oauth-consumer-key': 'ubuntuone'}) | ||
46 | 85 | secret = items[0].secret | ||
47 | 86 | return oauth.OAuthToken.from_string(secret) | ||
48 | 87 | |||
49 | 88 | |||
50 | 89 | class DevicesWidget(gtk.Table): | ||
51 | 90 | """ | ||
52 | 91 | the Devices tab | ||
53 | 92 | """ | ||
54 | 93 | def __init__(self, | ||
55 | 94 | bus, | ||
56 | 95 | keyring=gnomekeyring, | ||
57 | 96 | realm='https://ubuntuone.com', | ||
58 | 97 | consumer_key='ubuntuone', | ||
59 | 98 | url='https://one.ubuntu.com/api/1.0/devices/'): | ||
60 | 99 | super(DevicesWidget, self).__init__(rows=2, columns=3) | ||
61 | 100 | self.bus = bus | ||
62 | 101 | self.keyring = keyring | ||
63 | 102 | self.sdtool = SyncDaemonTool(bus) | ||
64 | 103 | self.set_border_width(6) | ||
65 | 104 | self.set_row_spacings(6) | ||
66 | 105 | self.set_col_spacings(6) | ||
67 | 106 | self.devices = None | ||
68 | 107 | self.realm = realm | ||
69 | 108 | self.consumer_key = consumer_key | ||
70 | 109 | self.base_url = url | ||
71 | 110 | self.conn = None | ||
72 | 111 | self.consumer = None | ||
73 | 112 | self.table_widgets = [] | ||
74 | 113 | |||
75 | 114 | self.connected = None # i.e. unknown | ||
76 | 115 | self.conn_btn = None | ||
77 | 116 | self.up_spin = None | ||
78 | 117 | self.dn_spin = None | ||
79 | 118 | self.bw_chk = None | ||
80 | 119 | self.bw_limited = False | ||
81 | 120 | self.up_limit = 2097152 | ||
82 | 121 | self.dn_limit = 2097152 | ||
83 | 122 | |||
84 | 123 | self._update_id = 0 | ||
85 | 124 | |||
86 | 125 | self.status_label = gtk.Label("Please wait...") | ||
87 | 126 | self.attach(self.status_label, 0, 3, 2, 3) | ||
88 | 127 | |||
89 | 128 | self.description = gtk.Label("The devices connected to with your personal cloud network are listed below") | ||
90 | 129 | self.description.set_alignment(0., .5) | ||
91 | 130 | self.description.set_line_wrap(True) | ||
92 | 131 | self.attach(self.description, 0, 3, 0, 1, xpadding=12, ypadding=12) | ||
93 | 132 | |||
94 | 133 | def update_bw_settings(self): | ||
95 | 134 | """ | ||
96 | 135 | Push the bandwidth settings at syncdaemon | ||
97 | 136 | """ | ||
98 | 137 | try: | ||
99 | 138 | client = self.bus.get_object(DBUS_IFACE_NAME, "/config", | ||
100 | 139 | follow_name_owner_changes=True) | ||
101 | 140 | iface = dbus.Interface(client, DBUS_IFACE_CONFIG_NAME) | ||
102 | 141 | iface.set_throttling_limits(self.dn_limit, self.up_limit, | ||
103 | 142 | reply_handler=dbus_async, | ||
104 | 143 | error_handler=self.error) | ||
105 | 144 | if self.bw_limited: | ||
106 | 145 | iface.enable_bandwidth_throttling(reply_handler=dbus_async, | ||
107 | 146 | error_handler=self.error) | ||
108 | 147 | else: | ||
109 | 148 | iface.disable_bandwidth_throttling(reply_handler=dbus_async, | ||
110 | 149 | error_handler=self.error) | ||
111 | 150 | except DBusException, e: | ||
112 | 151 | self.error(str(e)) | ||
113 | 152 | |||
114 | 153 | def handle_bw_controls_changed(self, *a): | ||
115 | 154 | """ | ||
116 | 155 | Sync the bandwidth throttling model with the view. | ||
117 | 156 | |||
118 | 157 | Start a timer to sync with syncdaemon too. | ||
119 | 158 | """ | ||
120 | 159 | # Remove the timeout ... | ||
121 | 160 | if self._update_id != 0: | ||
122 | 161 | gobject.source_remove(self._update_id) | ||
123 | 162 | |||
124 | 163 | # sync the model ... | ||
125 | 164 | self.bw_limited = self.bw_chk.get_active() | ||
126 | 165 | self.up_limit = self.up_spin.get_value_as_int() * 1024 | ||
127 | 166 | self.dn_limit = self.dn_spin.get_value_as_int() * 1024 | ||
128 | 167 | |||
129 | 168 | # ... and add the timeout back | ||
130 | 169 | self._update_id = gobject.timeout_add_seconds( | ||
131 | 170 | 1, self.update_bw_settings) | ||
132 | 171 | |||
133 | 172 | def handle_bw_checkbox_toggled(self, checkbox, *widgets): | ||
134 | 173 | """ | ||
135 | 174 | Callback for the bandwidth togglebutton | ||
136 | 175 | """ | ||
137 | 176 | active = checkbox.get_active() | ||
138 | 177 | for widget in widgets: | ||
139 | 178 | widget.set_sensitive(active) | ||
140 | 179 | self.handle_bw_controls_changed() | ||
141 | 180 | |||
142 | 181 | def handle_limits(self, limits): | ||
143 | 182 | """ | ||
144 | 183 | Callback for when syncdaemon tells us its throttling limits | ||
145 | 184 | """ | ||
146 | 185 | self.up_limit = int(limits['upload']) | ||
147 | 186 | self.dn_limit = int(limits['download']) | ||
148 | 187 | if self.up_spin is not None and self.dn_spin is not None: | ||
149 | 188 | self.up_spin.set_value(self.up_limit / 1024) | ||
150 | 189 | self.dn_spin.set_value(self.dn_limit / 1024) | ||
151 | 190 | |||
152 | 191 | def handle_throttling_enabled(self, enabled): | ||
153 | 192 | """ | ||
154 | 193 | Callback for when syncdaemon tells us whether throttling is enabled | ||
155 | 194 | """ | ||
156 | 195 | self.bw_limited = enabled | ||
157 | 196 | if self.bw_chk is not None: | ||
158 | 197 | self.bw_chk.set_active(enabled) | ||
159 | 198 | |||
160 | 199 | def handle_state_change(self, new_state): | ||
161 | 200 | """ | ||
162 | 201 | Callback for when syncdaemon's state changes | ||
163 | 202 | """ | ||
164 | 203 | if new_state['is_error']: | ||
165 | 204 | # this syncdaemon isn't going to connect no more | ||
166 | 205 | self.connected = None | ||
167 | 206 | else: | ||
168 | 207 | self.connected = new_state['is_connected'] | ||
169 | 208 | if self.conn_btn is not None: | ||
170 | 209 | if self.connected: | ||
171 | 210 | self.conn_btn.set_label(_("_Disconnect")) | ||
172 | 211 | else: | ||
173 | 212 | self.conn_btn.set_label(_("_Connect")) | ||
174 | 213 | if self.connected is None: | ||
175 | 214 | self.conn_btn.set_sensitive(False) | ||
176 | 215 | else: | ||
177 | 216 | self.conn_btn.set_sensitive(True) | ||
178 | 217 | |||
179 | 218 | def error(self, msg): | ||
180 | 219 | """ | ||
181 | 220 | Clear the table and show the error message in its place. | ||
182 | 221 | |||
183 | 222 | This might be better as an error dialo. | ||
184 | 223 | """ | ||
185 | 224 | self.clear_devices_view() | ||
186 | 225 | self.status_label.set_markup("<b>Error:</b> %s" % msg) | ||
187 | 226 | |||
188 | 227 | def request(self, path='', method='GET'): | ||
189 | 228 | """ | ||
190 | 229 | Helper that makes an oauth-wrapped rest request. | ||
191 | 230 | |||
192 | 231 | XXX duplication with request_REST_info (but this one should be async) | ||
193 | 232 | """ | ||
194 | 233 | url = self.base_url + path | ||
195 | 234 | |||
196 | 235 | token = get_access_token(self.keyring) | ||
197 | 236 | |||
198 | 237 | oauth_request = oauth.OAuthRequest.from_consumer_and_token( | ||
199 | 238 | http_url=url, | ||
200 | 239 | http_method=method, | ||
201 | 240 | oauth_consumer=self.consumer, | ||
202 | 241 | token=token, | ||
203 | 242 | parameters='') | ||
204 | 243 | oauth_request.sign_request(oauth.OAuthSignatureMethod_HMAC_SHA1(), | ||
205 | 244 | self.consumer, token) | ||
206 | 245 | |||
207 | 246 | scheme, netloc, path, query, fragment = urlparse.urlsplit(url) | ||
208 | 247 | |||
209 | 248 | conn = httplib.HTTPSConnection(netloc) | ||
210 | 249 | try: | ||
211 | 250 | conn.request(method, path, headers=oauth_request.to_header()) | ||
212 | 251 | except socket.error: | ||
213 | 252 | return None | ||
214 | 253 | return conn | ||
215 | 254 | |||
216 | 255 | def get_devices(self): | ||
217 | 256 | """ | ||
218 | 257 | Ask the server for a list of devices, and hook up | ||
219 | 258 | parse_devices to run on the result (when it gets here). | ||
220 | 259 | """ | ||
221 | 260 | try: | ||
222 | 261 | token = get_access_token(self.keyring) | ||
223 | 262 | except gnomekeyring.NoMatchError: | ||
224 | 263 | self.error("No token in the keyring") | ||
225 | 264 | self.devices = [] | ||
226 | 265 | else: | ||
227 | 266 | self.consumer = oauth.OAuthConsumer("ubuntuone", "hammertime") | ||
228 | 267 | |||
229 | 268 | self.conn = self.request() | ||
230 | 269 | if self.conn is None: | ||
231 | 270 | self.clear_devices_view() | ||
232 | 271 | self.error('Unable to connect') | ||
233 | 272 | else: | ||
234 | 273 | glib.io_add_watch( | ||
235 | 274 | self.conn.sock, | ||
236 | 275 | glib.IO_IN | glib.IO_PRI | glib.IO_ERR | glib.IO_HUP, | ||
237 | 276 | self.parse_devices) | ||
238 | 277 | |||
239 | 278 | def parse_devices(self, *a): | ||
240 | 279 | """ | ||
241 | 280 | Parse the list of devices, and hook up list_devices if it worked | ||
242 | 281 | """ | ||
243 | 282 | response = self.conn.getresponse() # shouldn't block | ||
244 | 283 | if response.status == 200: | ||
245 | 284 | response = response.read() # neither shouold this | ||
246 | 285 | self.devices = simplejson.loads(response) | ||
247 | 286 | gobject.idle_add(self.list_devices) | ||
248 | 287 | else: | ||
249 | 288 | self.clear_devices_view() | ||
250 | 289 | self.error(response.reason) | ||
251 | 290 | return False | ||
252 | 291 | |||
253 | 292 | def clear_devices_view(self): | ||
254 | 293 | """ | ||
255 | 294 | Clear out all the widgets except from the table, the | ||
256 | 295 | description and the status_label | ||
257 | 296 | """ | ||
258 | 297 | for i in self.get_children(): | ||
259 | 298 | if i not in (self.description, self.status_label): | ||
260 | 299 | i.destroy() | ||
261 | 300 | self.conn_btn = None | ||
262 | 301 | self.up_spin = None | ||
263 | 302 | self.dn_spin = None | ||
264 | 303 | self.bw_chk = None | ||
265 | 304 | |||
266 | 305 | def list_devices(self): | ||
267 | 306 | """ | ||
268 | 307 | Populate the table with the list of devices. | ||
269 | 308 | |||
270 | 309 | If the list of devices is empty, make a fake one that refers | ||
271 | 310 | to the local machine (to get the connect/restart buttons). | ||
272 | 311 | """ | ||
273 | 312 | self.resize(len(self.devices)+1, 3) | ||
274 | 313 | |||
275 | 314 | self.clear_devices_view() | ||
276 | 315 | |||
277 | 316 | token = get_access_token(self.keyring) | ||
278 | 317 | |||
279 | 318 | if not self.devices: | ||
280 | 319 | # a stopgap device so you can at least try to connect | ||
281 | 320 | self.devices = [{'kind': 'Computer', | ||
282 | 321 | 'description': _("<LOCAL MACHINE>"), | ||
283 | 322 | 'token': token.key, | ||
284 | 323 | 'FAKE': 'YES'}] | ||
285 | 324 | |||
286 | 325 | name_label = gtk.Label() | ||
287 | 326 | name_label.set_markup("<b>Name</b>") | ||
288 | 327 | name_label.set_alignment(0., .5) | ||
289 | 328 | self.attach(name_label, 1, 2, 1, 2) | ||
290 | 329 | self.status_label.set_label("") | ||
291 | 330 | |||
292 | 331 | i = 1 | ||
293 | 332 | for row in self.devices: | ||
294 | 333 | i += 1 | ||
295 | 334 | img = gtk.Image() | ||
296 | 335 | img.set_from_icon_name(row['kind'].lower(), gtk.ICON_SIZE_DND) | ||
297 | 336 | desc = gtk.Label(row['description']) | ||
298 | 337 | desc.set_alignment(0., .5) | ||
299 | 338 | self.attach(img, 0, 1, i, i+1) | ||
300 | 339 | self.attach(desc, 1, 2, i, i+1) | ||
301 | 340 | if 'FAKE' not in row: | ||
302 | 341 | # we don't include the "Remove" button for the fake entry :) | ||
303 | 342 | butn = gtk.Button('Remove') | ||
304 | 343 | butn.connect('clicked', self.remove, | ||
305 | 344 | row['kind'], row['token']) | ||
306 | 345 | self.attach(butn, 2, 3, i, i+1, xoptions=0, yoptions=0) | ||
307 | 346 | if row['token'] == token.key: | ||
308 | 347 | self.bw_chk = ck_btn = gtk.CheckButton( | ||
309 | 348 | _("_Limit Bandwidth Usage")) | ||
310 | 349 | ck_btn.set_active(self.bw_limited) | ||
311 | 350 | up_lbl = gtk.Label(_("Upload (kB/s):")) | ||
312 | 351 | up_lbl.set_alignment(0., .5) | ||
313 | 352 | adj = gtk.Adjustment(value=self.up_limit/1024., | ||
314 | 353 | lower=0.0, upper=4096.0, | ||
315 | 354 | step_incr=1.0, page_incr=16.0) | ||
316 | 355 | self.up_spin = up_btn = gtk.SpinButton(adj) | ||
317 | 356 | up_btn.connect("value-changed", self.handle_bw_controls_changed) | ||
318 | 357 | dn_lbl = gtk.Label(_("Download (kB/s):")) | ||
319 | 358 | dn_lbl.set_alignment(0., .5) | ||
320 | 359 | adj = gtk.Adjustment(value=self.dn_limit/1024., | ||
321 | 360 | lower=0.0, upper=4096.0, | ||
322 | 361 | step_incr=1.0, page_incr=16.0) | ||
323 | 362 | self.dn_spin = dn_btn = gtk.SpinButton(adj) | ||
324 | 363 | dn_btn.connect("value-changed", self.handle_bw_controls_changed) | ||
325 | 364 | ck_btn.connect('toggled', self.handle_bw_checkbox_toggled, | ||
326 | 365 | up_lbl, up_btn, dn_lbl, dn_btn) | ||
327 | 366 | self.handle_bw_checkbox_toggled(ck_btn, | ||
328 | 367 | up_lbl, up_btn, dn_lbl, dn_btn) | ||
329 | 368 | |||
330 | 369 | self.conn_btn = gtk.Button(_('_Connect')) | ||
331 | 370 | if self.connected is None: | ||
332 | 371 | self.conn_btn.set_sensitive(False) | ||
333 | 372 | elif self.connected: | ||
334 | 373 | self.conn_btn.set_label(_('_Disconnect')) | ||
335 | 374 | self.conn_btn.connect('clicked', self.handle_connect_button) | ||
336 | 375 | restart_btn = gtk.Button(_('_Restart')) | ||
337 | 376 | restart_btn.connect('clicked', self.handle_restart_button) | ||
338 | 377 | btn_box = gtk.HButtonBox() | ||
339 | 378 | btn_box.add(self.conn_btn) | ||
340 | 379 | btn_box.add(restart_btn) | ||
341 | 380 | |||
342 | 381 | i += 1 | ||
343 | 382 | self.attach(ck_btn, 1, 3, i, i+1) | ||
344 | 383 | i += 1 | ||
345 | 384 | self.attach(up_lbl, 1, 2, i, i+1) | ||
346 | 385 | self.attach(up_btn, 2, 3, i, i+1) | ||
347 | 386 | i += 1 | ||
348 | 387 | self.attach(dn_lbl, 1, 2, i, i+1) | ||
349 | 388 | self.attach(dn_btn, 2, 3, i, i+1) | ||
350 | 389 | i += 1 | ||
351 | 390 | self.attach(btn_box, 1, 3, i, i+1) | ||
352 | 391 | i += 2 | ||
353 | 392 | self.show_all() | ||
354 | 393 | |||
355 | 394 | def handle_connect_button(self, *a): | ||
356 | 395 | """ | ||
357 | 396 | Callback for the Connect/Disconnect button | ||
358 | 397 | """ | ||
359 | 398 | self.conn_btn.set_sensitive(False) | ||
360 | 399 | if self.connected: | ||
361 | 400 | d = self.sdtool.disconnect() | ||
362 | 401 | else: | ||
363 | 402 | d = self.sdtool.connect() | ||
364 | 403 | |||
365 | 404 | def handle_restart_button(self, *a): | ||
366 | 405 | """ | ||
367 | 406 | Callback for the Restart button | ||
368 | 407 | """ | ||
369 | 408 | self.sdtool.quit().addCallbacks(lambda _: self.sdtool.start()) | ||
370 | 409 | |||
371 | 410 | def remove(self, button, kind, token): | ||
372 | 411 | """ | ||
373 | 412 | Callback for the Remove button. Starts an async request to | ||
374 | 413 | remove a device. | ||
375 | 414 | """ | ||
376 | 415 | self.conn = self.request('remove/%s/%s' % (kind.lower(), token)) | ||
377 | 416 | if self.conn is None: | ||
378 | 417 | self.clear_devices_view() | ||
379 | 418 | self.error('Unable to connect') | ||
380 | 419 | else: | ||
381 | 420 | glib.io_add_watch( | ||
382 | 421 | self.conn.sock, | ||
383 | 422 | glib.IO_IN | glib.IO_PRI | glib.IO_ERR | glib.IO_HUP, | ||
384 | 423 | self.parse_devices) | ||
385 | 424 | |||
386 | 425 | |||
387 | 426 | |||
388 | 68 | class UbuntuOneDialog(gtk.Dialog): | 427 | class UbuntuOneDialog(gtk.Dialog): |
389 | 69 | """Preferences dialog.""" | 428 | """Preferences dialog.""" |
390 | 70 | 429 | ||
392 | 71 | def __init__(self, config=None, *args, **kw): | 430 | def __init__(self, config=None, keyring=gnomekeyring, *args, **kw): |
393 | 72 | """Initializes our config dialog.""" | 431 | """Initializes our config dialog.""" |
394 | 73 | super(UbuntuOneDialog, self).__init__(*args, **kw) | 432 | super(UbuntuOneDialog, self).__init__(*args, **kw) |
395 | 74 | self.set_title(_("Ubuntu One Preferences")) | 433 | self.set_title(_("Ubuntu One Preferences")) |
396 | @@ -80,12 +439,8 @@ | |||
397 | 80 | self.connect("close", self.__handle_response, gtk.RESPONSE_CLOSE) | 439 | self.connect("close", self.__handle_response, gtk.RESPONSE_CLOSE) |
398 | 81 | self.connect("response", self.__handle_response) | 440 | self.connect("response", self.__handle_response) |
399 | 82 | 441 | ||
400 | 83 | self.bw_enabled = False | ||
401 | 84 | self.up_limit = 2097152 | ||
402 | 85 | self.dn_limit = 2097152 | ||
403 | 86 | |||
404 | 87 | self.__bus = dbus.SessionBus() | 442 | self.__bus = dbus.SessionBus() |
406 | 88 | self.keyring = gnomekeyring | 443 | self.keyring = keyring |
407 | 89 | 444 | ||
408 | 90 | self.__bus.add_signal_receiver( | 445 | self.__bus.add_signal_receiver( |
409 | 91 | handler_function=self.__got_state, | 446 | handler_function=self.__got_state, |
410 | @@ -108,15 +463,13 @@ | |||
411 | 108 | # Timeout ID to avoid spamming DBus from spinbutton changes | 463 | # Timeout ID to avoid spamming DBus from spinbutton changes |
412 | 109 | self.__update_id = 0 | 464 | self.__update_id = 0 |
413 | 110 | 465 | ||
414 | 111 | # Connectivity status | ||
415 | 112 | self.connected = False | ||
416 | 113 | |||
417 | 114 | # SD Tool object | 466 | # SD Tool object |
418 | 115 | self.sdtool = SyncDaemonTool(self.__bus) | 467 | self.sdtool = SyncDaemonTool(self.__bus) |
419 | 116 | self.sdtool.get_status().addCallbacks(lambda _: self.__got_state, | 468 | self.sdtool.get_status().addCallbacks(lambda _: self.__got_state, |
420 | 117 | self.__sd_error) | 469 | self.__sd_error) |
421 | 118 | # Build the dialog | 470 | # Build the dialog |
422 | 119 | self.__construct() | 471 | self.__construct() |
423 | 472 | logger.debug("starting") | ||
424 | 120 | 473 | ||
425 | 121 | def quit(self): | 474 | def quit(self): |
426 | 122 | """Exit the main loop.""" | 475 | """Exit the main loop.""" |
427 | @@ -132,97 +485,23 @@ | |||
428 | 132 | 485 | ||
429 | 133 | def __got_state(self, state): | 486 | def __got_state(self, state): |
430 | 134 | """Got the state of syncdaemon.""" | 487 | """Got the state of syncdaemon.""" |
437 | 135 | self.connected = bool(state['is_connected']) | 488 | self.devices.handle_state_change(state) |
432 | 136 | if self.connected: | ||
433 | 137 | self.conn_btn.set_label(_("Disconnect")) | ||
434 | 138 | else: | ||
435 | 139 | self.conn_btn.set_label(_("Connect")) | ||
436 | 140 | self.conn_btn.set_sensitive(True) | ||
438 | 141 | 489 | ||
439 | 142 | def __got_limits(self, limits): | 490 | def __got_limits(self, limits): |
440 | 143 | """Got the throttling limits.""" | 491 | """Got the throttling limits.""" |
445 | 144 | self.up_limit = int(limits['upload']) | 492 | logger.debug("got limits: %s" % (limits,)) |
446 | 145 | self.dn_limit = int(limits['download']) | 493 | self.devices.handle_limits(limits) |
443 | 146 | self.up_spin.set_value(self.up_limit / 1024) | ||
444 | 147 | self.dn_spin.set_value(self.dn_limit / 1024) | ||
447 | 148 | 494 | ||
448 | 149 | def __got_enabled(self, enabled): | 495 | def __got_enabled(self, enabled): |
449 | 150 | """Got the throttling enabled config.""" | 496 | """Got the throttling enabled config.""" |
476 | 151 | self.bw_enabled = bool(enabled) | 497 | self.devices.handle_throttling_enabled(enabled) |
451 | 152 | self.limit_check.set_active(self.bw_enabled) | ||
452 | 153 | |||
453 | 154 | def __update_bw_settings(self): | ||
454 | 155 | """Update the bandwidth throttling config in syncdaemon.""" | ||
455 | 156 | self.bw_enabled = self.limit_check.get_active() | ||
456 | 157 | self.up_limit = self.up_spin.get_value_as_int() * 1024 | ||
457 | 158 | self.dn_limit = self.dn_spin.get_value_as_int() * 1024 | ||
458 | 159 | |||
459 | 160 | try: | ||
460 | 161 | client = self.__bus.get_object(DBUS_IFACE_NAME, "/config", | ||
461 | 162 | follow_name_owner_changes=True) | ||
462 | 163 | iface = dbus.Interface(client, DBUS_IFACE_CONFIG_NAME) | ||
463 | 164 | iface.set_throttling_limits(self.dn_limit, self.up_limit, | ||
464 | 165 | reply_handler=dbus_async, | ||
465 | 166 | error_handler=self.__dbus_error) | ||
466 | 167 | if self.bw_enabled: | ||
467 | 168 | iface.enable_bandwidth_throttling( | ||
468 | 169 | reply_handler=dbus_async, | ||
469 | 170 | error_handler=self.__dbus_error) | ||
470 | 171 | else: | ||
471 | 172 | iface.disable_bandwidth_throttling( | ||
472 | 173 | reply_handler=dbus_async, | ||
473 | 174 | error_handler=self.__dbus_error) | ||
474 | 175 | except DBusException, e: | ||
475 | 176 | self.__dbus_error(e) | ||
477 | 177 | 498 | ||
478 | 178 | def __handle_response(self, dialog, response): | 499 | def __handle_response(self, dialog, response): |
479 | 179 | """Handle the dialog's response.""" | 500 | """Handle the dialog's response.""" |
480 | 180 | self.hide() | 501 | self.hide() |
482 | 181 | self.__update_bw_settings() | 502 | self.devices.update_bw_settings() |
483 | 182 | gtk.main_quit() | 503 | gtk.main_quit() |
484 | 183 | 504 | ||
485 | 184 | def __bw_limit_toggled(self, button, data=None): | ||
486 | 185 | """Toggle the bw limit panel.""" | ||
487 | 186 | self.bw_enabled = self.limit_check.get_active() | ||
488 | 187 | self.bw_table.set_sensitive(self.bw_enabled) | ||
489 | 188 | try: | ||
490 | 189 | client = self.__bus.get_object(DBUS_IFACE_NAME, "/config", | ||
491 | 190 | follow_name_owner_changes=True) | ||
492 | 191 | iface = dbus.Interface(client, DBUS_IFACE_CONFIG_NAME) | ||
493 | 192 | iface.set_throttling_limits(self.dn_limit, self.up_limit, | ||
494 | 193 | reply_handler=dbus_async, | ||
495 | 194 | error_handler=self.__dbus_error) | ||
496 | 195 | if self.bw_enabled: | ||
497 | 196 | iface.enable_bandwidth_throttling( | ||
498 | 197 | reply_handler=dbus_async, | ||
499 | 198 | error_handler=self.__dbus_error) | ||
500 | 199 | else: | ||
501 | 200 | iface.disable_bandwidth_throttling( | ||
502 | 201 | reply_handler=dbus_async, | ||
503 | 202 | error_handler=self.__dbus_error) | ||
504 | 203 | except DBusException, e: | ||
505 | 204 | self.__dbus_error(e) | ||
506 | 205 | |||
507 | 206 | def __spinner_changed(self, button, data=None): | ||
508 | 207 | """Remove timeout and add anew.""" | ||
509 | 208 | if self.__update_id != 0: | ||
510 | 209 | gobject.source_remove(self.__update_id) | ||
511 | 210 | |||
512 | 211 | self.__update_id = gobject.timeout_add_seconds( | ||
513 | 212 | 1, self.__update_bw_settings) | ||
514 | 213 | |||
515 | 214 | def __connect_toggled(self, button, data=None): | ||
516 | 215 | """Toggle the connection state...""" | ||
517 | 216 | self.conn_btn.set_sensitive(False) | ||
518 | 217 | if self.connected: | ||
519 | 218 | self.sdtool.start().addCallbacks( | ||
520 | 219 | lambda _: self.sdtool.disconnect(), | ||
521 | 220 | self.__sd_error) | ||
522 | 221 | else: | ||
523 | 222 | self.sdtool.start().addCallbacks( | ||
524 | 223 | lambda _: self.sdtool.connect(), | ||
525 | 224 | self.__sd_error) | ||
526 | 225 | |||
527 | 226 | def _format_for_gb_display(self, bytes): | 505 | def _format_for_gb_display(self, bytes): |
528 | 227 | """Format bytes into reasonable gb display.""" | 506 | """Format bytes into reasonable gb display.""" |
529 | 228 | gb = bytes / 1024 / 1024 / 1024 | 507 | gb = bytes / 1024 / 1024 / 1024 |
530 | @@ -247,12 +526,7 @@ | |||
531 | 247 | def request_REST_info(self, url, method): | 526 | def request_REST_info(self, url, method): |
532 | 248 | """Make a REST request and return the resulting dict, or None.""" | 527 | """Make a REST request and return the resulting dict, or None.""" |
533 | 249 | consumer = oauth.OAuthConsumer("ubuntuone", "hammertime") | 528 | consumer = oauth.OAuthConsumer("ubuntuone", "hammertime") |
540 | 250 | items = [] | 529 | token = get_access_token(self.keyring) |
535 | 251 | items = self.keyring.find_items_sync( | ||
536 | 252 | gnomekeyring.ITEM_GENERIC_SECRET, | ||
537 | 253 | {'ubuntuone-realm': "https://ubuntuone.com", | ||
538 | 254 | 'oauth-consumer-key': consumer.key}) | ||
539 | 255 | token = oauth.OAuthToken.from_string(items[0].secret) | ||
541 | 256 | request = oauth.OAuthRequest.from_consumer_and_token( | 530 | request = oauth.OAuthRequest.from_consumer_and_token( |
542 | 257 | http_url=url, http_method=method, oauth_consumer=consumer, | 531 | http_url=url, http_method=method, oauth_consumer=consumer, |
543 | 258 | token=token) | 532 | token=token) |
544 | @@ -403,75 +677,11 @@ | |||
545 | 403 | self.mail_label.show() | 677 | self.mail_label.show() |
546 | 404 | 678 | ||
547 | 405 | # Devices tab | 679 | # Devices tab |
617 | 406 | devices = gtk.VBox(spacing=12) | 680 | self.devices = DevicesWidget(self.__bus, self.keyring) |
618 | 407 | devices.set_border_width(6) | 681 | self.notebook.append_page(self.devices) |
619 | 408 | self.notebook.append_page(devices) | 682 | self.notebook.set_tab_label_text(self.devices, _("Devices")) |
620 | 409 | self.notebook.set_tab_label_text(devices, _("Devices")) | 683 | self.devices.show_all() |
621 | 410 | devices.show() | 684 | self.devices.get_devices() |
553 | 411 | |||
554 | 412 | # Bandwidth limiting | ||
555 | 413 | self.limit_check = gtk.CheckButton(_("_Limit Bandwidth Usage")) | ||
556 | 414 | self.limit_check.connect("toggled", self.__bw_limit_toggled) | ||
557 | 415 | devices.pack_start(self.limit_check, False, False) | ||
558 | 416 | self.limit_check.show() | ||
559 | 417 | |||
560 | 418 | hbox = gtk.HBox(spacing=12) | ||
561 | 419 | devices.pack_start(hbox, False, False) | ||
562 | 420 | hbox.show() | ||
563 | 421 | |||
564 | 422 | label = gtk.Label() | ||
565 | 423 | hbox.pack_start(label, False, False) | ||
566 | 424 | label.show() | ||
567 | 425 | |||
568 | 426 | rbox = gtk.VBox(spacing=12) | ||
569 | 427 | hbox.pack_start(rbox, False, False) | ||
570 | 428 | rbox.show() | ||
571 | 429 | |||
572 | 430 | # Now put the bw limit bits in a table too | ||
573 | 431 | self.bw_table = gtk.Table(rows=2, columns=2) | ||
574 | 432 | self.bw_table.set_row_spacings(6) | ||
575 | 433 | self.bw_table.set_col_spacings(6) | ||
576 | 434 | self.bw_table.set_sensitive(False) | ||
577 | 435 | rbox.pack_start(self.bw_table, False, False) | ||
578 | 436 | self.bw_table.show() | ||
579 | 437 | |||
580 | 438 | # Upload speed | ||
581 | 439 | label = gtk.Label(_("Maximum _upload speed (KB/s):")) | ||
582 | 440 | label.set_use_underline(True) | ||
583 | 441 | label.set_alignment(0, 0.5) | ||
584 | 442 | self.bw_table.attach(label, 0, 1, 0, 1) | ||
585 | 443 | label.show() | ||
586 | 444 | |||
587 | 445 | adjustment = gtk.Adjustment(value=2048.0, lower=0.0, upper=4096.0, | ||
588 | 446 | step_incr=64.0, page_incr=128.0) | ||
589 | 447 | self.up_spin = gtk.SpinButton(adjustment) | ||
590 | 448 | self.up_spin.connect("value-changed", self.__spinner_changed) | ||
591 | 449 | label.set_mnemonic_widget(self.up_spin) | ||
592 | 450 | self.bw_table.attach(self.up_spin, 1, 2, 0, 1) | ||
593 | 451 | self.up_spin.show() | ||
594 | 452 | |||
595 | 453 | # Download speed | ||
596 | 454 | label = gtk.Label(_("Maximum _download speed (KB/s):")) | ||
597 | 455 | label.set_use_underline(True) | ||
598 | 456 | label.set_alignment(0, 0.5) | ||
599 | 457 | self.bw_table.attach(label, 0, 1, 1, 2) | ||
600 | 458 | label.show() | ||
601 | 459 | adjustment = gtk.Adjustment(value=2048.0, lower=64.0, upper=8192.0, | ||
602 | 460 | step_incr=64.0, page_incr=128.0) | ||
603 | 461 | self.dn_spin = gtk.SpinButton(adjustment) | ||
604 | 462 | self.dn_spin.connect("value-changed", self.__spinner_changed) | ||
605 | 463 | label.set_mnemonic_widget(self.dn_spin) | ||
606 | 464 | self.bw_table.attach(self.dn_spin, 1, 2, 1, 2) | ||
607 | 465 | self.dn_spin.show() | ||
608 | 466 | |||
609 | 467 | alignment = gtk.Alignment(1.0, 0.5) | ||
610 | 468 | rbox.pack_end(alignment, False, False) | ||
611 | 469 | alignment.show() | ||
612 | 470 | |||
613 | 471 | self.conn_btn = gtk.Button(_("Connect")) | ||
614 | 472 | self.conn_btn.connect('clicked', self.__connect_toggled) | ||
615 | 473 | alignment.add(self.conn_btn) | ||
616 | 474 | self.conn_btn.show() | ||
622 | 475 | 685 | ||
623 | 476 | # Services tab | 686 | # Services tab |
624 | 477 | services = gtk.VBox(spacing=12) | 687 | services = gtk.VBox(spacing=12) |
625 | 478 | 688 | ||
626 | === modified file 'tests/test_preferences.py' | |||
627 | --- tests/test_preferences.py 2010-02-18 16:02:23 +0000 | |||
628 | +++ tests/test_preferences.py 2010-03-05 17:04:28 +0000 | |||
629 | @@ -53,26 +53,24 @@ | |||
630 | 53 | 53 | ||
631 | 54 | self.item_id = 999 | 54 | self.item_id = 999 |
632 | 55 | 55 | ||
653 | 56 | ex = self.expect(self.item.item_id) | 56 | self.item.item_id |
654 | 57 | ex.result(self.item_id) | 57 | self.mocker.result(self.item_id) |
655 | 58 | ex.count(0, None) | 58 | self.mocker.count(0, None) |
656 | 59 | 59 | ||
657 | 60 | ex = self.expect(self.item.secret) | 60 | self.item.secret |
658 | 61 | ex.result('oauth_token=access_key&oauth_token_secret=access_secret') | 61 | self.mocker.result('oauth_token=access_key' |
659 | 62 | ex.count(0, None) | 62 | '&oauth_token_secret=access_secret') |
660 | 63 | 63 | self.mocker.count(0, None) | |
661 | 64 | def expect_token_query(self): | 64 | |
662 | 65 | """Expects the keyring to be queried for a token.""" | 65 | self.keyring.find_items_sync( |
663 | 66 | return self.expect( | 66 | None, |
664 | 67 | self.keyring.find_items_sync( | 67 | {'ubuntuone-realm': 'https://ubuntuone.com', |
665 | 68 | gnomekeyring.ITEM_GENERIC_SECRET, | 68 | 'oauth-consumer-key': 'ubuntuone'}) |
666 | 69 | {'ubuntuone-realm': 'https://ubuntuone.com', | 69 | self.mocker.count(0, None) |
667 | 70 | 'oauth-consumer-key': 'ubuntuone'}) | 70 | self.mocker.result([self.item]) |
668 | 71 | ) | 71 | self.keyring.ITEM_GENERIC_SECRET |
669 | 72 | 72 | self.mocker.count(0, None) | |
670 | 73 | def mock_has_token(self): | 73 | self.mocker.result(None) |
651 | 74 | """Mocks a cached token in the keyring.""" | ||
652 | 75 | self.expect_token_query().result([self.item]) | ||
671 | 76 | 74 | ||
672 | 77 | def tearDown(self): | 75 | def tearDown(self): |
673 | 78 | # collect all signal receivers registered during the test | 76 | # collect all signal receivers registered during the test |
674 | @@ -93,18 +91,108 @@ | |||
675 | 93 | def test_bw_throttling(self): | 91 | def test_bw_throttling(self): |
676 | 94 | """Test that toggling bw throttling works correctly.""" | 92 | """Test that toggling bw throttling works correctly.""" |
677 | 95 | self.mocker.replay() | 93 | self.mocker.replay() |
685 | 96 | dialog = self.u1prefs.UbuntuOneDialog() | 94 | widget = self.u1prefs.DevicesWidget(None, keyring=self.keyring) |
686 | 97 | self.assertTrue(dialog is not None) | 95 | try: |
687 | 98 | dialog.notebook.set_current_page(1) | 96 | widget.devices = [] |
688 | 99 | self.assertFalse(dialog.bw_table.get_property('sensitive')) | 97 | widget.list_devices() |
689 | 100 | dialog.limit_check.set_active(True) | 98 | self.assertFalse(widget.bw_limited, |
690 | 101 | self.assertTrue(dialog.bw_table.get_property('sensitive')) | 99 | "the bandwidth should start out not limited") |
691 | 102 | dialog.destroy() | 100 | self.assertTrue(widget.bw_chk, |
692 | 101 | "the checkbox should be present") | ||
693 | 102 | self.assertFalse(widget.bw_chk.get_active(), | ||
694 | 103 | "the checkbox should start out unchecked") | ||
695 | 104 | self.assertFalse(widget.up_spin.get_property('sensitive') or | ||
696 | 105 | widget.dn_spin.get_property('sensitive'), | ||
697 | 106 | "the spinbuttons should start out unsensitive") | ||
698 | 107 | widget.bw_chk.set_active(True) | ||
699 | 108 | self.assertTrue(widget.bw_chk.get_active(), | ||
700 | 109 | "the checkbox should now be checked") | ||
701 | 110 | self.assertTrue(widget.up_spin.get_property('sensitive') and | ||
702 | 111 | widget.dn_spin.get_property('sensitive'), | ||
703 | 112 | "the spinbuttons should now be sensitive") | ||
704 | 113 | finally: | ||
705 | 114 | widget.destroy() | ||
706 | 115 | |||
707 | 116 | def test_list_devices_fills_devices_list_with_fake_result_when_empty(self): | ||
708 | 117 | self.mocker.replay() | ||
709 | 118 | widget = self.u1prefs.DevicesWidget(None, keyring=self.keyring) | ||
710 | 119 | try: | ||
711 | 120 | widget.devices = [] | ||
712 | 121 | widget.list_devices() | ||
713 | 122 | # the devices list is no longer empty | ||
714 | 123 | self.assertTrue(widget.devices) | ||
715 | 124 | # it has 'fake' data (referring to the local machine) | ||
716 | 125 | self.assertTrue('FAKE' in widget.devices[0]) | ||
717 | 126 | finally: | ||
718 | 127 | widget.destroy() | ||
719 | 128 | |||
720 | 129 | def test_list_devices_shows_devices_list(self): | ||
721 | 130 | self.mocker.replay() | ||
722 | 131 | widget = self.u1prefs.DevicesWidget(None, keyring=self.keyring) | ||
723 | 132 | try: | ||
724 | 133 | widget.devices = [] | ||
725 | 134 | widget.list_devices() | ||
726 | 135 | # fake data now in devices | ||
727 | 136 | interesting = [] | ||
728 | 137 | for i in widget.get_children(): | ||
729 | 138 | clsname = i.__class__.__name__ | ||
730 | 139 | if clsname == 'Image': | ||
731 | 140 | interesting.append((clsname, i.get_icon_name()[0])) | ||
732 | 141 | if clsname in ('Label', 'Button', 'CheckButton'): | ||
733 | 142 | interesting.append((clsname, i.get_label())) | ||
734 | 143 | # check there is an image of a computer in there | ||
735 | 144 | self.assertTrue(('Image', 'computer') in interesting) | ||
736 | 145 | # check a placeholder for the local machine description is there | ||
737 | 146 | self.assertTrue(('Label', '<LOCAL MACHINE>') in interesting) | ||
738 | 147 | # check the bw limitation stuff is there | ||
739 | 148 | self.assertTrue(('CheckButton', '_Limit Bandwidth Usage') | ||
740 | 149 | in interesting) | ||
741 | 150 | self.assertTrue(('Label', 'Download (kB/s):') in interesting) | ||
742 | 151 | self.assertTrue(('Label', 'Upload (kB/s):') in interesting) | ||
743 | 152 | # check the 'Remove' button is *not* there | ||
744 | 153 | self.assertTrue(('Button', 'Remove') not in interesting) | ||
745 | 154 | finally: | ||
746 | 155 | widget.destroy() | ||
747 | 156 | |||
748 | 157 | def test_list_devices_shows_real_devices_list(self): | ||
749 | 158 | self.mocker.replay() | ||
750 | 159 | widget = self.u1prefs.DevicesWidget(None, keyring=self.keyring) | ||
751 | 160 | try: | ||
752 | 161 | widget.devices = [{'kind': 'Computer', | ||
753 | 162 | 'description': 'xyzzy', | ||
754 | 163 | 'token': 'blah'}, | ||
755 | 164 | {'kind': 'Phone', | ||
756 | 165 | 'description': 'quux', | ||
757 | 166 | 'token': '1234'}] | ||
758 | 167 | widget.list_devices() | ||
759 | 168 | # fake data now in devices | ||
760 | 169 | interesting = [] | ||
761 | 170 | for i in widget.get_children(): | ||
762 | 171 | clsname = i.__class__.__name__ | ||
763 | 172 | if clsname == 'Image': | ||
764 | 173 | interesting.append((clsname, i.get_icon_name()[0])) | ||
765 | 174 | if clsname in ('Label', 'Button', 'CheckButton'): | ||
766 | 175 | interesting.append((clsname, i.get_label())) | ||
767 | 176 | # check there is an image of a computer in there | ||
768 | 177 | self.assertTrue(('Image', 'computer') in interesting) | ||
769 | 178 | # and of a phone | ||
770 | 179 | self.assertTrue(('Image', 'phone') in interesting) | ||
771 | 180 | # check a label of the local machine description is there | ||
772 | 181 | self.assertTrue(('Label', 'xyzzy') in interesting) | ||
773 | 182 | # check the bw limitation stuff is not there (no local machine) | ||
774 | 183 | self.assertTrue(('CheckButton', '_Limit Bandwidth Usage') | ||
775 | 184 | not in interesting) | ||
776 | 185 | self.assertTrue(('Label', 'Download (kB/s):') not in interesting) | ||
777 | 186 | self.assertTrue(('Label', 'Upload (kB/s):') not in interesting) | ||
778 | 187 | # check the 'Remove' button is there | ||
779 | 188 | self.assertTrue(('Button', 'Remove') in interesting) | ||
780 | 189 | finally: | ||
781 | 190 | widget.destroy() | ||
782 | 103 | 191 | ||
783 | 104 | def test_quota_display(self): | 192 | def test_quota_display(self): |
784 | 105 | """Test that quota display works correctly.""" | 193 | """Test that quota display works correctly.""" |
785 | 106 | self.mocker.replay() | 194 | self.mocker.replay() |
787 | 107 | dialog = self.u1prefs.UbuntuOneDialog() | 195 | dialog = self.u1prefs.UbuntuOneDialog(keyring=self.keyring) |
788 | 108 | self.assertTrue(dialog is not None) | 196 | self.assertTrue(dialog is not None) |
789 | 109 | self.assertEqual(dialog.usage_graph.get_fraction(), 0.0) | 197 | self.assertEqual(dialog.usage_graph.get_fraction(), 0.0) |
790 | 110 | dialog.update_quota_display(1024, 2048) | 198 | dialog.update_quota_display(1024, 2048) |
791 | @@ -113,11 +201,6 @@ | |||
792 | 113 | 201 | ||
793 | 114 | def test_request_quota_info(self): | 202 | def test_request_quota_info(self): |
794 | 115 | """Test that we can request the quota info properly.""" | 203 | """Test that we can request the quota info properly.""" |
795 | 116 | self.mock_has_token() | ||
796 | 117 | dialog = self.u1prefs.UbuntuOneDialog() | ||
797 | 118 | self.assertTrue(dialog is not None) | ||
798 | 119 | dialog.keyring = self.keyring | ||
799 | 120 | self.assertEqual(dialog.usage_graph.get_fraction(), 0.0) | ||
800 | 121 | response = { 'status' : '200' } | 204 | response = { 'status' : '200' } |
801 | 122 | content = '{"total":2048, "used":1024}' | 205 | content = '{"total":2048, "used":1024}' |
802 | 123 | client = self.mocker.mock() | 206 | client = self.mocker.mock() |
803 | @@ -125,16 +208,15 @@ | |||
804 | 125 | self.expect(client.request('https://one.ubuntu.com/api/quota/', | 208 | self.expect(client.request('https://one.ubuntu.com/api/quota/', |
805 | 126 | 'GET', KWARGS)).result((response, content)) | 209 | 'GET', KWARGS)).result((response, content)) |
806 | 127 | self.mocker.replay() | 210 | self.mocker.replay() |
807 | 211 | dialog = self.u1prefs.UbuntuOneDialog(keyring=self.keyring) | ||
808 | 212 | self.assertTrue(dialog is not None) | ||
809 | 213 | self.assertEqual(dialog.usage_graph.get_fraction(), 0.0) | ||
810 | 128 | dialog.request_quota_info() | 214 | dialog.request_quota_info() |
811 | 129 | self.assertEqual(dialog.usage_graph.get_fraction(), 0.5) | 215 | self.assertEqual(dialog.usage_graph.get_fraction(), 0.5) |
812 | 130 | dialog.destroy() | 216 | dialog.destroy() |
813 | 131 | 217 | ||
814 | 132 | def test_request_account_info(self): | 218 | def test_request_account_info(self): |
815 | 133 | """Test that we can request the account info properly.""" | 219 | """Test that we can request the account info properly.""" |
816 | 134 | self.mock_has_token() | ||
817 | 135 | dialog = self.u1prefs.UbuntuOneDialog() | ||
818 | 136 | self.assertTrue(dialog is not None) | ||
819 | 137 | dialog.keyring = self.keyring | ||
820 | 138 | response = { 'status' : '200' } | 220 | response = { 'status' : '200' } |
821 | 139 | content = '''{"username": "ubuntuone", "nickname": "Ubuntu One", | 221 | content = '''{"username": "ubuntuone", "nickname": "Ubuntu One", |
822 | 140 | "email": "uone@example.com"} | 222 | "email": "uone@example.com"} |
823 | @@ -144,6 +226,8 @@ | |||
824 | 144 | self.expect(client.request('https://one.ubuntu.com/api/account/', | 226 | self.expect(client.request('https://one.ubuntu.com/api/account/', |
825 | 145 | 'GET', KWARGS)).result((response, content)) | 227 | 'GET', KWARGS)).result((response, content)) |
826 | 146 | self.mocker.replay() | 228 | self.mocker.replay() |
827 | 229 | dialog = self.u1prefs.UbuntuOneDialog(keyring=self.keyring) | ||
828 | 230 | self.assertTrue(dialog is not None) | ||
829 | 147 | dialog.request_account_info() | 231 | dialog.request_account_info() |
830 | 148 | self.assertEqual(dialog.name_label.get_text(), 'Ubuntu One') | 232 | self.assertEqual(dialog.name_label.get_text(), 'Ubuntu One') |
831 | 149 | self.assertEqual(dialog.user_label.get_text(), 'ubuntuone') | 233 | self.assertEqual(dialog.user_label.get_text(), 'ubuntuone') |
832 | @@ -152,13 +236,14 @@ | |||
833 | 152 | 236 | ||
834 | 153 | def test_toggle_bookmarks(self): | 237 | def test_toggle_bookmarks(self): |
835 | 154 | """Test toggling the bookmarks service on/off.""" | 238 | """Test toggling the bookmarks service on/off.""" |
837 | 155 | dialog = self.u1prefs.UbuntuOneDialog() | 239 | toggle_db_sync = self.mocker.mock() |
838 | 240 | self.expect(toggle_db_sync('bookmarks', False)) | ||
839 | 241 | self.expect(toggle_db_sync('bookmarks', True)) | ||
840 | 242 | self.expect(toggle_db_sync('bookmarks', False)) | ||
841 | 243 | self.mocker.replay() | ||
842 | 244 | dialog = self.u1prefs.UbuntuOneDialog(keyring=self.keyring) | ||
843 | 156 | self.assertTrue(dialog is not None) | 245 | self.assertTrue(dialog is not None) |
849 | 157 | dialog.toggle_db_sync = self.mocker.mock() | 246 | dialog.toggle_db_sync = toggle_db_sync |
845 | 158 | self.expect(dialog.toggle_db_sync('bookmarks', False)) | ||
846 | 159 | self.expect(dialog.toggle_db_sync('bookmarks', True)) | ||
847 | 160 | self.expect(dialog.toggle_db_sync('bookmarks', False)) | ||
848 | 161 | self.mocker.replay() | ||
850 | 162 | dialog.bookmarks_check.set_active(True) | 247 | dialog.bookmarks_check.set_active(True) |
851 | 163 | self.assertTrue(dialog.bookmarks_check.get_active()) | 248 | self.assertTrue(dialog.bookmarks_check.get_active()) |
852 | 164 | dialog.bookmarks_check.set_active(False) | 249 | dialog.bookmarks_check.set_active(False) |
853 | @@ -168,13 +253,14 @@ | |||
854 | 168 | 253 | ||
855 | 169 | def test_toggle_contacts(self): | 254 | def test_toggle_contacts(self): |
856 | 170 | """Test toggling the contacts service on/off.""" | 255 | """Test toggling the contacts service on/off.""" |
858 | 171 | dialog = self.u1prefs.UbuntuOneDialog() | 256 | toggle_db_sync = self.mocker.mock() |
859 | 257 | self.expect(toggle_db_sync('contacts', False)) | ||
860 | 258 | self.expect(toggle_db_sync('contacts', True)) | ||
861 | 259 | self.expect(toggle_db_sync('contacts', False)) | ||
862 | 260 | self.mocker.replay() | ||
863 | 261 | dialog = self.u1prefs.UbuntuOneDialog(keyring=self.keyring) | ||
864 | 172 | self.assertTrue(dialog is not None) | 262 | self.assertTrue(dialog is not None) |
870 | 173 | dialog.toggle_db_sync = self.mocker.mock() | 263 | dialog.toggle_db_sync = toggle_db_sync |
866 | 174 | self.expect(dialog.toggle_db_sync('contacts', False)) | ||
867 | 175 | self.expect(dialog.toggle_db_sync('contacts', True)) | ||
868 | 176 | self.expect(dialog.toggle_db_sync('contacts', False)) | ||
869 | 177 | self.mocker.replay() | ||
871 | 178 | dialog.abook_check.set_active(True) | 264 | dialog.abook_check.set_active(True) |
872 | 179 | self.assertTrue(dialog.abook_check.get_active()) | 265 | self.assertTrue(dialog.abook_check.get_active()) |
873 | 180 | dialog.abook_check.set_active(False) | 266 | dialog.abook_check.set_active(False) |
874 | @@ -184,9 +270,9 @@ | |||
875 | 184 | 270 | ||
876 | 185 | def test_toggle_files(self): | 271 | def test_toggle_files(self): |
877 | 186 | """Test toggling the files service on/off.""" | 272 | """Test toggling the files service on/off.""" |
879 | 187 | dialog = self.u1prefs.UbuntuOneDialog() | 273 | self.mocker.replay() |
880 | 274 | dialog = self.u1prefs.UbuntuOneDialog(keyring=self.keyring) | ||
881 | 188 | self.assertTrue(dialog is not None) | 275 | self.assertTrue(dialog is not None) |
882 | 189 | self.mocker.replay() | ||
883 | 190 | dialog.files_check.set_active(True) | 276 | dialog.files_check.set_active(True) |
884 | 191 | self.assertTrue(dialog.files_check.get_active()) | 277 | self.assertTrue(dialog.files_check.get_active()) |
885 | 192 | dialog.files_check.set_active(False) | 278 | dialog.files_check.set_active(False) |
886 | @@ -196,9 +282,9 @@ | |||
887 | 196 | 282 | ||
888 | 197 | def test_toggle_files_and_music(self): | 283 | def test_toggle_files_and_music(self): |
889 | 198 | """Test toggling the files and music services on/off.""" | 284 | """Test toggling the files and music services on/off.""" |
891 | 199 | dialog = self.u1prefs.UbuntuOneDialog() | 285 | self.mocker.replay() |
892 | 286 | dialog = self.u1prefs.UbuntuOneDialog(keyring=self.keyring) | ||
893 | 200 | self.assertTrue(dialog is not None) | 287 | self.assertTrue(dialog is not None) |
894 | 201 | self.mocker.replay() | ||
895 | 202 | dialog.files_check.set_active(False) | 288 | dialog.files_check.set_active(False) |
896 | 203 | self.assertFalse(dialog.files_check.get_active()) | 289 | self.assertFalse(dialog.files_check.get_active()) |
897 | 204 | self.assertFalse(dialog.music_check.props.sensitive) | 290 | self.assertFalse(dialog.music_check.props.sensitive) |
898 | 205 | 291 | ||
899 | === modified file 'ubuntuone/syncdaemon/dbus_interface.py' | |||
900 | --- ubuntuone/syncdaemon/dbus_interface.py 2010-03-03 15:04:02 +0000 | |||
901 | +++ ubuntuone/syncdaemon/dbus_interface.py 2010-03-05 17:04:28 +0000 | |||
902 | @@ -1010,6 +1010,7 @@ | |||
903 | 1010 | configured. | 1010 | configured. |
904 | 1011 | The values are bytes/second | 1011 | The values are bytes/second |
905 | 1012 | """ | 1012 | """ |
906 | 1013 | logger.debug("called get_throttling_limits") | ||
907 | 1013 | try: | 1014 | try: |
908 | 1014 | aq = self.dbus_iface.action_queue | 1015 | aq = self.dbus_iface.action_queue |
909 | 1015 | download = -1 | 1016 | download = -1 |
910 | @@ -1037,6 +1038,7 @@ | |||
911 | 1037 | def set_throttling_limits(self, download, upload, | 1038 | def set_throttling_limits(self, download, upload, |
912 | 1038 | reply_handler=None, error_handler=None): | 1039 | reply_handler=None, error_handler=None): |
913 | 1039 | """Set the read and write limits. The expected values are bytes/sec.""" | 1040 | """Set the read and write limits. The expected values are bytes/sec.""" |
914 | 1041 | logger.debug("called set_throttling_limits") | ||
915 | 1040 | try: | 1042 | try: |
916 | 1041 | # modify and save the config file | 1043 | # modify and save the config file |
917 | 1042 | user_config = config.get_user_config() | 1044 | user_config = config.get_user_config() |
Getting keyring errors