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