Merge lp:~nataliabidart/ubuntuone-control-panel/stable-3-0-update-2.99.92 into lp:ubuntuone-control-panel/stable-3-0
- stable-3-0-update-2.99.92
- Merge into stable-3-0
| Status: | Merged | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Approved by: | Natalia Bidart on 2012-04-03 | ||||||||||||||||||||||||||||
| Approved revision: | 258 | ||||||||||||||||||||||||||||
| Merged at revision: | 257 | ||||||||||||||||||||||||||||
| Proposed branch: | lp:~nataliabidart/ubuntuone-control-panel/stable-3-0-update-2.99.92 | ||||||||||||||||||||||||||||
| Merge into: | lp:ubuntuone-control-panel/stable-3-0 | ||||||||||||||||||||||||||||
| Diff against target: |
1335 lines (+334/-437) 19 files modified
ubuntuone/controlpanel/backend.py (+13/-31) ubuntuone/controlpanel/dbustests/test_sd_client/test_linux.py (+0/-94) ubuntuone/controlpanel/gui/__init__.py (+1/-1) ubuntuone/controlpanel/gui/qt/controlpanel.py (+3/-4) ubuntuone/controlpanel/gui/qt/folders.py (+3/-2) ubuntuone/controlpanel/gui/qt/gui.py (+1/-2) ubuntuone/controlpanel/gui/qt/main/__init__.py (+2/-1) ubuntuone/controlpanel/gui/qt/main/tests/test_main.py (+10/-1) ubuntuone/controlpanel/gui/qt/tests/test_folders.py (+13/-1) ubuntuone/controlpanel/gui/qt/tests/test_preferences.py (+15/-0) ubuntuone/controlpanel/gui/qt/tests/test_wizard.py (+12/-1) ubuntuone/controlpanel/gui/qt/wizard.py (+4/-8) ubuntuone/controlpanel/sd_client/__init__.py (+10/-13) ubuntuone/controlpanel/sd_client/linux.py (+0/-46) ubuntuone/controlpanel/tests/test_backend.py (+66/-105) ubuntuone/controlpanel/tests/test_sd_client.py (+23/-17) ubuntuone/controlpanel/utils/__init__.py (+8/-4) ubuntuone/controlpanel/utils/tests/test_windows.py (+106/-71) ubuntuone/controlpanel/utils/windows.py (+44/-35) |
||||||||||||||||||||||||||||
| To merge this branch: | bzr merge lp:~nataliabidart/ubuntuone-control-panel/stable-3-0-update-2.99.92 | ||||||||||||||||||||||||||||
| Related bugs: |
|
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| Alejandro J. Cura (community) | 2012-04-03 | Approve on 2012-04-03 | |
|
Review via email:
|
|||
Commit Message
- Updating from trunk up to revno 308:
[ Brian Curtin <email address hidden> ]
- Match test behavior with updated functionality.
[ Diego Sarmentero <email address hidden> ]
- Removing encoding to return unicode (LP: #966513).
- Using limit_bandwidth attribute to properly process the info dict
for preferences (LP: #944256).
[ Natalia B. Bidart <email address hidden> ]
- When user rejects the License, also uninstall the application
when in Windows (LP: #968327).
- Remove custom path validation and use the one provided by syncdaemon
(LP: #824252).
- Make use of the new feature from syncdaemon where 'refresh_volumes'
returns a deferred that gets fired when the server info is ready
(LP: #851810).
- Ensured that Folders' tree view has proper texts in the columns to
have proper column widths (LP: #965175).
[ Roberto Alsina <email address hidden> ]
- Fixed the combination of --minimized --with-icon options
(LP: #968369).
Description of the Change
- 258. By Natalia Bidart on 2012-04-03
-
Attaching bug numbers.
Preview Diff
| 1 | === modified file 'ubuntuone/controlpanel/backend.py' |
| 2 | --- ubuntuone/controlpanel/backend.py 2012-03-01 22:05:51 +0000 |
| 3 | +++ ubuntuone/controlpanel/backend.py 2012-04-03 13:15:23 +0000 |
| 4 | @@ -1,9 +1,6 @@ |
| 5 | # -*- coding: utf-8 -*- |
| 6 | - |
| 7 | -# Authors: Alejandro J. Cura <alecu@canonical.com> |
| 8 | -# Authors: Natalia B. Bidart <nataliabidart@canonical.com> |
| 9 | # |
| 10 | -# Copyright 2010 Canonical Ltd. |
| 11 | +# Copyright 2010-2012 Canonical Ltd. |
| 12 | # |
| 13 | # This program is free software: you can redistribute it and/or modify it |
| 14 | # under the terms of the GNU General Public License version 3, as published |
| 15 | @@ -26,11 +23,7 @@ |
| 16 | from functools import wraps |
| 17 | |
| 18 | from twisted.internet.defer import inlineCallbacks, returnValue |
| 19 | -# No name 'is_link' in module 'ubuntuone.platform' |
| 20 | -# pylint: disable=E0611, F0401 |
| 21 | -from ubuntuone.platform import is_link |
| 22 | from ubuntuone.platform.credentials import CredentialsManagementTool |
| 23 | -# pylint: enable=E0611, F0401 |
| 24 | |
| 25 | from ubuntuone.controlpanel import sd_client, replication_client |
| 26 | from ubuntuone.controlpanel.logger import setup_logging, log_call |
| 27 | @@ -599,7 +592,7 @@ |
| 28 | |
| 29 | @log_call(logger.debug) |
| 30 | @inlineCallbacks |
| 31 | - def volumes_info(self, with_storage_info=True): |
| 32 | + def volumes_info(self, with_storage_info=True, refresh=False): |
| 33 | """Get the volumes info.""" |
| 34 | self._volumes = {} |
| 35 | |
| 36 | @@ -612,6 +605,9 @@ |
| 37 | else: |
| 38 | free_bytes = account['quota_total'] - account['quota_used'] |
| 39 | |
| 40 | + if refresh: |
| 41 | + yield self.sd_client.refresh_volumes() |
| 42 | + |
| 43 | root_dir = yield self.sd_client.get_root_dir() |
| 44 | shares_dir = yield self.sd_client.get_shares_dir() |
| 45 | shares_dir_link = yield self.sd_client.get_shares_dir_link() |
| 46 | @@ -717,28 +713,9 @@ |
| 47 | yield self.sd_client.create_folder(path=folder_path) |
| 48 | |
| 49 | @log_call(logger.debug) |
| 50 | - @inlineCallbacks |
| 51 | def validate_path_for_folder(self, folder_path): |
| 52 | """Validate 'folder_path' for folder creation.""" |
| 53 | - user_home = yield self.get_home_dir() |
| 54 | - folder_path = append_path_sep(folder_path) |
| 55 | - |
| 56 | - # handle folder_path not within '~' or links |
| 57 | - # XXX is_link expects bytes, see bug #824252 |
| 58 | - if not folder_path.startswith(user_home) or is_link( |
| 59 | - folder_path.encode('utf-8')): |
| 60 | - returnValue(False) |
| 61 | - |
| 62 | - # handle folder_path nested with a existing cloud folder |
| 63 | - volumes = yield self.volumes_info(with_storage_info=False) |
| 64 | - for _, _, data in volumes: |
| 65 | - for volume in data: |
| 66 | - cloud_folder = append_path_sep(volume['path']) |
| 67 | - if (folder_path.startswith(cloud_folder) or |
| 68 | - cloud_folder.startswith(folder_path)): |
| 69 | - returnValue(False) |
| 70 | - |
| 71 | - returnValue(True) |
| 72 | + return self.sd_client.validate_path(folder_path) |
| 73 | |
| 74 | @log_call(logger.debug) |
| 75 | @inlineCallbacks |
| 76 | @@ -787,8 +764,13 @@ |
| 77 | result[name] = bool(value) |
| 78 | |
| 79 | limits = yield self.sd_client.get_throttling_limits() |
| 80 | - result[DOWNLOAD_KEY] = limits['download'] |
| 81 | - result[UPLOAD_KEY] = limits['upload'] |
| 82 | + limits_enabled = yield self.sd_client.bandwidth_throttling_enabled() |
| 83 | + if limits_enabled: |
| 84 | + result[DOWNLOAD_KEY] = limits['download'] |
| 85 | + result[UPLOAD_KEY] = limits['upload'] |
| 86 | + else: |
| 87 | + result[DOWNLOAD_KEY] = -1 |
| 88 | + result[UPLOAD_KEY] = -1 |
| 89 | |
| 90 | returnValue(result) |
| 91 | |
| 92 | |
| 93 | === removed file 'ubuntuone/controlpanel/dbustests/test_sd_client/test_linux.py' |
| 94 | --- ubuntuone/controlpanel/dbustests/test_sd_client/test_linux.py 2011-10-24 21:48:27 +0000 |
| 95 | +++ ubuntuone/controlpanel/dbustests/test_sd_client/test_linux.py 1970-01-01 00:00:00 +0000 |
| 96 | @@ -1,94 +0,0 @@ |
| 97 | -# -*- coding: utf-8 -*- |
| 98 | - |
| 99 | -# Authors: Alejandro J. Cura <alecu@canonical.com> |
| 100 | -# Authors: Natalia B. Bidart <natalia.bidart@canonical.com> |
| 101 | -# |
| 102 | -# Copyright 2010 Canonical Ltd. |
| 103 | -# |
| 104 | -# This program is free software: you can redistribute it and/or modify it |
| 105 | -# under the terms of the GNU General Public License version 3, as published |
| 106 | -# by the Free Software Foundation. |
| 107 | -# |
| 108 | -# This program is distributed in the hope that it will be useful, but |
| 109 | -# WITHOUT ANY WARRANTY; without even the implied warranties of |
| 110 | -# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
| 111 | -# PURPOSE. See the GNU General Public License for more details. |
| 112 | -# |
| 113 | -# You should have received a copy of the GNU General Public License along |
| 114 | -# with this program. If not, see <http://www.gnu.org/licenses/>. |
| 115 | - |
| 116 | -"""Tests for the DBus service when accessing SyncDaemon.""" |
| 117 | - |
| 118 | -import dbus |
| 119 | - |
| 120 | -from twisted.internet import defer |
| 121 | - |
| 122 | -from ubuntuone.platform.linux import dbus_interface as sd_dbus_iface |
| 123 | - |
| 124 | -from ubuntuone.controlpanel import sd_client |
| 125 | -from ubuntuone.controlpanel.dbustests import DBusClientTestCase |
| 126 | - |
| 127 | - |
| 128 | -SD_DBUS_IFACE_NAME = sd_dbus_iface.DBUS_IFACE_NAME |
| 129 | -SD_DBUS_IFACE_STATUS_NAME = sd_dbus_iface.DBUS_IFACE_STATUS_NAME |
| 130 | - |
| 131 | -# pylint, you have to go to decorator's school |
| 132 | -# pylint: disable=C0322 |
| 133 | - |
| 134 | -# Access to a protected member of a client class |
| 135 | -# pylint: disable=W0212 |
| 136 | - |
| 137 | - |
| 138 | -class StatusMockDBusSyncDaemon(dbus.service.Object): |
| 139 | - """A mock object that mimicks syncdaemon regarding the Status iface.""" |
| 140 | - |
| 141 | - state_dict = { |
| 142 | - 'name': 'TEST', |
| 143 | - 'description': 'Some test state, nothing else.', |
| 144 | - 'is_error': '', |
| 145 | - 'is_connected': 'True', |
| 146 | - 'is_online': '', |
| 147 | - 'queues': 'GORGEOUS', |
| 148 | - 'connection': '', |
| 149 | - } |
| 150 | - |
| 151 | - def _get_current_state(self): |
| 152 | - """Get the current status of the system.""" |
| 153 | - return self.state_dict |
| 154 | - |
| 155 | - @dbus.service.method(SD_DBUS_IFACE_STATUS_NAME, |
| 156 | - in_signature='', out_signature='a{ss}') |
| 157 | - def current_status(self): |
| 158 | - """Return the current faked status of the system.""" |
| 159 | - return self._get_current_state() |
| 160 | - |
| 161 | - # pylint: disable=C0103 |
| 162 | - # Invalid name "StatusChanged" |
| 163 | - |
| 164 | - @dbus.service.signal(SD_DBUS_IFACE_STATUS_NAME) |
| 165 | - def StatusChanged(self, status): |
| 166 | - """Fire a signal to notify that the status of the system changed.""" |
| 167 | - |
| 168 | - def emit_status_changed(self, state=None): |
| 169 | - """Emit StatusChanged.""" |
| 170 | - self.StatusChanged(self._get_current_state()) |
| 171 | - |
| 172 | - |
| 173 | -class StatusTestCase(DBusClientTestCase): |
| 174 | - """Test for the status dbus client methods.""" |
| 175 | - |
| 176 | - @defer.inlineCallbacks |
| 177 | - def setUp(self): |
| 178 | - yield super(StatusTestCase, self).setUp() |
| 179 | - self.register_mockserver(SD_DBUS_IFACE_NAME, |
| 180 | - "/status", StatusMockDBusSyncDaemon) |
| 181 | - |
| 182 | - def test_set_status_changed_handler(self): |
| 183 | - """A proper callback can be connected to StatusChanged signal.""" |
| 184 | - client = sd_client.SyncDaemonClient() |
| 185 | - _, sig = client.set_status_changed_handler(self._set_called) |
| 186 | - |
| 187 | - self.assertEqual(sig._handler, self._set_called) |
| 188 | - self.assertEqual(sig._member, 'StatusChanged') |
| 189 | - self.assertEqual(sig._path, '/status') |
| 190 | - self.assertEqual(sig._interface, SD_DBUS_IFACE_STATUS_NAME) |
| 191 | |
| 192 | === modified file 'ubuntuone/controlpanel/gui/__init__.py' |
| 193 | --- ubuntuone/controlpanel/gui/__init__.py 2012-03-20 15:11:56 +0000 |
| 194 | +++ ubuntuone/controlpanel/gui/__init__.py 2012-04-03 13:15:23 +0000 |
| 195 | @@ -204,7 +204,7 @@ |
| 196 | MAIN_PREFERENCES_TAB = _('Settings') |
| 197 | MAIN_WINDOW_TITLE = _('%(app_name)s Control Panel') |
| 198 | MUSIC_DISPLAY_NAME = _('Purchased Music') |
| 199 | -MUSIC_REAL_PATH = '.ubuntuone/Purchased from Ubuntu One' |
| 200 | +MUSIC_REAL_PATH = u'.ubuntuone/Purchased from Ubuntu One' |
| 201 | MY_FOLDERS = _('My folders') |
| 202 | NAME_NOT_SET = _('[unknown user name]') |
| 203 | NETWORK_OFFLINE = _('An internet connection is required to join or sign ' |
| 204 | |
| 205 | === modified file 'ubuntuone/controlpanel/gui/qt/controlpanel.py' |
| 206 | --- ubuntuone/controlpanel/gui/qt/controlpanel.py 2012-03-21 19:17:21 +0000 |
| 207 | +++ ubuntuone/controlpanel/gui/qt/controlpanel.py 2012-04-03 13:15:23 +0000 |
| 208 | @@ -1,5 +1,5 @@ |
| 209 | # -*- coding: utf-8 -*- |
| 210 | - |
| 211 | +# |
| 212 | # Copyright 2012 Canonical Ltd. |
| 213 | # |
| 214 | # This program is free software: you can redistribute it and/or modify it |
| 215 | @@ -174,7 +174,6 @@ |
| 216 | @log_call(logger.info) |
| 217 | def start_from_license(self): |
| 218 | """Use the license page as first page.""" |
| 219 | - # license |
| 220 | - self.ui.wizard.setStartId(self.ui.wizard.pages[ |
| 221 | - self.ui.wizard.license_page]) |
| 222 | + license_id = self.ui.wizard.pages[self.ui.wizard.license_page] |
| 223 | + self.ui.wizard.setStartId(license_id) |
| 224 | self.ui.wizard.restart() |
| 225 | |
| 226 | === modified file 'ubuntuone/controlpanel/gui/qt/folders.py' |
| 227 | --- ubuntuone/controlpanel/gui/qt/folders.py 2012-03-20 13:05:20 +0000 |
| 228 | +++ ubuntuone/controlpanel/gui/qt/folders.py 2012-04-03 13:15:23 +0000 |
| 229 | @@ -123,7 +123,7 @@ |
| 230 | self.ui.folders.headerItem().setText(FOLDER_NAME_COL, |
| 231 | FOLDERS_COLUMN_NAME) |
| 232 | self.ui.folders.headerItem().setText(SUBSCRIPTION_COL, |
| 233 | - FOLDERS_COLUMN_SYNC_LOCALLY) |
| 234 | + ALWAYS_SUBSCRIBED) |
| 235 | self.ui.folders.headerItem().setText(EXPLORE_COL, |
| 236 | FOLDERS_COLUMN_EXPLORE) |
| 237 | headers = self.ui.folders.header() |
| 238 | @@ -153,7 +153,8 @@ |
| 239 | def load(self): |
| 240 | """Load specific tab info.""" |
| 241 | self.is_processing = True |
| 242 | - info = yield self.backend.volumes_info(with_storage_info=False) |
| 243 | + info = yield self.backend.volumes_info(with_storage_info=False, |
| 244 | + refresh=self.remote_folders) |
| 245 | self.process_info(info) |
| 246 | |
| 247 | @handle_errors(logger=logger) |
| 248 | |
| 249 | === modified file 'ubuntuone/controlpanel/gui/qt/gui.py' |
| 250 | --- ubuntuone/controlpanel/gui/qt/gui.py 2012-03-26 13:23:57 +0000 |
| 251 | +++ ubuntuone/controlpanel/gui/qt/gui.py 2012-04-03 13:15:23 +0000 |
| 252 | @@ -43,8 +43,7 @@ |
| 253 | self.ui.setupUi(self) |
| 254 | self.close_callback = close_callback |
| 255 | self._setup() |
| 256 | - self.quit_action = QtGui.QAction(self, |
| 257 | - triggered=self.close) |
| 258 | + self.quit_action = QtGui.QAction(self, triggered=self.close) |
| 259 | self.quit_action.setShortcuts(["Ctrl+q", "Ctrl+w"]) |
| 260 | self.addAction(self.quit_action) |
| 261 | self.installer = installer |
| 262 | |
| 263 | === modified file 'ubuntuone/controlpanel/gui/qt/main/__init__.py' |
| 264 | --- ubuntuone/controlpanel/gui/qt/main/__init__.py 2012-03-27 13:41:19 +0000 |
| 265 | +++ ubuntuone/controlpanel/gui/qt/main/__init__.py 2012-04-03 13:15:23 +0000 |
| 266 | @@ -98,7 +98,8 @@ |
| 267 | icon, window = start(lambda: source.main_quit(app), |
| 268 | minimized=minimized, with_icon=with_icon, |
| 269 | installer=installer) |
| 270 | - window.switch_to(switch_to) |
| 271 | + if window: |
| 272 | + window.switch_to(switch_to) |
| 273 | # pylint: enable=W0612 |
| 274 | if icon: |
| 275 | app.new_instance.connect(icon.restore_window) |
| 276 | |
| 277 | === modified file 'ubuntuone/controlpanel/gui/qt/main/tests/test_main.py' |
| 278 | --- ubuntuone/controlpanel/gui/qt/main/tests/test_main.py 2012-03-27 13:49:49 +0000 |
| 279 | +++ ubuntuone/controlpanel/gui/qt/main/tests/test_main.py 2012-04-03 13:15:23 +0000 |
| 280 | @@ -96,8 +96,11 @@ |
| 281 | self.window = None |
| 282 | |
| 283 | def __call__(self, *args, **kwargs): |
| 284 | + if kwargs.get('minimized', False): |
| 285 | + self.window = None |
| 286 | + else: |
| 287 | + self.window = FakeMainWindow() |
| 288 | self.args = (args, kwargs) |
| 289 | - self.window = FakeMainWindow() |
| 290 | return None, self.window |
| 291 | |
| 292 | |
| 293 | @@ -166,6 +169,12 @@ |
| 294 | self.assertEqual(self.start.args[1], |
| 295 | {'minimized': False, 'with_icon': False, 'installer': True}) |
| 296 | |
| 297 | + def test_minimized_with_icon_options(self): |
| 298 | + """Ensure you can be minimized and with icon at the same time.""" |
| 299 | + main.main([sys.argv[0], "--minimized", "--with-icon"]) |
| 300 | + self.assertEqual(self.start.args[1], |
| 301 | + {'minimized': True, 'with_icon': True, 'installer': False}) |
| 302 | + |
| 303 | def test_translator(self): |
| 304 | """Ensure the Qt translator is loaded.""" |
| 305 | main.main([sys.argv[0]]) |
| 306 | |
| 307 | === modified file 'ubuntuone/controlpanel/gui/qt/tests/test_folders.py' |
| 308 | --- ubuntuone/controlpanel/gui/qt/tests/test_folders.py 2012-03-23 14:04:57 +0000 |
| 309 | +++ ubuntuone/controlpanel/gui/qt/tests/test_folders.py 2012-04-03 13:15:23 +0000 |
| 310 | @@ -187,7 +187,8 @@ |
| 311 | |
| 312 | def test_info_is_requested_on_load(self): |
| 313 | """The volumes info is requested to the backend.""" |
| 314 | - self.assert_backend_called('volumes_info', with_storage_info=False) |
| 315 | + self.assert_backend_called('volumes_info', with_storage_info=False, |
| 316 | + refresh=self.ui.remote_folders) |
| 317 | |
| 318 | def test_process_info(self): |
| 319 | """The volumes info is processed when ready.""" |
| 320 | @@ -409,6 +410,17 @@ |
| 321 | item) |
| 322 | it += 1 |
| 323 | |
| 324 | + def test_tree_view_header(self): |
| 325 | + """The tree view header is hidden but the text is correct.""" |
| 326 | + self.assertFalse(self.ui.ui.folders.header().isVisible()) |
| 327 | + |
| 328 | + name = self.ui.ui.folders.headerItem().text(gui.FOLDER_NAME_COL) |
| 329 | + self.assertEqual(name, gui.FOLDERS_COLUMN_NAME) |
| 330 | + name = self.ui.ui.folders.headerItem().text(gui.SUBSCRIPTION_COL) |
| 331 | + self.assertEqual(name, gui.ALWAYS_SUBSCRIBED) |
| 332 | + name = self.ui.ui.folders.headerItem().text(gui.EXPLORE_COL) |
| 333 | + self.assertEqual(name, gui.FOLDERS_COLUMN_EXPLORE) |
| 334 | + |
| 335 | def test_share_publish_button(self): |
| 336 | """When clicking the share/publish button, the proper url is opened.""" |
| 337 | self.assertTrue(self.ui.ui.share_publish_button.isVisible()) |
| 338 | |
| 339 | === modified file 'ubuntuone/controlpanel/gui/qt/tests/test_preferences.py' |
| 340 | --- ubuntuone/controlpanel/gui/qt/tests/test_preferences.py 2012-03-01 22:05:51 +0000 |
| 341 | +++ ubuntuone/controlpanel/gui/qt/tests/test_preferences.py 2012-04-03 13:15:23 +0000 |
| 342 | @@ -76,6 +76,21 @@ |
| 343 | |
| 344 | self.assertFalse(self.ui.is_processing) |
| 345 | |
| 346 | + def test_process_info_limit_bandwidth(self): |
| 347 | + """The ui is not processing when contents are load.""" |
| 348 | + self.ui.process_info(SAMPLE_SETTINGS) |
| 349 | + |
| 350 | + self.assertTrue(self.ui.ui.limit_uploads_checkbox.isChecked()) |
| 351 | + self.assertTrue(self.ui.ui.limit_downloads_checkbox.isChecked()) |
| 352 | + |
| 353 | + settings = SAMPLE_SETTINGS.copy() |
| 354 | + settings[gui.backend.DOWNLOAD_KEY] = -1 |
| 355 | + settings[gui.backend.UPLOAD_KEY] = -1 |
| 356 | + self.ui.process_info(settings) |
| 357 | + |
| 358 | + self.assertFalse(self.ui.ui.limit_uploads_checkbox.isChecked()) |
| 359 | + self.assertFalse(self.ui.ui.limit_downloads_checkbox.isChecked()) |
| 360 | + |
| 361 | def test_info_is_requested_on_load(self): |
| 362 | """The info is requested to the backend.""" |
| 363 | self.assert_backend_called('file_sync_settings_info') |
| 364 | |
| 365 | === modified file 'ubuntuone/controlpanel/gui/qt/tests/test_wizard.py' |
| 366 | --- ubuntuone/controlpanel/gui/qt/tests/test_wizard.py 2012-03-26 21:00:47 +0000 |
| 367 | +++ ubuntuone/controlpanel/gui/qt/tests/test_wizard.py 2012-04-03 13:15:23 +0000 |
| 368 | @@ -157,6 +157,7 @@ |
| 369 | @defer.inlineCallbacks |
| 370 | def setUp(self): |
| 371 | yield super(UbuntuOneWizardTestCase, self).setUp() |
| 372 | + self.patch(gui.utils, 'uninstall_application', self.fail) |
| 373 | self.patch(self.ui.confirm_dialog, 'exec_', |
| 374 | lambda: self.confirm_response) |
| 375 | |
| 376 | @@ -260,7 +261,7 @@ |
| 377 | button.click() |
| 378 | |
| 379 | self.assertEqual(self._called, (signal_args, {}), |
| 380 | - msg % (name, signal, signal_args)) |
| 381 | + msg % (name, signal, signal_args)) |
| 382 | self._called = False |
| 383 | |
| 384 | def test_done_rejected(self): |
| 385 | @@ -336,6 +337,16 @@ |
| 386 | page_name = 'license' |
| 387 | stage_name = 'install' |
| 388 | |
| 389 | + @defer.inlineCallbacks |
| 390 | + def setUp(self): |
| 391 | + yield super(UbuntuOneWizardLicensePage, self).setUp() |
| 392 | + self.patch(gui.utils, 'uninstall_application', self._set_called) |
| 393 | + |
| 394 | + def test_done_rejected(self): |
| 395 | + """When the wizard is closed on the final page, emit rejected.""" |
| 396 | + super(UbuntuOneWizardLicensePage, self).test_done_rejected() |
| 397 | + self.assertEqual(self._called, ((), {})) |
| 398 | + |
| 399 | |
| 400 | class UbuntuOneWizardLoginTestCase(UbuntuOneWizardTestCase): |
| 401 | """Test the login through the wizard.""" |
| 402 | |
| 403 | === modified file 'ubuntuone/controlpanel/gui/qt/wizard.py' |
| 404 | --- ubuntuone/controlpanel/gui/qt/wizard.py 2012-03-26 20:15:58 +0000 |
| 405 | +++ ubuntuone/controlpanel/gui/qt/wizard.py 2012-04-03 13:15:23 +0000 |
| 406 | @@ -23,7 +23,7 @@ |
| 407 | from ubuntu_sso.qt.sso_wizard_page import BaseWizardPage |
| 408 | from ubuntu_sso.utils.ui import CLOSE_AND_SETUP_LATER |
| 409 | |
| 410 | -from ubuntuone.controlpanel import cache |
| 411 | +from ubuntuone.controlpanel import cache, utils |
| 412 | from ubuntuone.controlpanel.logger import log_call, setup_logging |
| 413 | from ubuntuone.controlpanel.gui import ( |
| 414 | APP_NAME, |
| 415 | @@ -342,13 +342,9 @@ |
| 416 | response = self.confirm_dialog.exec_() |
| 417 | if response == QtGui.QDialog.Accepted: |
| 418 | logger.warning('UbuntuOneWizard: user canceled setup.') |
| 419 | - self.rejected.emit() |
| 420 | - elif (self.currentId() == self.pages[self.license_page]): |
| 421 | - response = self.confirm_dialog.exec_() |
| 422 | - if response == QtGui.QDialog.Accepted: |
| 423 | - logger.warning('UbuntuOneWizard: user wants to uninstall.') |
| 424 | - # TODO: needs implementation in this project |
| 425 | - ##qt.utils.uninstall_application() |
| 426 | + if self.currentId() == self.pages[self.license_page]: |
| 427 | + logger.warning('UbuntuOneWizard: user wants to uninstall.') |
| 428 | + utils.uninstall_application() |
| 429 | self.rejected.emit() |
| 430 | else: |
| 431 | super(UbuntuOneWizard, self).done(result) |
| 432 | |
| 433 | === modified file 'ubuntuone/controlpanel/sd_client/__init__.py' |
| 434 | --- ubuntuone/controlpanel/sd_client/__init__.py 2012-01-18 14:06:35 +0000 |
| 435 | +++ ubuntuone/controlpanel/sd_client/__init__.py 2012-04-03 13:15:23 +0000 |
| 436 | @@ -1,8 +1,6 @@ |
| 437 | # -*- coding: utf-8 -*- |
| 438 | - |
| 439 | -# Authors: Natalia B Bidart <natalia.bidart@canonical.com> |
| 440 | # |
| 441 | -# Copyright 2011 Canonical Ltd. |
| 442 | +# Copyright 2012 Canonical Ltd. |
| 443 | # |
| 444 | # This program is free software: you can redistribute it and/or modify it |
| 445 | # under the terms of the GNU General Public License version 3, as published |
| 446 | @@ -18,7 +16,6 @@ |
| 447 | |
| 448 | """The syncdaemon client.""" |
| 449 | |
| 450 | -import sys |
| 451 | import warnings |
| 452 | |
| 453 | # pylint: disable=E0611 |
| 454 | @@ -35,7 +32,6 @@ |
| 455 | |
| 456 | def __init__(self): |
| 457 | """Get a proxy for the SyncDaemonTool.""" |
| 458 | - self.status_changed_handler = None |
| 459 | self.proxy = tools.SyncDaemonTool() |
| 460 | |
| 461 | def get_throttling_limits(self): |
| 462 | @@ -128,6 +124,10 @@ |
| 463 | """Retrieve the folders information from syncdaemon.""" |
| 464 | return self.proxy.get_folders() |
| 465 | |
| 466 | + def validate_path(self, path): |
| 467 | + """Validates 'path' to create a new folder through syncdaemon.""" |
| 468 | + return self.proxy.validate_path(path) |
| 469 | + |
| 470 | def create_folder(self, path): |
| 471 | """Create a new folder through syncdaemon.""" |
| 472 | return self.proxy.create_folder(path) |
| 473 | @@ -200,11 +200,8 @@ |
| 474 | |
| 475 | def set_status_changed_handler(self, handler): |
| 476 | """Set the status handler function.""" |
| 477 | - self.status_changed_handler = handler |
| 478 | - if sys.platform.startswith("linux"): |
| 479 | - # pylint: disable=W0404 |
| 480 | - from ubuntuone.controlpanel.sd_client import linux |
| 481 | - result = linux.set_status_changed_handler(handler) |
| 482 | - else: |
| 483 | - result = self.proxy.set_status_changed_handler(handler) |
| 484 | - return result |
| 485 | + return self.proxy.connect_signal('StatusChanged', handler) |
| 486 | + |
| 487 | + def refresh_volumes(self): |
| 488 | + """Refresh the volumes information from syncdaemon.""" |
| 489 | + return self.proxy.refresh_volumes() |
| 490 | |
| 491 | === removed file 'ubuntuone/controlpanel/sd_client/linux.py' |
| 492 | --- ubuntuone/controlpanel/sd_client/linux.py 2011-06-29 17:59:07 +0000 |
| 493 | +++ ubuntuone/controlpanel/sd_client/linux.py 1970-01-01 00:00:00 +0000 |
| 494 | @@ -1,46 +0,0 @@ |
| 495 | -# -*- coding: utf-8 -*- |
| 496 | - |
| 497 | -# Authors: Alejandro J. Cura <alecu@canonical.com> |
| 498 | -# Authors: Natalia B. Bidart <nataliabidart@canonical.com> |
| 499 | -# |
| 500 | -# Copyright 2010 Canonical Ltd. |
| 501 | -# |
| 502 | -# This program is free software: you can redistribute it and/or modify it |
| 503 | -# under the terms of the GNU General Public License version 3, as published |
| 504 | -# by the Free Software Foundation. |
| 505 | -# |
| 506 | -# This program is distributed in the hope that it will be useful, but |
| 507 | -# WITHOUT ANY WARRANTY; without even the implied warranties of |
| 508 | -# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
| 509 | -# PURPOSE. See the GNU General Public License for more details. |
| 510 | -# |
| 511 | -# You should have received a copy of the GNU General Public License along |
| 512 | -# with this program. If not, see <http://www.gnu.org/licenses/>. |
| 513 | - |
| 514 | -"""Client to use other DBus services.""" |
| 515 | - |
| 516 | -import dbus.service |
| 517 | - |
| 518 | -from ubuntuone.controlpanel.logger import setup_logging |
| 519 | - |
| 520 | - |
| 521 | -logger = setup_logging('sd_client') |
| 522 | - |
| 523 | - |
| 524 | -def get_syncdaemon_proxy(object_path, dbus_interface): |
| 525 | - """Get a DBus proxy for syncdaemon at 'object_path':'dbus_interface'.""" |
| 526 | - logger.debug('get_syncdaemon_proxy: object_path %r, dbus_interface %r', |
| 527 | - object_path, dbus_interface) |
| 528 | - bus = dbus.SessionBus() |
| 529 | - obj = bus.get_object(bus_name='com.ubuntuone.SyncDaemon', |
| 530 | - object_path=object_path, |
| 531 | - follow_name_owner_changes=True) |
| 532 | - proxy = dbus.Interface(object=obj, dbus_interface=dbus_interface) |
| 533 | - return proxy |
| 534 | - |
| 535 | - |
| 536 | -def set_status_changed_handler(handler): |
| 537 | - """Connect 'handler' with syncdaemon's StatusChanged signal.""" |
| 538 | - proxy = get_syncdaemon_proxy('/status', 'com.ubuntuone.SyncDaemon.Status') |
| 539 | - sig = proxy.connect_to_signal('StatusChanged', handler) |
| 540 | - return proxy, sig |
| 541 | |
| 542 | === modified file 'ubuntuone/controlpanel/tests/test_backend.py' |
| 543 | --- ubuntuone/controlpanel/tests/test_backend.py 2012-02-06 15:23:27 +0000 |
| 544 | +++ ubuntuone/controlpanel/tests/test_backend.py 2012-04-03 13:15:23 +0000 |
| 545 | @@ -1,9 +1,6 @@ |
| 546 | # -*- coding: utf-8 -*- |
| 547 | - |
| 548 | -# Authors: Alejandro J. Cura <alecu@canonical.com> |
| 549 | -# Authors: Natalia B. Bidart <nataliabidart@canonical.com> |
| 550 | # |
| 551 | -# Copyright 2010 Canonical Ltd. |
| 552 | +# Copyright 2010-2012 Canonical Ltd. |
| 553 | # |
| 554 | # This program is free software: you can redistribute it and/or modify it |
| 555 | # under the terms of the GNU General Public License version 3, as published |
| 556 | @@ -169,6 +166,7 @@ |
| 557 | self.actions = [] |
| 558 | self.shares = [] |
| 559 | self.folders = [] |
| 560 | + self.volumes_refreshed = False |
| 561 | |
| 562 | def get_throttling_limits(self): |
| 563 | """Return the sample speed limits.""" |
| 564 | @@ -291,6 +289,10 @@ |
| 565 | """Unsubcribe from 'volume_id'.""" |
| 566 | self.subscribed_folders.remove(volume_id) |
| 567 | |
| 568 | + def validate_path(self, path): |
| 569 | + """Validate a path for folder creation.""" |
| 570 | + return path != USER_HOME |
| 571 | + |
| 572 | def create_folder(self, path): |
| 573 | """Grab list of folders.""" |
| 574 | self.folders.append(path) |
| 575 | @@ -319,6 +321,11 @@ |
| 576 | """Grab list of shared (shares from the user to others).""" |
| 577 | return SAMPLE_SHARED |
| 578 | |
| 579 | + def refresh_volumes(self): |
| 580 | + """Refresh the volume list.""" |
| 581 | + self.volumes_refreshed = True |
| 582 | + return defer.succeed(None) |
| 583 | + |
| 584 | |
| 585 | class MockReplicationClient(CallRecorder): |
| 586 | """A mock replication_client module.""" |
| 587 | @@ -860,10 +867,19 @@ |
| 588 | u'display_name': display_name, |
| 589 | } |
| 590 | |
| 591 | + self.patch(self.be.sd_client, 'shares', SAMPLE_SHARES) |
| 592 | + self.patch(self.be.sd_client, 'folders', SAMPLE_FOLDERS) |
| 593 | + |
| 594 | @inlineCallbacks |
| 595 | - def expected_volumes(self, sample_shares, sample_folders, |
| 596 | + def expected_volumes(self, sample_shares=None, sample_folders=None, |
| 597 | with_storage_info=True): |
| 598 | """Get shares and group by sharing user, get folders and free space.""" |
| 599 | + if sample_shares is None: |
| 600 | + sample_shares = self.be.sd_client.shares |
| 601 | + |
| 602 | + if sample_folders is None: |
| 603 | + sample_folders = self.be.sd_client.folders |
| 604 | + |
| 605 | free_bytes = self.be.FREE_BYTES_NOT_AVAILABLE |
| 606 | if with_storage_info: |
| 607 | try: |
| 608 | @@ -926,11 +942,19 @@ |
| 609 | @inlineCallbacks |
| 610 | def test_volumes_info(self): |
| 611 | """The volumes_info method exercises its callback.""" |
| 612 | - self.patch(self.be.sd_client, 'shares', SAMPLE_SHARES) |
| 613 | - self.patch(self.be.sd_client, 'folders', SAMPLE_FOLDERS) |
| 614 | - |
| 615 | - expected = yield self.expected_volumes(SAMPLE_SHARES, SAMPLE_FOLDERS) |
| 616 | + expected = yield self.expected_volumes() |
| 617 | result = yield self.be.volumes_info() |
| 618 | + |
| 619 | + self.assertEqual(result, expected) |
| 620 | + self.assertFalse(self.be.sd_client.volumes_refreshed) |
| 621 | + |
| 622 | + @inlineCallbacks |
| 623 | + def test_volumes_info_can_refresh_volumes(self): |
| 624 | + """The volumes_info can be refreshed.""" |
| 625 | + expected = yield self.expected_volumes() |
| 626 | + result = yield self.be.volumes_info(refresh=True) |
| 627 | + |
| 628 | + self.assertTrue(self.be.sd_client.volumes_refreshed) |
| 629 | self.assertEqual(result, expected) |
| 630 | |
| 631 | @inlineCallbacks |
| 632 | @@ -943,7 +967,6 @@ |
| 633 | path = path[len(USER_HOME) + 1:] |
| 634 | item[u'path'] = os.path.join(root_path, path) |
| 635 | self.patch(self.be.sd_client, 'shares', SAMPLE_SHARES) |
| 636 | - self.patch(self.be.sd_client, 'folders', SAMPLE_FOLDERS) |
| 637 | |
| 638 | yield self.be.volumes_info() |
| 639 | for item in SAMPLE_FOLDERS: |
| 640 | @@ -956,11 +979,7 @@ |
| 641 | @inlineCallbacks |
| 642 | def test_volumes_info_without_storage_info(self): |
| 643 | """The volumes_info method exercises its callback.""" |
| 644 | - self.patch(self.be.sd_client, 'shares', SAMPLE_SHARES) |
| 645 | - self.patch(self.be.sd_client, 'folders', SAMPLE_FOLDERS) |
| 646 | - |
| 647 | - expected = yield self.expected_volumes(SAMPLE_SHARES, SAMPLE_FOLDERS, |
| 648 | - with_storage_info=False) |
| 649 | + expected = yield self.expected_volumes(with_storage_info=False) |
| 650 | result = yield self.be.volumes_info(with_storage_info=False) |
| 651 | self.assertEqual(result, expected) |
| 652 | |
| 653 | @@ -971,11 +990,8 @@ |
| 654 | @inlineCallbacks |
| 655 | def test_volumes_are_cached(self): |
| 656 | """The volume list is cached.""" |
| 657 | - self.patch(self.be.sd_client, 'shares', SAMPLE_SHARES) |
| 658 | - self.patch(self.be.sd_client, 'folders', SAMPLE_FOLDERS) |
| 659 | - |
| 660 | expected = {} |
| 661 | - info = yield self.expected_volumes(SAMPLE_SHARES, SAMPLE_FOLDERS) |
| 662 | + info = yield self.expected_volumes() |
| 663 | for _, _, data in info: |
| 664 | for volume in data: |
| 665 | sid = volume['volume_id'] |
| 666 | @@ -1024,10 +1040,8 @@ |
| 667 | ] |
| 668 | |
| 669 | self.patch(self.be.sd_client, 'shares', read_only_shares) |
| 670 | - self.patch(self.be.sd_client, 'folders', SAMPLE_FOLDERS) |
| 671 | |
| 672 | - expected = yield self.expected_volumes(read_only_shares, |
| 673 | - SAMPLE_FOLDERS) |
| 674 | + expected = yield self.expected_volumes() |
| 675 | result = yield self.be.volumes_info() |
| 676 | self.assertEqual(result, expected) |
| 677 | |
| 678 | @@ -1035,10 +1049,8 @@ |
| 679 | def test_volumes_info_no_quota_for_root(self): |
| 680 | """The volumes_info returns info even if quota call fails.""" |
| 681 | self.be.wc.failure = 500 |
| 682 | - self.patch(self.be.sd_client, 'shares', SAMPLE_SHARES) |
| 683 | - self.patch(self.be.sd_client, 'folders', SAMPLE_FOLDERS) |
| 684 | |
| 685 | - expected = yield self.expected_volumes(SAMPLE_SHARES, SAMPLE_FOLDERS) |
| 686 | + expected = yield self.expected_volumes() |
| 687 | result = yield self.be.volumes_info() |
| 688 | |
| 689 | self.assertEqual(len(result), len(expected)) |
| 690 | @@ -1126,29 +1138,15 @@ |
| 691 | @inlineCallbacks |
| 692 | def test_create_folder(self): |
| 693 | """New folders can be created.""" |
| 694 | + self.patch(self.be.sd_client, 'folders', []) |
| 695 | + |
| 696 | folder_path = os.path.join(USER_HOME, 'Test Me') |
| 697 | yield self.be.create_folder(folder_path=folder_path) |
| 698 | |
| 699 | self.assertEqual(self.be.sd_client.folders, [folder_path]) |
| 700 | |
| 701 | - |
| 702 | -class BackendValidatePathForFolderTestCase(BackendBasicTestCase): |
| 703 | - """Test for the path validator when creating folders.""" |
| 704 | - |
| 705 | - msg = '%r must not be a valid path for creating a folder.' |
| 706 | - |
| 707 | - @defer.inlineCallbacks |
| 708 | - def setUp(self): |
| 709 | - yield super(BackendValidatePathForFolderTestCase, self).setUp() |
| 710 | - old_home = os.environ['HOME'] |
| 711 | - os.environ['HOME'] = USER_HOME |
| 712 | - self.addCleanup(os.environ.__setitem__, 'HOME', old_home) |
| 713 | - self.patch(self.be.sd_client, 'shares', SAMPLE_SHARES) |
| 714 | - self.patch(self.be.sd_client, 'folders', SAMPLE_FOLDERS) |
| 715 | - self.patch(backend, 'is_link', lambda p: False) |
| 716 | - |
| 717 | - @defer.inlineCallbacks |
| 718 | - def test_valid_if_folder_inside_home(self): |
| 719 | + @defer.inlineCallbacks |
| 720 | + def test_validate_path_for_folder(self): |
| 721 | """Test proper validation of path for creating folders.""" |
| 722 | folder_path = os.path.join(USER_HOME, 'Test Me') |
| 723 | |
| 724 | @@ -1157,68 +1155,11 @@ |
| 725 | '%r must be a valid path for creating a folder.' % folder_path) |
| 726 | |
| 727 | @defer.inlineCallbacks |
| 728 | - def test_valid_if_folder_shares_a_prefix_with_an_udf(self): |
| 729 | - """Test proper validation of path for creating folders. |
| 730 | - |
| 731 | - If the user chooses a folder with the same prefix as an UDF, but |
| 732 | - outside every UDF, the path is valid. |
| 733 | - |
| 734 | - """ |
| 735 | - tricky_path = ROOT_PATH |
| 736 | - assert not tricky_path.endswith(os.path.sep) |
| 737 | - tricky_path += ' Suffix' |
| 738 | - assert tricky_path.startswith(ROOT_PATH) |
| 739 | - |
| 740 | - result = yield self.be.validate_path_for_folder(tricky_path) |
| 741 | - self.assertTrue(result, |
| 742 | - '%r must be a valid path for creating a folder.' % tricky_path) |
| 743 | - |
| 744 | - @inlineCallbacks |
| 745 | - def test_path_not_valid_if_outside_home(self): |
| 746 | - """A folder outside ~ is not valid.""" |
| 747 | - outside_home = os.path.abspath(os.path.join(USER_HOME, os.path.pardir)) |
| 748 | - |
| 749 | - result = yield self.be.validate_path_for_folder(outside_home) |
| 750 | - self.assertFalse(result, self.msg % outside_home) |
| 751 | - |
| 752 | - @defer.inlineCallbacks |
| 753 | - def test_not_valid_if_folder_inside_root(self): |
| 754 | - """A folder inside the root is not valid.""" |
| 755 | - root_path = ROOT_PATH |
| 756 | - # create a valid path inside the root |
| 757 | - inside_root = os.path.abspath(os.path.join(root_path, 'test')) |
| 758 | - |
| 759 | - result = yield self.be.validate_path_for_folder(inside_root) |
| 760 | - self.assertFalse(result, self.msg % inside_root) |
| 761 | - |
| 762 | - @defer.inlineCallbacks |
| 763 | - def test_not_valid_if_folder_inside_an_udf(self): |
| 764 | - """A folder inside an UDF is not valid.""" |
| 765 | - udf_path = SAMPLE_FOLDERS[-1]['path'] |
| 766 | - # create a valid path inside an existing UDF |
| 767 | - inside_udf = os.path.abspath(os.path.join(udf_path, 'test')) |
| 768 | - |
| 769 | - result = yield self.be.validate_path_for_folder(inside_udf) |
| 770 | - self.assertFalse(result, self.msg % inside_udf) |
| 771 | - |
| 772 | - @defer.inlineCallbacks |
| 773 | - def test_not_valid_if_folder_is_parent_of_an_udf(self): |
| 774 | - """A folder parent of an UDF is not valid.""" |
| 775 | - udf_path = SAMPLE_FOLDERS[-1]['path'] |
| 776 | - # create a valid path that is parent from an existing UDF |
| 777 | - udf_parent = os.path.abspath(os.path.join(udf_path, os.path.pardir)) |
| 778 | - |
| 779 | - result = yield self.be.validate_path_for_folder(udf_parent) |
| 780 | - self.assertFalse(result, self.msg % udf_parent) |
| 781 | - |
| 782 | - @defer.inlineCallbacks |
| 783 | - def test_not_valid_if_folder_is_link(self): |
| 784 | - """A link path is not valid.""" |
| 785 | - self.patch(backend, 'is_link', lambda p: True) |
| 786 | - path_link = os.path.join(USER_HOME, 'Test Me') |
| 787 | - |
| 788 | - result = yield self.be.validate_path_for_folder(path_link) |
| 789 | - self.assertFalse(result, self.msg % path_link) |
| 790 | + def test_validate_path_for_folder_invalid(self): |
| 791 | + """Test proper validation of path for creating folders.""" |
| 792 | + result = yield self.be.validate_path_for_folder(USER_HOME) |
| 793 | + self.assertFalse(result, |
| 794 | + '%r must not be a valid path for creating a folder.' % USER_HOME) |
| 795 | |
| 796 | |
| 797 | class BackendSyncStatusTestCase(BackendBasicTestCase): |
| 798 | @@ -1598,6 +1539,7 @@ |
| 799 | @inlineCallbacks |
| 800 | def test_file_sync_settings_info(self): |
| 801 | """The settings_info method exercises its callback.""" |
| 802 | + self.patch(self.be.sd_client, "throttling", True) |
| 803 | self.be.sd_client.limits = {"download": 1000, "upload": 100} |
| 804 | expected = { |
| 805 | backend.AUTOCONNECT_KEY: self.be.sd_client.autoconnect, |
| 806 | @@ -1614,6 +1556,25 @@ |
| 807 | self.assertEqual(expected, result) |
| 808 | |
| 809 | @inlineCallbacks |
| 810 | + def test_file_sync_settings_info_with_limit(self): |
| 811 | + """The settings_info method exercises its callback.""" |
| 812 | + self.patch(self.be.sd_client, "throttling", False) |
| 813 | + self.be.sd_client.limits = {"download": 987456, "upload": 125698} |
| 814 | + expected = { |
| 815 | + backend.AUTOCONNECT_KEY: self.be.sd_client.autoconnect, |
| 816 | + backend.SHOW_ALL_NOTIFICATIONS_KEY: |
| 817 | + self.be.sd_client.show_all_notifications, |
| 818 | + backend.SHARE_AUTOSUBSCRIBE_KEY: |
| 819 | + self.be.sd_client.share_autosubscribe, |
| 820 | + backend.UDF_AUTOSUBSCRIBE_KEY: |
| 821 | + self.be.sd_client.udf_autosubscribe, |
| 822 | + backend.DOWNLOAD_KEY: -1, |
| 823 | + backend.UPLOAD_KEY: -1, |
| 824 | + } |
| 825 | + result = yield self.be.file_sync_settings_info() |
| 826 | + self.assertEqual(expected, result) |
| 827 | + |
| 828 | + @inlineCallbacks |
| 829 | def test_change_file_sync_setting_autoconnect(self): |
| 830 | """The settings can be changed for autoconnect.""" |
| 831 | yield self.assert_boolean_setting_is_correct(backend.AUTOCONNECT_KEY) |
| 832 | |
| 833 | === modified file 'ubuntuone/controlpanel/tests/test_sd_client.py' |
| 834 | --- ubuntuone/controlpanel/tests/test_sd_client.py 2012-03-19 17:16:43 +0000 |
| 835 | +++ ubuntuone/controlpanel/tests/test_sd_client.py 2012-04-03 13:15:23 +0000 |
| 836 | @@ -1,9 +1,6 @@ |
| 837 | # -*- coding: utf-8 -*- |
| 838 | - |
| 839 | -# Authors: Alejandro J. Cura <alecu@canonical.com> |
| 840 | -# Authors: Natalia B. Bidart <natalia.bidart@canonical.com> |
| 841 | # |
| 842 | -# Copyright 2010 Canonical Ltd. |
| 843 | +# Copyright 2010-2012 Canonical Ltd. |
| 844 | # |
| 845 | # This program is free software: you can redistribute it and/or modify it |
| 846 | # under the terms of the GNU General Public License version 3, as published |
| 847 | @@ -24,11 +21,7 @@ |
| 848 | |
| 849 | from twisted.internet import defer |
| 850 | from twisted.internet.defer import inlineCallbacks, returnValue |
| 851 | -from ubuntuone.devtools.testcases import skipIfNotOS |
| 852 | -# No name 'tools' in module 'ubuntuone.platform' |
| 853 | -# pylint: disable=E0611 |
| 854 | from ubuntuone.platform import tools |
| 855 | -# pylint: enable=E0611 |
| 856 | from ubuntuone.syncdaemon.interaction_interfaces import bool_str |
| 857 | |
| 858 | from ubuntuone.controlpanel import sd_client |
| 859 | @@ -164,6 +157,10 @@ |
| 860 | """Get the list of the shares "shared"/created/offered.""" |
| 861 | self.called['list_shared'] = None |
| 862 | |
| 863 | + def validate_path(self, path): |
| 864 | + """Validate a path for folder creation.""" |
| 865 | + return path not in [f['path'] for f in self.folders.itervalues()] |
| 866 | + |
| 867 | def create_folder(self, path): |
| 868 | """Create a user defined folder in the specified path.""" |
| 869 | if path == '': # simulate an error |
| 870 | @@ -183,14 +180,12 @@ |
| 871 | @inlineCallbacks |
| 872 | def subscribe_folder(self, folder_id): |
| 873 | """Subscribe to a user defined folder given its id.""" |
| 874 | - yield self._set_folder_attr(folder_id, |
| 875 | - u'subscribed', True) |
| 876 | + yield self._set_folder_attr(folder_id, u'subscribed', True) |
| 877 | |
| 878 | @inlineCallbacks |
| 879 | def unsubscribe_folder(self, folder_id): |
| 880 | """Unsubscribe from a user defined folder given its id.""" |
| 881 | - yield self._set_folder_attr(folder_id, |
| 882 | - u'subscribed', False) |
| 883 | + yield self._set_folder_attr(folder_id, u'subscribed', False) |
| 884 | |
| 885 | @inlineCallbacks |
| 886 | def get_folders(self): |
| 887 | @@ -315,9 +310,9 @@ |
| 888 | """Return the shares link directory.""" |
| 889 | return self.shares_dir_link |
| 890 | |
| 891 | - def set_status_changed_handler(self, handler): |
| 892 | + def connect_signal(self, signal_name, handler): |
| 893 | """Set the handler for the status changed signal.""" |
| 894 | - self.called['status_changed_handler'] = handler |
| 895 | + self.called[signal_name] = handler |
| 896 | |
| 897 | |
| 898 | class BaseTestCase(TestCase): |
| 899 | @@ -519,6 +514,19 @@ |
| 900 | yield self.assertFailure(self.sd.get_folders(), CustomError) |
| 901 | |
| 902 | @inlineCallbacks |
| 903 | + def test_validate_path(self): |
| 904 | + """Check if a folder path is valid.""" |
| 905 | + path = '~/bar/baz' |
| 906 | + result = yield self.sd.validate_path(path) |
| 907 | + |
| 908 | + self.assertTrue(result) |
| 909 | + |
| 910 | + yield self.sd.create_folder(path) |
| 911 | + result = yield self.sd.validate_path(path) |
| 912 | + |
| 913 | + self.assertFalse(result) |
| 914 | + |
| 915 | + @inlineCallbacks |
| 916 | def test_create_folder(self): |
| 917 | """Create a new folder.""" |
| 918 | path = '~/bar/baz' |
| 919 | @@ -694,14 +702,12 @@ |
| 920 | |
| 921 | self.assertEqual(self.sd.proxy.called['quit'], None) |
| 922 | |
| 923 | - @skipIfNotOS('win32', 'The tested function is only defined on windows') |
| 924 | @inlineCallbacks |
| 925 | def test_set_status_changed_handler(self): |
| 926 | """Connect a handler to the status changed signal.""" |
| 927 | sample_handler = object() |
| 928 | yield self.sd.set_status_changed_handler(sample_handler) |
| 929 | - self.assertEqual(sample_handler, |
| 930 | - self.sd.proxy.called['status_changed_handler']) |
| 931 | + self.assertEqual(sample_handler, self.sd.proxy.called['StatusChanged']) |
| 932 | |
| 933 | |
| 934 | class BasicTestCase(BaseTestCase): |
| 935 | |
| 936 | === modified file 'ubuntuone/controlpanel/utils/__init__.py' |
| 937 | --- ubuntuone/controlpanel/utils/__init__.py 2012-03-22 23:28:19 +0000 |
| 938 | +++ ubuntuone/controlpanel/utils/__init__.py 2012-04-03 13:15:23 +0000 |
| 939 | @@ -32,19 +32,23 @@ |
| 940 | # ignore issues with the name of the method |
| 941 | # pylint: disable=C0103 |
| 942 | |
| 943 | +no_op = lambda *args, **kwargs: None |
| 944 | + |
| 945 | # import the platform dependent code. |
| 946 | if sys.platform == 'win32': |
| 947 | from ubuntuone.controlpanel.utils import windows |
| 948 | + add_to_autostart = windows.add_to_autostart |
| 949 | are_updates_present = windows.are_updates_present |
| 950 | default_folders = windows.default_folders |
| 951 | perform_update = windows.perform_update |
| 952 | - add_to_autostart = windows.add_to_autostart |
| 953 | + uninstall_application = windows.uninstall_application |
| 954 | else: |
| 955 | from ubuntuone.controlpanel.utils import linux |
| 956 | - are_updates_present = lambda *args, **kwargs: False |
| 957 | + add_to_autostart = no_op |
| 958 | + are_updates_present = no_op |
| 959 | default_folders = linux.default_folders |
| 960 | - perform_update = lambda *args, **kwargs: None |
| 961 | - add_to_autostart = lambda *args, **kwargs: None |
| 962 | + perform_update = no_op |
| 963 | + uninstall_application = no_op |
| 964 | |
| 965 | # pylint: enable=C0103 |
| 966 | |
| 967 | |
| 968 | === modified file 'ubuntuone/controlpanel/utils/tests/test_windows.py' |
| 969 | --- ubuntuone/controlpanel/utils/tests/test_windows.py 2012-03-23 21:20:18 +0000 |
| 970 | +++ ubuntuone/controlpanel/utils/tests/test_windows.py 2012-04-03 13:15:23 +0000 |
| 971 | @@ -1,7 +1,6 @@ |
| 972 | # -*- coding: utf-8 -*- |
| 973 | - |
| 974 | # |
| 975 | -# Copyright 2011 Canonical Ltd. |
| 976 | +# Copyright 2011-2012 Canonical Ltd. |
| 977 | # |
| 978 | # This program is free software: you can redistribute it and/or modify it |
| 979 | # under the terms of the GNU General Public License version 3, as published |
| 980 | @@ -28,6 +27,34 @@ |
| 981 | # let me use protected methods |
| 982 | # pylint: disable=W0212 |
| 983 | |
| 984 | +SOME_EXE_NAME = 'foo.exe' |
| 985 | + |
| 986 | + |
| 987 | +class FrozenTestCase(TestCase): |
| 988 | + """A base test case for handling frozen/not frozen systems.""" |
| 989 | + |
| 990 | + frozen = True |
| 991 | + executable = 'path/to/current/exe/ubuntuone/dist/executable.exe' |
| 992 | + |
| 993 | + @defer.inlineCallbacks |
| 994 | + def setUp(self): |
| 995 | + """Set the different tests.""" |
| 996 | + yield super(FrozenTestCase, self).setUp() |
| 997 | + |
| 998 | + for attr_name in ('frozen', 'executable'): |
| 999 | + value_not_set = object() |
| 1000 | + value = getattr(utils.windows.sys, attr_name, value_not_set) |
| 1001 | + |
| 1002 | + if self.frozen is not None: |
| 1003 | + setattr(utils.windows.sys, attr_name, getattr(self, attr_name)) |
| 1004 | + elif self.frozen is None and value is not value_not_set: |
| 1005 | + delattr(utils.windows.sys, attr_name) |
| 1006 | + |
| 1007 | + if self.frozen is not None and value is value_not_set: |
| 1008 | + self.addCleanup(delattr, utils.windows.sys, attr_name) |
| 1009 | + elif value is not value_not_set: |
| 1010 | + self.addCleanup(setattr, utils.windows.sys, attr_name, value) |
| 1011 | + |
| 1012 | |
| 1013 | class AutoupdaterTestCase(TestCase): |
| 1014 | """Test the code that is used for the auto update process.""" |
| 1015 | @@ -36,7 +63,9 @@ |
| 1016 | def setUp(self): |
| 1017 | """Prepare for the diff tests.""" |
| 1018 | yield super(AutoupdaterTestCase, self).setUp() |
| 1019 | - self.auto_update_path = r'path\to\exe' |
| 1020 | + self._base_path = r'path\to\exe' |
| 1021 | + self.auto_update_path = os.path.join(self._base_path, |
| 1022 | + utils.windows.AUTOUPDATE_EXE_NAME) |
| 1023 | self.return_from_call = 0 |
| 1024 | self.command = None |
| 1025 | self.args = [] |
| 1026 | @@ -48,8 +77,8 @@ |
| 1027 | return self.return_from_call |
| 1028 | |
| 1029 | self.patch(utils.windows, 'getProcessValue', fake_execute_process) |
| 1030 | - self.patch(utils.windows, '_get_update_path', |
| 1031 | - lambda: self.auto_update_path) |
| 1032 | + self.patch(utils.windows, 'get_exe_path', |
| 1033 | + lambda exe_name: os.path.join(self._base_path, exe_name)) |
| 1034 | |
| 1035 | @defer.inlineCallbacks |
| 1036 | def test_are_updates_present_true(self): |
| 1037 | @@ -81,11 +110,9 @@ |
| 1038 | """Test the method that performs the update.""" |
| 1039 | self.patch(utils.windows.win32api, 'ShellExecute', self._set_called) |
| 1040 | utils.perform_update() |
| 1041 | - self.assertIn(self.auto_update_path, self._called[0][2]) |
| 1042 | - self.assertEqual('runas', self._called[0][1]) |
| 1043 | - self.assertEqual('--unattendedmodeui none', self._called[0][3]) |
| 1044 | - self.assertEqual('', self._called[0][4]) |
| 1045 | - self.assertEqual(0, self._called[0][5]) |
| 1046 | + args = (None, 'runas', self.auto_update_path, |
| 1047 | + '--unattendedmodeui none', '', 0) |
| 1048 | + self.assertEqual(self._called, (args, {})) |
| 1049 | |
| 1050 | |
| 1051 | class FakeOpenKey(object): |
| 1052 | @@ -164,7 +191,8 @@ |
| 1053 | [((self.registry.OpenKey, 'Ubuntu One', 0, 1, |
| 1054 | '"%s\\ubuntuone-syncdaemon.exe"' % path), {}), |
| 1055 | ((self.registry.OpenKey, 'Ubuntu One Icon', 0, 1, |
| 1056 | - '"%s\\ubuntuone-control-panel-qt.exe" --minimized' % path), |
| 1057 | + '"%s\\ubuntuone-control-panel-qt.exe" ' |
| 1058 | + '--minimized --with-icon' % path), |
| 1059 | {})]) |
| 1060 | |
| 1061 | def test_not_added_if_not_frozen(self): |
| 1062 | @@ -192,7 +220,7 @@ |
| 1063 | for name in names: |
| 1064 | name = getattr(utils.windows.shellcon, 'CSIDL_%s' % name) |
| 1065 | folder = utils.windows.shell.SHGetFolderPath(0, name, None, 0) |
| 1066 | - expected.append(folder.encode('utf8')) |
| 1067 | + expected.append(folder) |
| 1068 | |
| 1069 | self.assertEqual(sorted(folders), sorted(expected)) |
| 1070 | |
| 1071 | @@ -216,15 +244,14 @@ |
| 1072 | self.test_special_folders(names=('PERSONAL', 'MYMUSIC', 'MYPICTURES')) |
| 1073 | |
| 1074 | |
| 1075 | -class GetPathTestCase(TestCase): |
| 1076 | - """Test the code that is used for the auto update process.""" |
| 1077 | +class GetExePathTestCase(FrozenTestCase): |
| 1078 | + """Test the path calculator when sys is frozen.""" |
| 1079 | |
| 1080 | @defer.inlineCallbacks |
| 1081 | def setUp(self): |
| 1082 | """Set the different tests.""" |
| 1083 | - yield super(GetPathTestCase, self).setUp() |
| 1084 | + yield super(GetExePathTestCase, self).setUp() |
| 1085 | self.called = [] |
| 1086 | - self.exec_path = 'path/to/current/exe' |
| 1087 | self.exists = True |
| 1088 | |
| 1089 | def fake_abspath(path): |
| 1090 | @@ -247,62 +274,70 @@ |
| 1091 | self.patch(utils.windows.os.path, 'dirname', fake_dirname) |
| 1092 | self.patch(utils.windows.os.path, 'exists', fake_exists) |
| 1093 | |
| 1094 | - def _delete_frozen_state(self): |
| 1095 | - """Delete the frozen state.""" |
| 1096 | - del utils.windows.sys.frozen |
| 1097 | - del utils.windows.sys.executable |
| 1098 | - |
| 1099 | - def test_get_auto_update_path_frozen(self): |
| 1100 | - """Test the method used to get the autoupdate.""" |
| 1101 | - # patch the diff parts of sys so that we get fake paths |
| 1102 | - is_frozen = hasattr(utils.windows.sys, 'frozen') |
| 1103 | - if not is_frozen: |
| 1104 | - utils.windows.sys.frozen = True |
| 1105 | - utils.windows.sys.executable = self.exec_path |
| 1106 | - self.addCleanup(self._delete_frozen_state) |
| 1107 | - |
| 1108 | - # called method and assert that we have the correct result |
| 1109 | - path = utils.windows._get_update_path() |
| 1110 | - self.assertEqual(os.path.join(self.exec_path, |
| 1111 | - utils.windows.AUTOUPDATE_EXE_NAME), path) |
| 1112 | - self.assertTrue('os.path.abspath' in self.called) |
| 1113 | - self.assertTrue('os.path.dirname' in self.called) |
| 1114 | - self.assertTrue('os.path.exists' in self.called) |
| 1115 | - |
| 1116 | - def _reset_frozen_state(self, old_frozen, old_exec_path): |
| 1117 | - """Reset the frozen state.""" |
| 1118 | - utils.windows.sys.frozen = old_frozen |
| 1119 | - utils.windows.sys.executable = old_exec_path |
| 1120 | - |
| 1121 | - def _reset__file__(self, path): |
| 1122 | - """Reset the value of __file__.""" |
| 1123 | - utils.windows.__file__ = path |
| 1124 | - |
| 1125 | - def test_get_auto_update_path_not_frozen(self): |
| 1126 | - """Test the method used to get the autoupdate.""" |
| 1127 | - is_frozen = hasattr(utils.windows.sys, 'frozen') |
| 1128 | - if is_frozen: |
| 1129 | - old_frozen = utils.windows.sys.frozen |
| 1130 | - old_exec_path = utils.windows.sys.executable |
| 1131 | - del utils.windows.sys.frozen |
| 1132 | - del utils.windows.sys.executable |
| 1133 | - self.addCleanup(self._reset_frozen_state, old_frozen, |
| 1134 | - old_exec_path) |
| 1135 | - # set a fake __file__ for the module |
| 1136 | - old_file = utils.windows.__file__ |
| 1137 | - utils.windows.__file__ = self.exec_path |
| 1138 | - self.addCleanup(self._reset__file__, old_file) |
| 1139 | - |
| 1140 | - path = utils.windows._get_update_path() |
| 1141 | - self.assertEqual(os.path.join(self.exec_path, |
| 1142 | - utils.windows.AUTOUPDATE_EXE_NAME), path) |
| 1143 | - self.assertEqual(2, self.called.count('os.path.dirname')) |
| 1144 | - self.assertTrue('os.path.exists' in self.called) |
| 1145 | - |
| 1146 | - def test_get_auto_update_path_not_present(self): |
| 1147 | + def test_get_exe_path(self): |
| 1148 | + """Test the method used to get the autoupdate.""" |
| 1149 | + path = utils.windows.get_exe_path(exe_name=SOME_EXE_NAME) |
| 1150 | + |
| 1151 | + self.assertEqual(os.path.join(self.executable, SOME_EXE_NAME), path) |
| 1152 | + |
| 1153 | + expected = ['os.path.abspath', 'os.path.dirname', 'os.path.dirname', |
| 1154 | + 'os.path.exists'] |
| 1155 | + self.assertEqual(expected, self.called) |
| 1156 | + |
| 1157 | + def test_get_exe_path_not_present(self): |
| 1158 | """Test the method used to get the autoupdate.""" |
| 1159 | self.exists = False |
| 1160 | |
| 1161 | # called method and assert that we have the correct result |
| 1162 | - path = utils.windows._get_update_path() |
| 1163 | - self.assertEqual(None, path) |
| 1164 | + path = utils.windows.get_exe_path(exe_name=SOME_EXE_NAME) |
| 1165 | + self.assertTrue(path is None) |
| 1166 | + |
| 1167 | + |
| 1168 | +class GetExePathNotFrozenTestCase(GetExePathTestCase): |
| 1169 | + """Test the path calculator when sys is not frozen.""" |
| 1170 | + |
| 1171 | + frozen = None |
| 1172 | + |
| 1173 | + def test_get_exe_path(self): |
| 1174 | + """Test the method used to get the autoupdate.""" |
| 1175 | + self.patch(utils.windows, '__file__', self.executable) |
| 1176 | + |
| 1177 | + path = utils.windows.get_exe_path(exe_name=SOME_EXE_NAME) |
| 1178 | + self.assertEqual(os.path.join(self.executable, SOME_EXE_NAME), path) |
| 1179 | + |
| 1180 | + expected = ['os.path.dirname', 'os.path.dirname', 'os.path.dirname', |
| 1181 | + 'os.path.exists'] |
| 1182 | + self.assertEqual(expected, self.called) |
| 1183 | + |
| 1184 | + |
| 1185 | +class UninstallApplicationTestCase(FrozenTestCase): |
| 1186 | + """Test the uninstall_application helper when sys is frozen.""" |
| 1187 | + |
| 1188 | + @defer.inlineCallbacks |
| 1189 | + def setUp(self): |
| 1190 | + yield super(UninstallApplicationTestCase, self).setUp() |
| 1191 | + self.patch(utils.windows.win32api, "ShellExecute", self._set_called) |
| 1192 | + self.patch(os.path, "exists", lambda path: True) |
| 1193 | + |
| 1194 | + def test_uninstall(self): |
| 1195 | + """The uninstaller is run.""" |
| 1196 | + utils.uninstall_application() |
| 1197 | + |
| 1198 | + exe_name = utils.windows.UNINSTALL_EXE_NAME |
| 1199 | + uninstall_path = utils.windows.get_exe_path(exe_name=exe_name) |
| 1200 | + self.assertEqual(self._called, |
| 1201 | + ((None, '', uninstall_path, '--mode win32', '', 0), {})) |
| 1202 | + |
| 1203 | + def test_uninstall_exe_not_present(self): |
| 1204 | + """The uninstaller is not run if not available.""" |
| 1205 | + self.patch(os.path, "exists", lambda path: False) |
| 1206 | + |
| 1207 | + utils.uninstall_application() |
| 1208 | + |
| 1209 | + self.assertFalse(self._called) |
| 1210 | + |
| 1211 | + |
| 1212 | +class UninstallApplicationNotFrozenTestCase(UninstallApplicationTestCase): |
| 1213 | + """Test the uninstall_application helper when sys is not frozen.""" |
| 1214 | + |
| 1215 | + frozen = None |
| 1216 | |
| 1217 | === modified file 'ubuntuone/controlpanel/utils/windows.py' |
| 1218 | --- ubuntuone/controlpanel/utils/windows.py 2012-03-23 21:48:53 +0000 |
| 1219 | +++ ubuntuone/controlpanel/utils/windows.py 2012-04-03 13:15:23 +0000 |
| 1220 | @@ -1,7 +1,6 @@ |
| 1221 | # -*- coding: utf-8 -*- |
| 1222 | - |
| 1223 | # |
| 1224 | -# Copyright 2011 Canonical Ltd. |
| 1225 | +# Copyright 2011-2012 Canonical Ltd. |
| 1226 | # |
| 1227 | # This program is free software: you can redistribute it and/or modify it |
| 1228 | # under the terms of the GNU General Public License version 3, as published |
| 1229 | @@ -35,19 +34,41 @@ |
| 1230 | logger = setup_logging('utils.windows') |
| 1231 | AUTOUPDATE_EXE_NAME = 'autoupdate-windows.exe' |
| 1232 | AUTORUN_KEY = r"Software\Microsoft\Windows\CurrentVersion\Run" |
| 1233 | - |
| 1234 | - |
| 1235 | -def _get_update_path(): |
| 1236 | +UNINSTALL_EXE_NAME = 'uninstall.exe' |
| 1237 | + |
| 1238 | + |
| 1239 | +def get_exe_path(exe_name): |
| 1240 | """Return the path in which the autoupdate command is found.""" |
| 1241 | - if hasattr(sys, 'frozen'): |
| 1242 | + if getattr(sys, 'frozen', False): |
| 1243 | exec_path = os.path.abspath(sys.executable) |
| 1244 | else: |
| 1245 | exec_path = os.path.dirname(__file__) |
| 1246 | - folder = os.path.dirname(exec_path) |
| 1247 | - update_path = os.path.join(folder, AUTOUPDATE_EXE_NAME) |
| 1248 | - if os.path.exists(update_path): |
| 1249 | - return update_path |
| 1250 | - return None |
| 1251 | + |
| 1252 | + result = None |
| 1253 | + folder = os.path.dirname(os.path.dirname(exec_path)) |
| 1254 | + exe_path = os.path.join(folder, exe_name) |
| 1255 | + if os.path.exists(exe_path): |
| 1256 | + result = exe_path |
| 1257 | + |
| 1258 | + return result |
| 1259 | + |
| 1260 | + |
| 1261 | +def add_to_autostart(): |
| 1262 | + """Add syncdaemon to the session's autostart.""" |
| 1263 | + if getattr(sys, "frozen", False): |
| 1264 | + sd_path = '"%s"' % os.path.join(os.path.dirname( |
| 1265 | + os.path.abspath(sys.executable)), |
| 1266 | + "ubuntuone-syncdaemon.exe") |
| 1267 | + u1cp_path = '"%s"' % os.path.join(os.path.dirname( |
| 1268 | + os.path.abspath(sys.executable)), |
| 1269 | + "ubuntuone-control-panel-qt.exe") |
| 1270 | + |
| 1271 | + with _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, AUTORUN_KEY, |
| 1272 | + 0, _winreg.KEY_ALL_ACCESS) as key: |
| 1273 | + # pylint: disable=E0602 |
| 1274 | + _winreg.SetValueEx(key, "Ubuntu One", 0, _winreg.REG_SZ, sd_path) |
| 1275 | + _winreg.SetValueEx(key, "Ubuntu One Icon", 0, _winreg.REG_SZ, |
| 1276 | + u1cp_path + " --minimized --with-icon") |
| 1277 | |
| 1278 | |
| 1279 | @defer.inlineCallbacks |
| 1280 | @@ -55,7 +76,7 @@ |
| 1281 | """Return if there are updates for Ubuntu One.""" |
| 1282 | result = False |
| 1283 | retcode = None |
| 1284 | - update_path = _get_update_path() |
| 1285 | + update_path = get_exe_path(exe_name=AUTOUPDATE_EXE_NAME) |
| 1286 | if update_path is not None: |
| 1287 | # If there is an update present we will get 0, non-zero otherwise |
| 1288 | retcode = yield getProcessValue(update_path, args=('--mode', |
| 1289 | @@ -74,7 +95,7 @@ |
| 1290 | # but the latter does not support XP |
| 1291 | # (Minimum supported client: Windows Vista) |
| 1292 | get_path = lambda name: shell.SHGetFolderPath( |
| 1293 | - 0, getattr(shellcon, name), None, 0).encode('utf8') |
| 1294 | + 0, getattr(shellcon, name), None, 0) |
| 1295 | |
| 1296 | folders = [] |
| 1297 | # More information on these constants at |
| 1298 | @@ -92,27 +113,15 @@ |
| 1299 | |
| 1300 | def perform_update(): |
| 1301 | """Spawn the autoupdate process and call the stop function.""" |
| 1302 | - update_path = _get_update_path() |
| 1303 | + update_path = get_exe_path(exe_name=AUTOUPDATE_EXE_NAME) |
| 1304 | if update_path is not None: |
| 1305 | # lets call the updater with the commands that are required, |
| 1306 | - win32api.ShellExecute(None, 'runas', |
| 1307 | - update_path, |
| 1308 | - '--unattendedmodeui none', '', 0) |
| 1309 | - |
| 1310 | - |
| 1311 | -def add_to_autostart(): |
| 1312 | - """Add syncdaemon to the session's autostart.""" |
| 1313 | - if getattr(sys, "frozen", False): |
| 1314 | - sd_path = '"%s"' % os.path.join(os.path.dirname( |
| 1315 | - os.path.abspath(sys.executable)), |
| 1316 | - "ubuntuone-syncdaemon.exe") |
| 1317 | - u1cp_path = '"%s"' % os.path.join(os.path.dirname( |
| 1318 | - os.path.abspath(sys.executable)), |
| 1319 | - "ubuntuone-control-panel-qt.exe") |
| 1320 | - |
| 1321 | - with _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, AUTORUN_KEY, |
| 1322 | - 0, _winreg.KEY_ALL_ACCESS) as key: |
| 1323 | - # pylint: disable=E0602 |
| 1324 | - _winreg.SetValueEx(key, "Ubuntu One", 0, _winreg.REG_SZ, sd_path) |
| 1325 | - _winreg.SetValueEx(key, "Ubuntu One Icon", 0, _winreg.REG_SZ, |
| 1326 | - u1cp_path + " --minimized --with-icon") |
| 1327 | + win32api.ShellExecute(None, 'runas', update_path, |
| 1328 | + '--unattendedmodeui none', '', 0) |
| 1329 | + |
| 1330 | + |
| 1331 | +def uninstall_application(): |
| 1332 | + """Uninstall Ubuntu One.""" |
| 1333 | + uninstall_path = get_exe_path(exe_name=UNINSTALL_EXE_NAME) |
| 1334 | + if uninstall_path is not None: |
| 1335 | + win32api.ShellExecute(None, '', uninstall_path, '--mode win32', '', 0) |


Approving