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

Proposed by Natalia Bidart
Status: Merged
Approved by: dobey
Approved revision: 44
Merged at revision: 38
Proposed branch: lp:~nataliabidart/ubuntuone-control-panel/remove-devices
Merge into: lp:ubuntuone-control-panel
Prerequisite: lp:~nataliabidart/ubuntuone-control-panel/new-sso-iface
Diff against target: 857 lines (+301/-79)
7 files modified
data/device.ui (+13/-11)
ubuntuone/controlpanel/__init__.py (+1/-1)
ubuntuone/controlpanel/backend.py (+37/-12)
ubuntuone/controlpanel/gtk/gui.py (+75/-18)
ubuntuone/controlpanel/gtk/tests/test_gui.py (+142/-31)
ubuntuone/controlpanel/tests/test_backend.py (+26/-1)
ubuntuone/controlpanel/webclient.py (+7/-5)
To merge this branch: bzr merge lp:~nataliabidart/ubuntuone-control-panel/remove-devices
Reviewer Review Type Date Requested Status
Manuel de la Peña (community) Approve
Roberto Alsina (community) fieldtest Approve
Review via email: mp+44139@code.launchpad.net

Commit message

* Devices can now be removed (LP: #691295).

Description of the change

To run the tests, do:

./run-tests

To test IRL, open 2 terminals pointing to this branch, and run:

terminal 1: DEBUG=True PYTHONPATH=. ./bin/ubuntuone-control-panel-backend
terminal 2: DEBUG=True PYTHONPATH=. ./bin/ubuntuone-control-panel-gtk

and play with the 3rd tab. The 'Remove' button is fully functional so be careful.

Among the suggested tests if removing the local device (ie the computer you're testing on). You should be taken to the overview panel after that to re-add your account.

To post a comment you must log in.
Revision history for this message
Roberto Alsina (ralsina) wrote :

It works.

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

+1

review: Approve
Revision history for this message
Ubuntu One Auto Pilot (otto-pilot) wrote :
Download full text (23.0 KiB)

The attempt to merge lp:~nataliabidart/ubuntuone-control-panel/remove-devices into lp:ubuntuone-control-panel failed. Below is the output from the failed tests.

Running test suite for ubuntuone/controlpanel/tests
ubuntuone.controlpanel.tests.test_backend
  BackendAccountTestCase
    test_account_info ... [OK]
    test_account_info_fails ... [OK]
    test_backend_creation ... [OK]
    test_device_is_local ... [OK]
    test_get_token ... [OK]
  BackendBasicTestCase
    test_backend_creation ... [OK]
    test_device_is_local ... [OK]
    test_get_token ... [OK]
  BackendDevicesTestCase
    test_backend_creation ... [OK]
    test_change_download_speed_limit ... [OK]
    test_change_limit_bandwidth ... [OK]
    test_change_upload_speed_limit ... [OK]
    test_changing_settings_for_wrong_id_has_no_effect ... [OK]
    test_device_is_local ... [OK]
    test_devices_info ... [OK]
    test_devices_info_fails ... [OK]
    test_get_token ... [OK]
    test_remove_device ... [OK]
    test_remove_device_clear_credentials_if_local_device ... [OK]
    test_remove_device_fails ... [OK]
  BackendSyncStatusTestCase
    test_backend_creation ... [OK]
    test_device_is_local ... [OK]
    test_disabled ... [OK]
    test_disconnected ... [OK]
    test_error ... [OK]
    test_get_token ... [OK]
    test_idle ... [OK]
    test_starting_when_init_not_user ... [OK]
    test_starting_when_init_with_user ... [OK]
    test_starting_when_local_rescan_not_user ... [OK]
    test_starting_when_local_rescan_with_user ... [OK]
    test_starting_when_ready_with_user ... [OK]
    test_status_changed ... [OK]
    test_syncing_even_if_not_online ... [OK]
    test_syncing_if_online ... [OK]
    test_unknown ... ...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'data/device.ui'
--- data/device.ui 2010-12-16 20:56:57 +0000
+++ data/device.ui 2010-12-18 17:42:12 +0000
@@ -2,6 +2,14 @@
2<interface>2<interface>
3 <requires lib="gtk+" version="2.16"/>3 <requires lib="gtk+" version="2.16"/>
4 <!-- interface-naming-policy project-wide -->4 <!-- interface-naming-policy project-wide -->
5 <object class="GtkAdjustment" id="adjustment2">
6 <property name="upper">10000</property>
7 <property name="step_increment">1</property>
8 </object>
9 <object class="GtkAdjustment" id="adjustment1">
10 <property name="upper">10000</property>
11 <property name="step_increment">1</property>
12 </object>
5 <object class="GtkVBox" id="itself">13 <object class="GtkVBox" id="itself">
6 <property name="visible">True</property>14 <property name="visible">True</property>
7 <property name="spacing">5</property>15 <property name="spacing">5</property>
@@ -74,7 +82,7 @@
74 <property name="can_focus">True</property>82 <property name="can_focus">True</property>
75 <property name="receives_default">False</property>83 <property name="receives_default">False</property>
76 <property name="draw_indicator">True</property>84 <property name="draw_indicator">True</property>
77 <signal name="toggled" handler="on_limit_bandwidth_toggled"/>85 <signal name="toggled" handler="on_limit_bandwidth_toggled" swapped="no"/>
78 </object>86 </object>
79 </child>87 </child>
80 <child>88 <child>
@@ -108,7 +116,7 @@
108 <property name="invisible_char">•</property>116 <property name="invisible_char">•</property>
109 <property name="activates_default">True</property>117 <property name="activates_default">True</property>
110 <property name="adjustment">adjustment1</property>118 <property name="adjustment">adjustment1</property>
111 <signal name="value_changed" handler="on_max_upload_speed_value_changed"/>119 <signal name="value-changed" handler="on_max_upload_speed_value_changed" swapped="no"/>
112 </object>120 </object>
113 <packing>121 <packing>
114 <property name="left_attach">1</property>122 <property name="left_attach">1</property>
@@ -126,7 +134,7 @@
126 <property name="invisible_char">•</property>134 <property name="invisible_char">•</property>
127 <property name="activates_default">True</property>135 <property name="activates_default">True</property>
128 <property name="adjustment">adjustment2</property>136 <property name="adjustment">adjustment2</property>
129 <signal name="value_changed" handler="on_max_download_speed_value_changed"/>137 <signal name="value-changed" handler="on_max_download_speed_value_changed" swapped="no"/>
130 </object>138 </object>
131 <packing>139 <packing>
132 <property name="left_attach">1</property>140 <property name="left_attach">1</property>
@@ -161,6 +169,8 @@
161 <property name="can_focus">True</property>169 <property name="can_focus">True</property>
162 <property name="receives_default">True</property>170 <property name="receives_default">True</property>
163 <property name="use_stock">True</property>171 <property name="use_stock">True</property>
172 <signal name="activate" handler="on_remove_clicked" swapped="no"/>
173 <signal name="clicked" handler="on_remove_clicked" swapped="no"/>
164 </object>174 </object>
165 <packing>175 <packing>
166 <property name="expand">False</property>176 <property name="expand">False</property>
@@ -190,12 +200,4 @@
190 </packing>200 </packing>
191 </child>201 </child>
192 </object>202 </object>
193 <object class="GtkAdjustment" id="adjustment1">
194 <property name="upper">10000</property>
195 <property name="step_increment">1</property>
196 </object>
197 <object class="GtkAdjustment" id="adjustment2">
198 <property name="upper">10000</property>
199 <property name="step_increment">1</property>
200 </object>
201</interface>203</interface>
202204
=== modified file 'ubuntuone/controlpanel/__init__.py'
--- ubuntuone/controlpanel/__init__.py 2010-10-08 01:31:34 +0000
+++ ubuntuone/controlpanel/__init__.py 2010-12-18 17:42:12 +0000
@@ -29,4 +29,4 @@
29DBUS_PREFERENCES_PATH = "/preferences"29DBUS_PREFERENCES_PATH = "/preferences"
30DBUS_PREFERENCES_IFACE = "com.ubuntuone.controlpanel.Preferences"30DBUS_PREFERENCES_IFACE = "com.ubuntuone.controlpanel.Preferences"
3131
32WEBSERVICE_BASE_URL = "https://one.ubuntu.com/api/"32WEBSERVICE_BASE_URL = u"https://one.ubuntu.com/api/"
3333
=== modified file 'ubuntuone/controlpanel/backend.py'
--- ubuntuone/controlpanel/backend.py 2010-12-18 17:42:11 +0000
+++ ubuntuone/controlpanel/backend.py 2010-12-18 17:42:12 +0000
@@ -49,6 +49,11 @@
49STATUS_KEY = 'status'49STATUS_KEY = 'status'
5050
5151
52def bool_str(value):
53 """Return the string representation of a bool (dbus-compatible)."""
54 return 'True' if value else ''
55
56
52class ControlBackend(object):57class ControlBackend(object):
53 """The control panel backend."""58 """The control panel backend."""
5459
@@ -124,6 +129,15 @@
124 credentials = yield dbus_client.get_credentials()129 credentials = yield dbus_client.get_credentials()
125 returnValue(credentials["token"])130 returnValue(credentials["token"])
126131
132 @inlineCallbacks
133 def device_is_local(self, device_id):
134 """Return whether 'device_id' is the local devicew or not."""
135 dtype, did = self.type_n_id(device_id)
136 local_token = yield self.get_token()
137 is_local = (dtype == DEVICE_TYPE_COMPUTER and did == local_token)
138 logger.info('device_is_local: result %r, ', is_local)
139 returnValue(is_local)
140
127 @log_call(logger.debug)141 @log_call(logger.debug)
128 @inlineCallbacks142 @inlineCallbacks
129 def account_info(self):143 def account_info(self):
@@ -146,7 +160,6 @@
146 def devices_info(self):160 def devices_info(self):
147 """Get the user devices info."""161 """Get the user devices info."""
148 result = []162 result = []
149 this_token = yield self.get_token()
150 limit_bw = yield dbus_client.bandwidth_throttling_enabled()163 limit_bw = yield dbus_client.bandwidth_throttling_enabled()
151 limits = yield dbus_client.get_throttling_limits()164 limits = yield dbus_client.get_throttling_limits()
152165
@@ -159,16 +172,22 @@
159 di["configurable"] = ''172 di["configurable"] = ''
160 if di["type"] == DEVICE_TYPE_COMPUTER:173 if di["type"] == DEVICE_TYPE_COMPUTER:
161 di["device_id"] = di["type"] + d["token"]174 di["device_id"] = di["type"] + d["token"]
162 if d["token"] == this_token:
163 di["configurable"] = 'True'
164 di["limit_bandwidth"] = 'True' if limit_bw else ''
165 upload = limits["upload"]
166 download = limits["download"]
167 di[UPLOAD_KEY] = str(upload)
168 di[DOWNLOAD_KEY] = str(download)
169 if di["type"] == DEVICE_TYPE_PHONE:175 if di["type"] == DEVICE_TYPE_PHONE:
170 di["device_id"] = di["type"] + str(d["id"])176 di["device_id"] = di["type"] + str(d["id"])
171177
178 is_local = yield self.device_is_local(di["device_id"])
179 di["is_local"] = bool_str(is_local)
180 # currently, only local devices are configurable.
181 # eventually, more the devices will be configurable.
182 di["configurable"] = bool_str(is_local)
183
184 if bool(di["configurable"]):
185 di["limit_bandwidth"] = bool_str(limit_bw)
186 upload = limits["upload"]
187 download = limits["download"]
188 di[UPLOAD_KEY] = str(upload)
189 di[DOWNLOAD_KEY] = str(download)
190
172 # date_added is not in the webservice yet (LP: #673668)191 # date_added is not in the webservice yet (LP: #673668)
173 # di["date_added"] = ""192 # di["date_added"] = ""
174193
@@ -190,9 +209,7 @@
190 @inlineCallbacks209 @inlineCallbacks
191 def change_device_settings(self, device_id, settings):210 def change_device_settings(self, device_id, settings):
192 """Change the settings for the given device."""211 """Change the settings for the given device."""
193 dtype, did = self.type_n_id(device_id)212 is_local = yield self.device_is_local(device_id)
194 local_token = yield self.get_token()
195 is_local = (dtype == DEVICE_TYPE_COMPUTER and did == local_token)
196213
197 if is_local and "limit_bandwidth" in settings:214 if is_local and "limit_bandwidth" in settings:
198 limit_bw = bool(settings["limit_bandwidth"])215 limit_bw = bool(settings["limit_bandwidth"])
@@ -222,8 +239,16 @@
222 def remove_device(self, device_id):239 def remove_device(self, device_id):
223 """Remove a device's tokens from the sso server."""240 """Remove a device's tokens from the sso server."""
224 dtype, did = self.type_n_id(device_id)241 dtype, did = self.type_n_id(device_id)
225 api = DEVICE_REMOVE_API % (dtype, did)242 is_local = yield self.device_is_local(device_id)
243
244 api = DEVICE_REMOVE_API % (dtype.lower(), did)
226 yield self.wc.call_api(api)245 yield self.wc.call_api(api)
246
247 if is_local:
248 logger.warning('remove_device: device is local, id %r, '
249 'clearing credentials.', device_id)
250 yield dbus_client.clear_credentials()
251
227 returnValue(device_id)252 returnValue(device_id)
228253
229 @log_call(logger.debug)254 @log_call(logger.debug)
230255
=== modified file 'ubuntuone/controlpanel/gtk/gui.py'
--- ubuntuone/controlpanel/gtk/gui.py 2010-12-17 17:25:10 +0000
+++ ubuntuone/controlpanel/gtk/gui.py 2010-12-18 17:42:12 +0000
@@ -48,7 +48,7 @@
48from ubuntuone.controlpanel import (DBUS_BUS_NAME, DBUS_PREFERENCES_PATH,48from ubuntuone.controlpanel import (DBUS_BUS_NAME, DBUS_PREFERENCES_PATH,
49 DBUS_PREFERENCES_IFACE)49 DBUS_PREFERENCES_IFACE)
50from ubuntuone.controlpanel.backend import (DEVICE_TYPE_PHONE,50from ubuntuone.controlpanel.backend import (DEVICE_TYPE_PHONE,
51 DEVICE_TYPE_COMPUTER)51 DEVICE_TYPE_COMPUTER, bool_str)
52from ubuntuone.controlpanel.logger import setup_logging, log_call52from ubuntuone.controlpanel.logger import setup_logging, log_call
53from ubuntuone.controlpanel.utils import get_data_file53from ubuntuone.controlpanel.utils import get_data_file
5454
@@ -74,11 +74,6 @@
74KILOBYTES = 102474KILOBYTES = 1024
7575
7676
77def bool_str(value):
78 """Return the string representation of a bool (dbus-compatible)."""
79 return 'True' if value else ''
80
81
82def filter_by_app_name(f):77def filter_by_app_name(f):
83 """Excecute 'f' filtering by app_name."""78 """Excecute 'f' filtering by app_name."""
8479
@@ -187,15 +182,23 @@
187 self._window_id = window_id182 self._window_id = window_id
188183
189 self.management = None184 self.management = None
190 self.overview = OverviewPanel(window_id=window_id)185 self.overview = None
186 self.on_show_overview_panel()
187 self.show()
188
189 def on_show_overview_panel(self, widget=None):
190 """Show the overview panel."""
191 for child in self.get_children():
192 self.remove(child)
193
194 self.overview = OverviewPanel(window_id=self._window_id)
191 self.overview.connect('credentials-found',195 self.overview.connect('credentials-found',
192 self.on_show_management_panel)196 self.on_show_management_panel)
193 self.add(self.overview)197 self.add(self.overview)
194 self.show()
195198
196 def on_show_management_panel(self, widget=None,199 def on_show_management_panel(self, widget=None,
197 credentials_are_new=False, token=None):200 credentials_are_new=False, token=None):
198 """Show the netbook (main panel)."""201 """Show the notebook (main panel)."""
199 if self.overview in self.get_children():202 if self.overview in self.get_children():
200 self.remove(self.overview)203 self.remove(self.overview)
201204
@@ -206,6 +209,9 @@
206209
207 self.add(self.management)210 self.add(self.management)
208211
212 self.management.connect('local-device-removed',
213 self.on_show_overview_panel)
214
209215
210class UbuntuOneBin(gtk.VBox):216class UbuntuOneBin(gtk.VBox):
211 """A Ubuntu One bin."""217 """A Ubuntu One bin."""
@@ -505,10 +511,11 @@
505511
506512
507class Device(gtk.VBox, ControlPanelMixin):513class Device(gtk.VBox, ControlPanelMixin):
508 """The devices panel."""514 """The device widget."""
509515
510 DEVICE_CHANGE_ERROR = _('The settings could not be changed,\n'516 DEVICE_CHANGE_ERROR = _('The settings could not be changed,\n'
511 'previous values were restored.')517 'previous values were restored.')
518 DEVICE_REMOVAL_ERROR = _('The device could not be removed.')
512519
513 def __init__(self):520 def __init__(self):
514 gtk.VBox.__init__(self)521 gtk.VBox.__init__(self)
@@ -516,19 +523,25 @@
516523
517 self._updating = False524 self._updating = False
518 self._last_settings = {}525 self._last_settings = {}
526 self.id = None
527 self.is_local = False
519 self.configurable = False528 self.configurable = False
520529
521 self.update(device_id='', device_name='', limit_bandwidth=False,530 self.update(device_id=None, device_name='',
531 is_local=False, configurable=False, limit_bandwidth=False,
522 max_upload_speed=0, max_download_speed=0)532 max_upload_speed=0, max_download_speed=0)
523533
524 self.add(self.itself)534 self.add(self.itself)
525 self.device_id.hide()
526 self.show()535 self.show()
527536
528 self.backend.connect_to_signal('DeviceSettingsChanged',537 self.backend.connect_to_signal('DeviceSettingsChanged',
529 self.on_device_settings_changed)538 self.on_device_settings_changed)
530 self.backend.connect_to_signal('DeviceSettingsChangeError',539 self.backend.connect_to_signal('DeviceSettingsChangeError',
531 self.on_device_settings_change_error)540 self.on_device_settings_change_error)
541 self.backend.connect_to_signal('DeviceRemoved',
542 self.on_device_removed)
543 self.backend.connect_to_signal('DeviceRemovalError',
544 self.on_device_removal_error)
532545
533 def _change_device_settings(self, *args):546 def _change_device_settings(self, *args):
534 """Update backend settings for this device."""547 """Update backend settings for this device."""
@@ -538,8 +551,7 @@
538 # Not disabling the GUI to avoid annyong twitchings551 # Not disabling the GUI to avoid annyong twitchings
539 #self.set_sensitive(False)552 #self.set_sensitive(False)
540 self.warning_label.set_text('')553 self.warning_label.set_text('')
541 self.backend.change_device_settings(self.device_id.get_text(),554 self.backend.change_device_settings(self.id, self.__dict__)
542 self.__dict__)
543555
544 def _block_signals(f):556 def _block_signals(f):
545 """Execute 'f' while having the _updating flag set."""557 """Execute 'f' while having the _updating flag set."""
@@ -563,6 +575,11 @@
563 on_max_upload_speed_value_changed = _change_device_settings575 on_max_upload_speed_value_changed = _change_device_settings
564 on_max_download_speed_value_changed = _change_device_settings576 on_max_download_speed_value_changed = _change_device_settings
565577
578 def on_remove_clicked(self, widget):
579 """Remove button was clicked or activated."""
580 self.backend.remove_device(self.id)
581 self.set_sensitive(False)
582
566 @_block_signals583 @_block_signals
567 def update(self, **kwargs):584 def update(self, **kwargs):
568 """Update according to named parameters.585 """Update according to named parameters.
@@ -571,6 +588,7 @@
571 * device_id (string, not shown to the user)588 * device_id (string, not shown to the user)
572 * device_name (string)589 * device_name (string)
573 * type (either DEVICE_TYPE_PHONE or DEVICE_TYPE_COMPUTER)590 * type (either DEVICE_TYPE_PHONE or DEVICE_TYPE_COMPUTER)
591 * is_local (True/False)
574 * configurable (True/False)592 * configurable (True/False)
575 * if configurable, the following can be set:593 * if configurable, the following can be set:
576 * limit_bandwidth (True/False)594 * limit_bandwidth (True/False)
@@ -579,7 +597,7 @@
579597
580 """598 """
581 if 'device_id' in kwargs:599 if 'device_id' in kwargs:
582 self.device_id.set_text(kwargs['device_id'])600 self.id = kwargs['device_id']
583601
584 if 'device_name' in kwargs:602 if 'device_name' in kwargs:
585 self.device_name.set_markup('<b>%s</b>' % kwargs['device_name'])603 self.device_name.set_markup('<b>%s</b>' % kwargs['device_name'])
@@ -590,6 +608,9 @@
590 self.device_type.set_from_icon_name(dtype.lower(),608 self.device_type.set_from_icon_name(dtype.lower(),
591 gtk.ICON_SIZE_BUTTON)609 gtk.ICON_SIZE_BUTTON)
592610
611 if 'is_local' in kwargs:
612 self.is_local = bool(kwargs['is_local'])
613
593 if 'configurable' in kwargs:614 if 'configurable' in kwargs:
594 self.configurable = bool(kwargs['configurable'])615 self.configurable = bool(kwargs['configurable'])
595 self.throttling.set_visible(self.configurable)616 self.throttling.set_visible(self.configurable)
@@ -607,9 +628,10 @@
607 @property628 @property
608 def __dict__(self):629 def __dict__(self):
609 result = {630 result = {
610 'device_id': self.device_id.get_text(),631 'device_id': self.id,
611 'device_name': self.device_name.get_text(),632 'device_name': self.device_name.get_text(),
612 'device_type': self.device_type.get_icon_name()[0].capitalize(),633 'device_type': self.device_type.get_icon_name()[0].capitalize(),
634 'is_local': bool_str(self.is_local),
613 'configurable': bool_str(self.configurable),635 'configurable': bool_str(self.configurable),
614 'limit_bandwidth': bool_str(self.limit_bandwidth.get_active()),636 'limit_bandwidth': bool_str(self.limit_bandwidth.get_active()),
615 'max_upload_speed': \637 'max_upload_speed': \
@@ -622,7 +644,7 @@
622 @log_call(logger.info)644 @log_call(logger.info)
623 def on_device_settings_changed(self, device_id):645 def on_device_settings_changed(self, device_id):
624 """The change of this device settings succeded."""646 """The change of this device settings succeded."""
625 if device_id != self.device_id.get_text():647 if device_id != self.id:
626 return648 return
627 self.set_sensitive(True)649 self.set_sensitive(True)
628 self.warning_label.set_text('')650 self.warning_label.set_text('')
@@ -631,12 +653,27 @@
631 @log_call(logger.error)653 @log_call(logger.error)
632 def on_device_settings_change_error(self, device_id, error_dict=None):654 def on_device_settings_change_error(self, device_id, error_dict=None):
633 """The change of this device settings failed."""655 """The change of this device settings failed."""
634 if device_id != self.device_id.get_text():656 if device_id != self.id:
635 return657 return
636 self.update(**self._last_settings)658 self.update(**self._last_settings)
637 self._set_warning(self.DEVICE_CHANGE_ERROR, self.warning_label)659 self._set_warning(self.DEVICE_CHANGE_ERROR, self.warning_label)
638 self.set_sensitive(True)660 self.set_sensitive(True)
639661
662 @log_call(logger.warning)
663 def on_device_removed(self, device_id):
664 """The removal of this device succeded."""
665 if device_id != self.id:
666 return
667 self.hide()
668
669 @log_call(logger.error)
670 def on_device_removal_error(self, device_id, error_dict=None):
671 """The removal of this device failed."""
672 if device_id != self.id:
673 return
674 self._set_warning(self.DEVICE_REMOVAL_ERROR, self.warning_label)
675 self.set_sensitive(True)
676
640677
641class DevicesPanel(UbuntuOneBin, ControlPanelMixin):678class DevicesPanel(UbuntuOneBin, ControlPanelMixin):
642 """The devices panel."""679 """The devices panel."""
@@ -650,10 +687,14 @@
650 self.add(self.itself)687 self.add(self.itself)
651 self.show()688 self.show()
652689
690 self._devices = {}
691
653 self.backend.connect_to_signal('DevicesInfoReady',692 self.backend.connect_to_signal('DevicesInfoReady',
654 self.on_devices_info_ready)693 self.on_devices_info_ready)
655 self.backend.connect_to_signal('DevicesInfoError',694 self.backend.connect_to_signal('DevicesInfoError',
656 self.on_devices_info_error)695 self.on_devices_info_error)
696 self.backend.connect_to_signal('DeviceRemoved',
697 self.on_device_removed)
657 self.backend.devices_info()698 self.backend.devices_info()
658699
659 def on_devices_info_ready(self, info):700 def on_devices_info_ready(self, info):
@@ -665,11 +706,22 @@
665 DEVICE_TYPE_COMPUTER)706 DEVICE_TYPE_COMPUTER)
666 device.update(**device_info)707 device.update(**device_info)
667 self.devices.pack_start(device)708 self.devices.pack_start(device)
709 self._devices[device.id] = device
668710
669 @log_call(logger.error)711 @log_call(logger.error)
670 def on_devices_info_error(self, error_dict=None):712 def on_devices_info_error(self, error_dict=None):
671 """Backend notifies of an error when fetching volumes info."""713 """Backend notifies of an error when fetching volumes info."""
672714
715 @log_call(logger.warning)
716 def on_device_removed(self, device_id):
717 """The removal of a device succeded."""
718 if device_id in self._devices:
719 child = self._devices.pop(device_id)
720 self.devices.remove(child)
721
722 if child.is_local:
723 self.emit('local-device-removed')
724
673725
674class ApplicationsPanel(UbuntuOneBin, ControlPanelMixin):726class ApplicationsPanel(UbuntuOneBin, ControlPanelMixin):
675 """The applications panel."""727 """The applications panel."""
@@ -750,6 +802,8 @@
750 self.notebook.insert_page(getattr(self, tab), position=page_num)802 self.notebook.insert_page(getattr(self, tab), position=page_num)
751803
752 self.folders_button.connect('clicked', lambda b: self.folders.load())804 self.folders_button.connect('clicked', lambda b: self.folders.load())
805 sig = 'local-device-removed'
806 self.devices.connect(sig, lambda widget: self.emit(sig))
753807
754 self.backend.account_info()808 self.backend.account_info()
755 self.backend.file_sync_status()809 self.backend.file_sync_status()
@@ -818,3 +872,6 @@
818gobject.signal_new('credentials-found', OverviewPanel,872gobject.signal_new('credentials-found', OverviewPanel,
819 gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,873 gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
820 (gobject.TYPE_BOOLEAN, gobject.TYPE_PYOBJECT))874 (gobject.TYPE_BOOLEAN, gobject.TYPE_PYOBJECT))
875
876gobject.signal_new('local-device-removed', DevicesPanel,
877 gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ())
821878
=== modified file 'ubuntuone/controlpanel/gtk/tests/test_gui.py'
--- ubuntuone/controlpanel/gtk/tests/test_gui.py 2010-12-17 17:25:10 +0000
+++ ubuntuone/controlpanel/gtk/tests/test_gui.py 2010-12-18 17:42:12 +0000
@@ -47,19 +47,21 @@
4747
48FAKE_DEVICE_INFO = {48FAKE_DEVICE_INFO = {
49 'device_id': '1258-6854', 'device_name': 'Baz', 'device_type': 'Computer',49 'device_id': '1258-6854', 'device_name': 'Baz', 'device_type': 'Computer',
50 'configurable': 'True', 'limit_bandwidth': 'True',50 'is_local': 'True', 'configurable': 'True', 'limit_bandwidth': 'True',
51 'max_upload_speed': '1000', 'max_download_speed': '72548',51 'max_upload_speed': '1000', 'max_download_speed': '72548',
52}52}
5353
54FAKE_DEVICES_INFO = [54FAKE_DEVICES_INFO = [
55 {'device_id': '0', 'name': 'Foo', 'type': 'Computer', 'configurable': ''},55 {'device_id': '0', 'name': 'Foo', 'type': 'Computer',
56 {'device_id': '1', 'name': 'Bar', 'type': 'Phone', 'configurable': ''},56 'is_local': '', 'configurable': ''},
57 {'device_id': '1', 'name': 'Bar', 'type': 'Phone',
58 'is_local': '', 'configurable': ''},
57 {'device_id': '2', 'name': 'Z', 'type': 'Computer',59 {'device_id': '2', 'name': 'Z', 'type': 'Computer',
58 'configurable': 'True', 'limit_bandwidth': '',60 'is_local': '', 'configurable': 'True', 'limit_bandwidth': '',
59 'max_upload_speed': '0', 'max_download_speed': '0'},61 'max_upload_speed': '0', 'max_download_speed': '0'},
60 {'device_id': '1258-6854', 'name': 'Baz', 'type': 'Computer',62 {'device_id': '1258-6854', 'name': 'Baz', 'type': 'Computer',
61 'configurable': 'True', 'limit_bandwidth': 'True',63 'is_local': 'True', 'configurable': 'True', 'limit_bandwidth': 'True',
62 'max_upload_speed': '1000', 'max_download_speed': '72548'},64 'max_upload_speed': '1000', 'max_download_speed': '72548'}, # local
63]65]
6466
6567
@@ -128,6 +130,7 @@
128 exposed_methods = [130 exposed_methods = [
129 'account_info', 'devices_info', 'change_device_settings',131 'account_info', 'devices_info', 'change_device_settings',
130 'volumes_info', 'change_volume_settings', 'file_sync_status',132 'volumes_info', 'change_volume_settings', 'file_sync_status',
133 'remove_device',
131 ]134 ]
132135
133136
@@ -356,6 +359,15 @@
356 self.assertEqual(self.ui.management.notebook.get_current_page(),359 self.assertEqual(self.ui.management.notebook.get_current_page(),
357 self.ui.management.FOLDERS_PAGE)360 self.ui.management.FOLDERS_PAGE)
358361
362 def test_local_device_removed_shows_overview_panel(self):
363 """On 'local-device-removed' signal, the overview panel is shown."""
364 self.ui.overview.emit('credentials-found', True, object())
365 self.ui.management.emit('local-device-removed')
366
367 children = self.ui.get_children()
368 self.assertEqual(1, len(children))
369 self.assertTrue(children[0] is self.ui.overview)
370
359371
360class UbuntuOneBinTestCase(BaseTestCase):372class UbuntuOneBinTestCase(BaseTestCase):
361 """The test suite for a Ubuntu One panel."""373 """The test suite for a Ubuntu One panel."""
@@ -907,12 +919,14 @@
907919
908 def assert_device_equal(self, device, expected):920 def assert_device_equal(self, device, expected):
909 """Assert that the device has the values from expected."""921 """Assert that the device has the values from expected."""
910 self.assertEqual(device.device_id.get_text(),922 self.assertEqual(device.id,
911 expected['device_id'])923 expected['device_id'])
912 self.assertEqual(device.device_name.get_text(),924 self.assertEqual(device.device_name.get_text(),
913 expected['device_name'])925 expected['device_name'])
914 self.assertEqual(device.device_type.get_icon_name()[0],926 self.assertEqual(device.device_type.get_icon_name()[0],
915 expected['device_type'].lower())927 expected['device_type'].lower())
928 self.assertEqual(device.is_local,
929 bool(expected['is_local']))
916 self.assertEqual(device.configurable,930 self.assertEqual(device.configurable,
917 bool(expected['configurable']))931 bool(expected['configurable']))
918 self.assertEqual(device.limit_bandwidth.get_active(),932 self.assertEqual(device.limit_bandwidth.get_active(),
@@ -927,7 +941,7 @@
927 """Changing throttling settings updates the backend properly."""941 """Changing throttling settings updates the backend properly."""
928 expected = self.ui.__dict__942 expected = self.ui.__dict__
929 self.assert_backend_called('change_device_settings',943 self.assert_backend_called('change_device_settings',
930 (self.ui.device_id.get_text(), expected))944 (self.ui.id, expected))
931 self.assertEqual(self.ui.warning_label.get_text(), '')945 self.assertEqual(self.ui.warning_label.get_text(), '')
932946
933 def modify_settings(self):947 def modify_settings(self):
@@ -961,16 +975,13 @@
961 """The warning label is cleared."""975 """The warning label is cleared."""
962 self.assertEqual(self.ui.warning_label.get_text(), '')976 self.assertEqual(self.ui.warning_label.get_text(), '')
963977
964 def test_device_id_is_hidden(self):
965 """The device id label is hidden."""
966 self.assertFalse(self.ui.device_id.get_visible())
967
968 def test_default_values(self):978 def test_default_values(self):
969 """Default values are correct."""979 """Default values are correct."""
970 self.assertEqual(self.ui.device_id.get_text(), '')980 self.assertEqual(self.ui.id, None)
971 self.assertEqual(self.ui.device_name.get_text(), '')981 self.assertEqual(self.ui.device_name.get_text(), '')
972 self.assertEqual(self.ui.device_type.get_icon_name()[0],982 self.assertEqual(self.ui.device_type.get_icon_name()[0],
973 gui.DEVICE_TYPE_COMPUTER.lower())983 gui.DEVICE_TYPE_COMPUTER.lower())
984 self.assertEqual(self.ui.is_local, False)
974 self.assertEqual(self.ui.configurable, False)985 self.assertEqual(self.ui.configurable, False)
975 self.assertEqual(self.ui.limit_bandwidth.get_active(), False)986 self.assertEqual(self.ui.limit_bandwidth.get_active(), False)
976 self.assertEqual(self.ui.max_upload_speed.get_value_as_int(), 0)987 self.assertEqual(self.ui.max_upload_speed.get_value_as_int(), 0)
@@ -980,12 +991,6 @@
980 """When updating, the backend is not called."""991 """When updating, the backend is not called."""
981 self.assertEqual(self.ui.backend._called, {})992 self.assertEqual(self.ui.backend._called, {})
982993
983 def test_update_device_id(self):
984 """A device can be updated from a dict."""
985 value = '741-822-963'
986 self.ui.update(device_id=value)
987 self.assertEqual(value, self.ui.device_id.get_text())
988
989 def test_update_device_name(self):994 def test_update_device_name(self):
990 """A device can be updated from a dict."""995 """A device can be updated from a dict."""
991 value = 'The death star'996 value = 'The death star'
@@ -1012,13 +1017,23 @@
1012 self.assertEqual((dtype.lower(), gui.gtk.ICON_SIZE_BUTTON),1017 self.assertEqual((dtype.lower(), gui.gtk.ICON_SIZE_BUTTON),
1013 self.ui.device_type.get_icon_name())1018 self.ui.device_type.get_icon_name())
10141019
1015 def test_update_configurable(self):1020 def test_update_is_not_local(self):
1021 """A device can be updated from a dict."""
1022 self.ui.update(is_local='')
1023 self.assertFalse(self.ui.is_local)
1024
1025 def test_update_is_local(self):
1026 """A device can be updated from a dict."""
1027 self.ui.update(is_local='True')
1028 self.assertTrue(self.ui.is_local)
1029
1030 def test_update_non_configurable(self):
1016 """A device can be updated from a dict."""1031 """A device can be updated from a dict."""
1017 self.ui.update(configurable='')1032 self.ui.update(configurable='')
1018 self.assertFalse(self.ui.configurable)1033 self.assertFalse(self.ui.configurable)
1019 self.assertFalse(self.ui.throttling.get_visible())1034 self.assertFalse(self.ui.throttling.get_visible())
10201035
1021 def test_update_non_configurable(self):1036 def test_update_configurable(self):
1022 """A device can be updated from a dict."""1037 """A device can be updated from a dict."""
1023 self.ui.update(configurable='True')1038 self.ui.update(configurable='True')
1024 self.assertTrue(self.ui.configurable)1039 self.assertTrue(self.ui.configurable)
@@ -1073,12 +1088,15 @@
1073 [self.ui.on_device_settings_changed])1088 [self.ui.on_device_settings_changed])
1074 self.assertEqual(self.ui.backend._signals['DeviceSettingsChangeError'],1089 self.assertEqual(self.ui.backend._signals['DeviceSettingsChangeError'],
1075 [self.ui.on_device_settings_change_error])1090 [self.ui.on_device_settings_change_error])
1091 self.assertEqual(self.ui.backend._signals['DeviceRemoved'],
1092 [self.ui.on_device_removed])
1093 self.assertEqual(self.ui.backend._signals['DeviceRemovalError'],
1094 [self.ui.on_device_removal_error])
10761095
1077 def test_on_device_settings_changed(self):1096 def test_on_device_settings_changed(self):
1078 """When settings were changed for this device, enable it."""1097 """When settings were changed for this device, enable it."""
1079 self.modify_settings()1098 self.modify_settings()
1080 did = self.ui.device_id.get_text()1099 self.ui.on_device_settings_changed(device_id=self.ui.id)
1081 self.ui.on_device_settings_changed(device_id=did)
10821100
1083 self.assertTrue(self.ui.get_sensitive())1101 self.assertTrue(self.ui.get_sensitive())
1084 self.assertEqual(self.ui.warning_label.get_text(), '')1102 self.assertEqual(self.ui.warning_label.get_text(), '')
@@ -1087,8 +1105,7 @@
1087 def test_on_device_settings_change_after_error(self):1105 def test_on_device_settings_change_after_error(self):
1088 """Change success after error."""1106 """Change success after error."""
1089 self.modify_settings()1107 self.modify_settings()
1090 did = self.ui.device_id.get_text()1108 self.ui.on_device_settings_change_error(device_id=self.ui.id) # error
1091 self.ui.on_device_settings_change_error(device_id=did) # change failed
10921109
1093 self.test_on_device_settings_changed()1110 self.test_on_device_settings_changed()
10941111
@@ -1109,8 +1126,7 @@
11091126
1110 self.modify_settings()1127 self.modify_settings()
11111128
1112 did = self.ui.device_id.get_text()1129 self.ui.on_device_settings_change_error(device_id=self.ui.id) # error
1113 self.ui.on_device_settings_change_error(device_id=did) # change failed
11141130
1115 self.assertTrue(self.ui.get_sensitive())1131 self.assertTrue(self.ui.get_sensitive())
1116 self.assert_warning_correct(self.ui.warning_label,1132 self.assert_warning_correct(self.ui.warning_label,
@@ -1120,8 +1136,7 @@
1120 def test_on_device_settings_change_error_after_success(self):1136 def test_on_device_settings_change_error_after_success(self):
1121 """Change error after success."""1137 """Change error after success."""
1122 self.modify_settings()1138 self.modify_settings()
1123 did = self.ui.device_id.get_text()1139 self.ui.on_device_settings_changed(device_id=self.ui.id)
1124 self.ui.on_device_settings_changed(device_id=did)
11251140
1126 self.test_on_device_settings_change_error()1141 self.test_on_device_settings_change_error()
11271142
@@ -1131,6 +1146,49 @@
1131 self.ui.on_device_settings_change_error(device_id='yudo')1146 self.ui.on_device_settings_change_error(device_id='yudo')
1132 self.assertEqual(self.ui.warning_label.get_text(), '')1147 self.assertEqual(self.ui.warning_label.get_text(), '')
11331148
1149 def test_remove(self):
1150 """Clicking on remove calls the backend properly."""
1151 self.ui.is_local = False
1152 self.ui.remove.clicked()
1153
1154 self.assert_backend_called('remove_device', (self.ui.id,))
1155 self.assertFalse(self.ui.get_sensitive(),
1156 'Must be disabled while removing.')
1157
1158 def test_on_device_removed(self):
1159 """On this device removed, hide and destroy."""
1160 self.ui.remove.clicked()
1161 self.ui.on_device_removed(device_id=self.ui.id)
1162
1163 self.assertFalse(self.ui.get_visible(),
1164 'Must not be visible after removed.')
1165
1166 def test_on_device_removed_other_id(self):
1167 """On other device removed, do nothing."""
1168 self.ui.remove.clicked()
1169 self.ui.on_device_removed(device_id='foo')
1170
1171 self.assertTrue(self.ui.get_visible(),
1172 'Must be visible after other device was removed.')
1173
1174 def test_on_device_removal_error(self):
1175 """On this device removal error, re-enable and show error."""
1176 self.ui.remove.clicked()
1177 self.ui.on_device_removal_error(device_id=self.ui.id)
1178
1179 self.assertTrue(self.ui.get_sensitive(),
1180 'Must be enabled after removal error.')
1181 self.assert_warning_correct(self.ui.warning_label,
1182 self.ui.DEVICE_REMOVAL_ERROR)
1183
1184 def test_on_device_removal_error_other_id(self):
1185 """On other device removal error, do nothing."""
1186 self.ui.remove.clicked()
1187 self.ui.on_device_removal_error(device_id='foo')
1188
1189 self.assertFalse(self.ui.get_sensitive(),
1190 'Must be disabled after other device removal error.')
1191
11341192
1135class DevicesTestCase(ControlPanelMixinTestCase):1193class DevicesTestCase(ControlPanelMixinTestCase):
1136 """The test suite for the devices panel."""1194 """The test suite for the devices panel."""
@@ -1156,6 +1214,8 @@
1156 [self.ui.on_devices_info_ready])1214 [self.ui.on_devices_info_ready])
1157 self.assertEqual(self.ui.backend._signals['DevicesInfoError'],1215 self.assertEqual(self.ui.backend._signals['DevicesInfoError'],
1158 [self.ui.on_devices_info_error])1216 [self.ui.on_devices_info_error])
1217 self.assertEqual(self.ui.backend._signals['DeviceRemoved'],
1218 [self.ui.on_device_removed])
11591219
1160 def test_devices_info_is_requested(self):1220 def test_devices_info_is_requested(self):
1161 """The devices info is requested to the backend."""1221 """The devices info is requested to the backend."""
@@ -1171,12 +1231,13 @@
1171 for child, device in zip(children, FAKE_DEVICES_INFO):1231 for child, device in zip(children, FAKE_DEVICES_INFO):
1172 self.assertIsInstance(child, gui.Device)1232 self.assertIsInstance(child, gui.Device)
11731233
1174 self.assertEqual(device['device_id'],1234 self.assertEqual(device['device_id'], child.id)
1175 child.device_id.get_text())
1176 self.assertEqual(device['device_name'],1235 self.assertEqual(device['device_name'],
1177 child.device_name.get_text())1236 child.device_name.get_text())
1178 self.assertEqual(device['device_type'].lower(),1237 self.assertEqual(device['device_type'].lower(),
1179 child.device_type.get_icon_name()[0])1238 child.device_type.get_icon_name()[0])
1239 self.assertEqual(bool(device['is_local']),
1240 child.is_local)
1180 self.assertEqual(bool(device['configurable']),1241 self.assertEqual(bool(device['configurable']),
1181 child.configurable)1242 child.configurable)
11821243
@@ -1190,9 +1251,51 @@
1190 self.assertEqual(value,1251 self.assertEqual(value,
1191 child.max_download_speed.get_value_as_int())1252 child.max_download_speed.get_value_as_int())
11921253
1254 def test_on_devices_info_ready_have_devices_cached(self):
1255 """The devices are cached for further removal."""
1256 self.ui.on_devices_info_ready(FAKE_DEVICES_INFO)
1257
1258 for child in self.ui.devices.get_children():
1259 self.assertTrue(self.ui._devices[child.id] is child)
1260
1193 def test_on_devices_info_error(self):1261 def test_on_devices_info_error(self):
1194 """The devices info couldn't be retrieved."""1262 """The devices info couldn't be retrieved."""
1195 self.ui.on_devices_info_error()1263 self.ui.on_devices_info_error()
1264 # add test!
1265
1266 def test_on_device_removed(self):
1267 """When a child device was removed, remove and destroy."""
1268 self.ui.on_devices_info_ready(FAKE_DEVICES_INFO)
1269 did = FAKE_DEVICES_INFO[0]['device_id']
1270 device = self.ui._devices[did]
1271 self.ui.on_device_removed(device_id=did)
1272
1273 self.assertTrue(device not in self.ui.devices.get_children())
1274 self.assertTrue(did not in self.ui._devices)
1275
1276 def test_on_local_device_removed(self):
1277 """Removing the local device emits local-device-removed."""
1278 self.ui.connect('local-device-removed', self._set_called)
1279
1280 self.ui.on_devices_info_ready(FAKE_DEVICES_INFO)
1281 local_device = FAKE_DEVICES_INFO[-1]
1282 assert bool(local_device['is_local'])
1283 local_device_id = local_device['device_id']
1284 assert self.ui._devices[local_device_id].is_local
1285
1286 self.ui.on_device_removed(device_id=local_device_id)
1287
1288 self.assertEqual(self._called, ((self.ui,), {}))
1289
1290 def test_on_device_removed_for_no_child_device(self):
1291 """On other device removed, do nothing."""
1292 self.ui.on_devices_info_ready(FAKE_DEVICES_INFO)
1293 old_devices = self.ui.devices.get_children()
1294
1295 self.ui.on_device_removed(device_id='foo')
1296
1297 new_devices = self.ui.devices.get_children()
1298 self.assertEqual(new_devices, old_devices)
11961299
11971300
1198class ApplicationsTestCase(ControlPanelMixinTestCase):1301class ApplicationsTestCase(ControlPanelMixinTestCase):
@@ -1413,3 +1516,11 @@
1413 self.assert_warning_correct(self.ui.status_label,1516 self.assert_warning_correct(self.ui.status_label,
1414 self.ui.FILE_SYNC_ERROR)1517 self.ui.FILE_SYNC_ERROR)
1415 self.assertFalse(self.ui.status_label.active)1518 self.assertFalse(self.ui.status_label.active)
1519
1520 def test_local_device_removed_is_emitted(self):
1521 """Signal local-device-removed is sent when DevicesPanel emits it."""
1522 self.ui.connect('local-device-removed', self._set_called)
1523
1524 self.ui.devices.emit('local-device-removed')
1525
1526 self.assertEqual(self._called, ((self.ui,), {}))
14161527
=== modified file 'ubuntuone/controlpanel/tests/test_backend.py'
--- ubuntuone/controlpanel/tests/test_backend.py 2010-12-18 17:42:11 +0000
+++ ubuntuone/controlpanel/tests/test_backend.py 2010-12-18 17:42:12 +0000
@@ -114,9 +114,11 @@
114 "device_id": "ComputerABCDEF01234token",114 "device_id": "ComputerABCDEF01234token",
115 "name": "Ubuntu One @ darkstar",115 "name": "Ubuntu One @ darkstar",
116 "type": "Computer",116 "type": "Computer",
117 "is_local": '',
117 "configurable": '',118 "configurable": '',
118 },119 },
119 {120 {
121 'is_local': 'True',
120 'configurable': 'True',122 'configurable': 'True',
121 'device_id': 'ComputerABC1234DEF',123 'device_id': 'ComputerABC1234DEF',
122 'limit_bandwidth': '',124 'limit_bandwidth': '',
@@ -130,6 +132,7 @@
130 "name": "Nokia E65",132 "name": "Nokia E65",
131 "type": "Phone",133 "type": "Phone",
132 "configurable": '',134 "configurable": '',
135 "is_local": '',
133 },136 },
134]137]
135138
@@ -301,6 +304,16 @@
301 token = yield self.be.get_token()304 token = yield self.be.get_token()
302 self.assertEqual(token, SAMPLE_CREDENTIALS["token"])305 self.assertEqual(token, SAMPLE_CREDENTIALS["token"])
303306
307 @inlineCallbacks
308 def test_device_is_local(self):
309 """The device_is_local returns the right result."""
310 result = yield self.be.device_is_local(self.local_token)
311 self.assertTrue(result)
312
313 did = EXPECTED_DEVICES_INFO[0]['device_id']
314 result = yield self.be.device_is_local(did)
315 self.assertFalse(result)
316
304317
305class BackendAccountTestCase(BackendBasicTestCase):318class BackendAccountTestCase(BackendBasicTestCase):
306 """Account tests for the backend."""319 """Account tests for the backend."""
@@ -345,11 +358,23 @@
345 """The remove_device method calls the right api."""358 """The remove_device method calls the right api."""
346 dtype, did = "Computer", "SAMPLE-TOKEN"359 dtype, did = "Computer", "SAMPLE-TOKEN"
347 device_id = dtype + did360 device_id = dtype + did
348 apiurl = DEVICE_REMOVE_API % (dtype, did)361 apiurl = DEVICE_REMOVE_API % (dtype.lower(), did)
349 # pylint: disable=E1101362 # pylint: disable=E1101
350 self.be.wc.results[apiurl] = SAMPLE_DEVICES_JSON363 self.be.wc.results[apiurl] = SAMPLE_DEVICES_JSON
351 result = yield self.be.remove_device(device_id)364 result = yield self.be.remove_device(device_id)
352 self.assertEqual(result, device_id)365 self.assertEqual(result, device_id)
366 # credentials were not cleared
367 self.assertEqual(MockDBusClient.creds, SAMPLE_CREDENTIALS)
368
369 @inlineCallbacks
370 def test_remove_device_clear_credentials_if_local_device(self):
371 """The remove_device method clears the credentials if is local."""
372 apiurl = DEVICE_REMOVE_API % ('computer', SAMPLE_CREDENTIALS['token'])
373 # pylint: disable=E1101
374 self.be.wc.results[apiurl] = SAMPLE_DEVICES_JSON
375 yield self.be.remove_device(self.local_token)
376 # credentials were cleared
377 self.assertEqual(MockDBusClient.creds, None)
353378
354 @inlineCallbacks379 @inlineCallbacks
355 def test_remove_device_fails(self):380 def test_remove_device_fails(self):
356381
=== modified file 'ubuntuone/controlpanel/webclient.py'
--- ubuntuone/controlpanel/webclient.py 2010-12-02 16:23:03 +0000
+++ ubuntuone/controlpanel/webclient.py 2010-12-18 17:42:12 +0000
@@ -48,22 +48,24 @@
4848
49 def _handler(self, session, msg, d):49 def _handler(self, session, msg, d):
50 """Handle the result of an http message."""50 """Handle the result of an http message."""
51 logger.debug("WebClient: got http response: %d", msg.status_code)51 logger.debug("WebClient: got http response %d for uri %r",
52 msg.status_code, msg.get_uri().to_string(False))
53 data = msg.response_body.data
52 if msg.status_code == 200:54 if msg.status_code == 200:
53 result = simplejson.loads(msg.response_body.data)55 result = simplejson.loads(data)
54 d.callback(result)56 d.callback(result)
55 else:57 else:
56 e = WebClientError(msg.status_code, msg)58 e = WebClientError(msg.status_code, data)
57 d.errback(e)59 d.errback(e)
5860
59 def _call_api_with_creds(self, credentials, api_name):61 def _call_api_with_creds(self, credentials, api_name):
60 """Get a given url from the webservice with credentials."""62 """Get a given url from the webservice with credentials."""
61 url = self.base_url + api_name63 url = (self.base_url + api_name).encode('utf-8')
62 method = "GET"64 method = "GET"
65 logger.debug("WebClient: getting url: %s, %s", method, url)
63 msg = Soup.Message.new(method, url)66 msg = Soup.Message.new(method, url)
64 add_oauth_headers(msg.request_headers.append, method, url, credentials)67 add_oauth_headers(msg.request_headers.append, method, url, credentials)
65 d = defer.Deferred()68 d = defer.Deferred()
66 logger.debug("WebClient: getting url: %s", url)
67 self.session.queue_message(msg, self._handler, d)69 self.session.queue_message(msg, self._handler, d)
68 return d70 return d
6971

Subscribers

People subscribed via source and target branches