Merge lp:~dobey/ubuntu-sso-client/update-4-0 into lp:ubuntu-sso-client/stable-4-0
- update-4-0
- Merge into stable-4-0
Status: | Merged |
---|---|
Approved by: | dobey |
Approved revision: | no longer in the source branch. |
Merged at revision: | 960 |
Proposed branch: | lp:~dobey/ubuntu-sso-client/update-4-0 |
Merge into: | lp:ubuntu-sso-client/stable-4-0 |
Diff against target: |
1801 lines (+311/-618) 50 files modified
bin/ubuntu-sso-login (+1/-1) setup.py (+2/-4) ubuntu_sso/account.py (+5/-5) ubuntu_sso/gtk/gui.py (+23/-5) ubuntu_sso/gtk/tests/test_gui.py (+14/-5) ubuntu_sso/keyring/tests/test_linux.py (+1/-1) ubuntu_sso/logger.py (+2/-2) ubuntu_sso/main/__init__.py (+1/-1) ubuntu_sso/main/linux.py (+6/-1) ubuntu_sso/main/tests/test_linux.py (+59/-0) ubuntu_sso/networkstate/darwin.py (+2/-2) ubuntu_sso/networkstate/linux.py (+3/-3) ubuntu_sso/networkstate/windows.py (+1/-1) ubuntu_sso/qt/__init__.py (+1/-1) ubuntu_sso/qt/current_user_sign_in_page.py (+1/-3) ubuntu_sso/qt/main/__init__.py (+2/-0) ubuntu_sso/qt/main/tests/test_main.py (+1/-0) ubuntu_sso/qt/proxy_dialog.py (+1/-1) ubuntu_sso/qt/setup_account_page.py (+2/-3) ubuntu_sso/qt/sso_wizard_page.py (+2/-2) ubuntu_sso/qt/tests/test_arrow.py (+1/-1) ubuntu_sso/qt/tests/test_common.py (+3/-3) ubuntu_sso/qt/tests/test_current_user_sign_in_page.py (+1/-1) ubuntu_sso/qt/tests/test_setup_account.py (+1/-2) ubuntu_sso/tests/test_account.py (+1/-1) ubuntu_sso/tests/test_credentials.py (+2/-1) ubuntu_sso/utils/__init__.py (+1/-1) ubuntu_sso/utils/ipc.py (+3/-3) ubuntu_sso/utils/runner/glib.py (+1/-1) ubuntu_sso/utils/runner/tests/test_glib.py (+1/-1) ubuntu_sso/utils/runner/tests/test_qt.py (+2/-2) ubuntu_sso/utils/runner/tx.py (+2/-2) ubuntu_sso/utils/tcpactivation.py (+5/-1) ubuntu_sso/utils/tests/test_common.py (+1/-0) ubuntu_sso/utils/tests/test_tcpactivation.py (+49/-50) ubuntu_sso/utils/txsecrets.py (+1/-1) ubuntu_sso/utils/webclient/common.py (+2/-2) ubuntu_sso/utils/webclient/gsettings.py (+9/-2) ubuntu_sso/utils/webclient/libsoup.py (+1/-1) ubuntu_sso/utils/webclient/qtnetwork.py (+3/-3) ubuntu_sso/utils/webclient/restful.py (+12/-1) ubuntu_sso/utils/webclient/tests/test_gsettings.py (+32/-0) ubuntu_sso/utils/webclient/tests/test_restful.py (+44/-0) ubuntu_sso/utils/webclient/tests/test_webclient.py (+2/-2) ubuntu_sso/utils/webclient/timestamp.py (+1/-1) ubuntu_sso/xdg_base_directory/__init__.py (+0/-104) ubuntu_sso/xdg_base_directory/tests/__init__.py (+0/-29) ubuntu_sso/xdg_base_directory/tests/test_common.py (+0/-91) ubuntu_sso/xdg_base_directory/tests/test_windows.py (+0/-157) ubuntu_sso/xdg_base_directory/windows.py (+0/-113) |
To merge this branch: | bzr merge lp:~dobey/ubuntu-sso-client/update-4-0 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alejandro J. Cura (community) | Approve | ||
Roberto Alsina (community) | Approve | ||
Review via email: mp+112380@code.launchpad.net |
Commit message
[Mike McCracken]
- Delay importing twisted.
- Correctly bring main sso client window to the front on OS X. (LP: #1012837)
- Fixes bug with loading incorrect plug-ins caused by ignoring qt.conf. (LP: #1010102)
[Alejandro Cura]
- Account for g_variant_print type annotations (LP: #1007109).
[Brian Curtin]
- Move from iteritems/
- Use Python 3 style exception handling syntax.
[Rodney Dawes]
- Remove the xdg_base_directory module as it duplicates dirspec now.
- Disable the color validation for warning labels due to new GTK+ breaking it.
- Ensure we are using strict ssl with the system ca-certificates.crt file.
- Trap DBusException when getting the SessionBus, and add a test case for it.
[Manuel de la Pena]
- Changed tests so that they use u1-dev-tools better and do not get blocked in the clean up (LP: #1009071).
[Natalia Bidart]
- Added a little more logging to the webclient when doing REST calls.
[Roberto Alsina]
- Remove back buttons in signin/signup pages (Fixes LP: #1009107).
Description of the change
Ubuntu One Auto Pilot (otto-pilot) wrote : | # |
Voting does not meet specified criteria. Required: Approve >= 1, Disapprove == 0, Needs Fixing == 0, Needs Information == 0, Resubmit == 0, Pending == 0. Got: 1 Approve, 1 Pending.
Alejandro J. Cura (alecu) wrote : | # |
+1 looks just like trunk
- 960. By Brian Curtin
-
[Mike McCracken]
- Delay importing twisted.
internet. reactor to avoid creating default reactor when we need qt4reactor. (LP: #1017672)
- Correctly bring main sso client window to the front on OS X. (LP: #1012837)
- Fixes bug with loading incorrect plug-ins caused by ignoring qt.conf. (LP: #1010102)[Alejandro Cura]
- Account for g_variant_print type annotations (LP: #1007109).
[Brian Curtin]
- Move from iteritems/
itervalues to items/values for Python 3 support.
- Use Python 3 style exception handling syntax.[Rodney Dawes]
- Remove the xdg_base_directory module as it duplicates dirspec now.
- Disable the color validation for warning labels due to new GTK+ breaking it.
- Ensure we are using strict ssl with the system ca-certificates.crt file.
- Trap DBusException when getting the SessionBus, and add a test case for it.[Manuel de la Pena]
- Changed tests so that they use u1-dev-tools better and do not get blocked in the clean up (LP: #1009071).
[Natalia Bidart]
- Added a little more logging to the webclient when doing REST calls.
[Roberto Alsina]
- Remove back buttons in signin/signup pages (Fixes LP: #1009107).
Preview Diff
1 | === modified file 'bin/ubuntu-sso-login' |
2 | --- bin/ubuntu-sso-login 2012-05-18 14:25:49 +0000 |
3 | +++ bin/ubuntu-sso-login 2012-06-27 15:30:29 +0000 |
4 | @@ -57,7 +57,7 @@ |
5 | # need to create the QApplication before installing the reactor |
6 | if os.environ.get('TESTABILITY', False): |
7 | sys.argv.append('-testability') |
8 | - QtGui.QApplication(sys.argv) |
9 | + app = QtGui.QApplication(sys.argv) |
10 | |
11 | # pylint: disable=F0401 |
12 | import qt4reactor |
13 | |
14 | === modified file 'setup.py' |
15 | --- setup.py 2012-06-05 19:55:04 +0000 |
16 | +++ setup.py 2012-06-27 15:30:29 +0000 |
17 | @@ -301,8 +301,8 @@ |
18 | author='Natalia Bidart', |
19 | author_email='natalia.bidart@canonical.com', |
20 | description='Ubuntu Single Sign-On client', |
21 | - long_description='Desktop service to allow applications to sign in' \ |
22 | - 'to Ubuntu services via SSO', |
23 | + long_description=('Desktop service to allow applications to sign in' |
24 | + 'to Ubuntu services via SSO'), |
25 | url='https://launchpad.net/ubuntu-sso-client', |
26 | extra_path='ubuntu-sso-client', |
27 | data_files=data_files, |
28 | @@ -325,8 +325,6 @@ |
29 | 'ubuntu_sso.utils.runner.tests', |
30 | 'ubuntu_sso.utils.webclient', |
31 | 'ubuntu_sso.utils.webclient.tests', |
32 | - 'ubuntu_sso.xdg_base_directory', |
33 | - 'ubuntu_sso.xdg_base_directory.tests', |
34 | ], |
35 | cmdclass=cmdclass, |
36 | **extra) |
37 | |
38 | === modified file 'ubuntu_sso/account.py' |
39 | --- ubuntu_sso/account.py 2012-05-29 16:56:45 +0000 |
40 | +++ ubuntu_sso/account.py 2012-06-27 15:30:29 +0000 |
41 | @@ -110,7 +110,7 @@ |
42 | def _format_webservice_errors(self, errdict): |
43 | """Turn each list of strings in the errdict into a LF separated str.""" |
44 | result = {} |
45 | - for key, val in errdict.iteritems(): |
46 | + for key, val in errdict.items(): |
47 | # workaround until bug #624955 is solved |
48 | if isinstance(val, basestring): |
49 | result[key] = val |
50 | @@ -197,7 +197,7 @@ |
51 | finally: |
52 | restful_client.shutdown() |
53 | |
54 | - logger.debug('login: authentication successful! consumer_key: %r, ' \ |
55 | + logger.debug('login: authentication successful! consumer_key: %r, ' |
56 | 'token_name: %r', credentials['consumer_key'], token_name) |
57 | defer.returnValue(credentials) |
58 | |
59 | @@ -212,7 +212,7 @@ |
60 | finally: |
61 | restful_client.shutdown() |
62 | key = 'preferred_email' |
63 | - result = key in me_info and me_info[key] != None |
64 | + result = key in me_info and me_info[key] is not None |
65 | |
66 | logger.info('is_validated: consumer_key: %r, result: %r.', |
67 | token['consumer_key'], result) |
68 | @@ -249,7 +249,7 @@ |
69 | try: |
70 | operation = u"registration.request_password_reset_token" |
71 | result = yield restful_client.restcall(operation, email=email) |
72 | - except WebClientError, e: |
73 | + except WebClientError as e: |
74 | logger.exception('request_password_reset_token failed with:') |
75 | raise ResetPasswordTokenError(e[1].split('\n')[0]) |
76 | finally: |
77 | @@ -275,7 +275,7 @@ |
78 | u"registration.set_new_password", |
79 | email=email, token=token, |
80 | new_password=new_password) |
81 | - except WebClientError, e: |
82 | + except WebClientError as e: |
83 | logger.exception('set_new_password failed with:') |
84 | raise NewPasswordError(e[1].split('\n')[0]) |
85 | finally: |
86 | |
87 | === modified file 'ubuntu_sso/gtk/gui.py' |
88 | --- ubuntu_sso/gtk/gui.py 2012-04-11 16:38:28 +0000 |
89 | +++ ubuntu_sso/gtk/gui.py 2012-06-27 15:30:29 +0000 |
90 | @@ -109,6 +109,12 @@ |
91 | LARGE_MARKUP = u'<span size="x-large">%s</span>' |
92 | |
93 | |
94 | +# SSL properties and certs location |
95 | +STRICT_SSL_PROP = 'ssl-strict' |
96 | +CERTS_FILE_PROP = 'ssl-ca-file' |
97 | +CA_CERT_FILE = '/etc/ssl/certs/ca-certificates.crt' |
98 | + |
99 | + |
100 | def log_call(f): |
101 | """Decorator to log call funtions.""" |
102 | |
103 | @@ -356,7 +362,7 @@ |
104 | if app_name == self.app_name: |
105 | result = f(app_name, *args, **kwargs) |
106 | else: |
107 | - logger.info('%s: ignoring call since received app_name '\ |
108 | + logger.info('%s: ignoring call since received app_name ' |
109 | '%r (expected %r)', |
110 | f.__name__, app_name, self.app_name) |
111 | return result |
112 | @@ -365,7 +371,7 @@ |
113 | |
114 | def _setup_signals(self): |
115 | """Bind signals to callbacks to be able to test the pages.""" |
116 | - for signal, method in self._signals.iteritems(): |
117 | + for signal, method in self._signals.items(): |
118 | actual = self._signals_receivers.get(signal) |
119 | if actual is not None: |
120 | msg = 'Signal %r is already connected with %r.' |
121 | @@ -703,7 +709,7 @@ |
122 | if os.path.exists(self._captcha_filename): |
123 | os.remove(self._captcha_filename) |
124 | |
125 | - for signal, match in self._signals_receivers.iteritems(): |
126 | + for signal, match in self._signals_receivers.items(): |
127 | self.backend.disconnect_from_signal(signal, match) |
128 | |
129 | # hide the main window |
130 | @@ -790,7 +796,7 @@ |
131 | self.user_email = email1 |
132 | self.user_password = password1 |
133 | |
134 | - logger.info('Calling register_user with email %r, password <hidden>,' \ |
135 | + logger.info('Calling register_user with email %r, password <hidden>,' |
136 | ' name %r, captcha_id %r and captcha_solution %r.', email1, |
137 | name, self._captcha_id, captcha_solution) |
138 | |
139 | @@ -943,7 +949,7 @@ |
140 | return |
141 | |
142 | email = self.reset_email_entry.get_text() |
143 | - logger.info('Calling set_new_password with email %r, token %r and ' \ |
144 | + logger.info('Calling set_new_password with email %r, token %r and ' |
145 | 'new password: <hidden>.', email, token) |
146 | f = self.backend.set_new_password |
147 | error_handler = partial(self._handle_error, f, |
148 | @@ -953,11 +959,23 @@ |
149 | |
150 | self._set_current_page(self.processing_vbox) |
151 | |
152 | + def _webkit_init_ssl(self): |
153 | + """Set the WebKit ssl strictness.""" |
154 | + # delay the import of webkit to be able to build without it |
155 | + from gi.repository import WebKit # pylint: disable=E0611 |
156 | + |
157 | + # Set the Soup session to be strict and use system CA certs |
158 | + session = WebKit.get_default_session() |
159 | + session.set_property(STRICT_SSL_PROP, True) |
160 | + session.set_property(CERTS_FILE_PROP, CA_CERT_FILE) |
161 | + |
162 | def _add_webkit_browser(self): |
163 | """Add the webkit browser for the t&c.""" |
164 | # delay the import of webkit to be able to build without it |
165 | from gi.repository import WebKit # pylint: disable=E0611 |
166 | |
167 | + self._webkit_init_ssl() |
168 | + |
169 | browser = WebKit.WebView() |
170 | |
171 | browser.connect('notify::load-status', |
172 | |
173 | === modified file 'ubuntu_sso/gtk/tests/test_gui.py' |
174 | --- ubuntu_sso/gtk/tests/test_gui.py 2012-04-11 16:38:28 +0000 |
175 | +++ ubuntu_sso/gtk/tests/test_gui.py 2012-06-27 15:30:29 +0000 |
176 | @@ -168,6 +168,7 @@ |
177 | self.memento = MementoHandler() |
178 | self.memento.setLevel(logging.DEBUG) |
179 | gui.logger.addHandler(self.memento) |
180 | + self.addCleanup(gui.logger.removeHandler, self.memento) |
181 | |
182 | def _set_called(self, *args, **kwargs): |
183 | """Set _called to True.""" |
184 | @@ -446,9 +447,10 @@ |
185 | self.assertEqual(actual, message) |
186 | |
187 | # content color is correct |
188 | - expected = gui.WARNING_TEXT_COLOR |
189 | - actual = label.get_style().fg[Gtk.StateFlags.NORMAL] |
190 | - self.assert_color_equal(expected, actual) |
191 | + # FIXME - New GTK+ 3.5 breaks this check - see bug #1014772 |
192 | + # expected = gui.WARNING_TEXT_COLOR |
193 | + # actual = label.get_style().fg[Gtk.StateFlags.NORMAL] |
194 | + # self.assert_color_equal(expected, actual) |
195 | |
196 | def assert_correct_entry_warning(self, entry, message): |
197 | """Check that a warning is shown displaying 'message'.""" |
198 | @@ -911,6 +913,7 @@ |
199 | def setUp(self): |
200 | yield super(TermsAndConditionsBrowserTestCase, self).setUp() |
201 | self.patch(WebKit, 'WebView', FakedEmbeddedBrowser) |
202 | + self.patch(self.ui, '_webkit_init_ssl', self._set_called) |
203 | |
204 | self.ui.tc_button.clicked() |
205 | self.addCleanup(self.ui.tc_browser_vbox.hide) |
206 | @@ -919,6 +922,12 @@ |
207 | assert len(children) == 1 |
208 | self.browser = children[0] |
209 | |
210 | + def test_ssl_validation(self): |
211 | + """The browser is set to validate SSL.""" |
212 | + self.assertEqual(self._called, ((), {}), |
213 | + '_webkit_init_ssl should be called when creating a ' |
214 | + 'webkit browser.') |
215 | + |
216 | def test_tc_browser_is_created_when_tc_page_is_shown(self): |
217 | """The browser is created when the TC button is clicked.""" |
218 | self.ui.on_tc_browser_notify_load_status(self.browser) |
219 | @@ -1983,7 +1992,7 @@ |
220 | """Callbacks are connected to signals of interest.""" |
221 | msg1 = 'callback %r for signal %r must be added to the backend.' |
222 | msg2 = 'callback %r for signal %r must be added to the ui log.' |
223 | - for signal, method in self.ui._signals.iteritems(): |
224 | + for signal, method in self.ui._signals.items(): |
225 | actual = self.ui.backend.callbacks.get(signal) |
226 | self.assertEqual([method], actual, msg1 % (method, signal)) |
227 | actual = self.ui._signals_receivers.get(signal) |
228 | @@ -1992,7 +2001,7 @@ |
229 | def test_callbacks_only_log_when_app_name_doesnt_match(self): |
230 | """Callbacks do nothing but logging when app_name doesn't match.""" |
231 | mismatch_app_name = self.ui.app_name * 2 |
232 | - for method in self.ui._signals.itervalues(): |
233 | + for method in self.ui._signals.values(): |
234 | msgs = ('ignoring', method.__name__, repr(mismatch_app_name)) |
235 | method(mismatch_app_name, 'dummy') |
236 | self.assertTrue(self.memento.check(logging.INFO, *msgs)) |
237 | |
238 | === modified file 'ubuntu_sso/keyring/tests/test_linux.py' |
239 | --- ubuntu_sso/keyring/tests/test_linux.py 2012-04-09 17:38:24 +0000 |
240 | +++ ubuntu_sso/keyring/tests/test_linux.py 2012-06-27 15:30:29 +0000 |
241 | @@ -137,7 +137,7 @@ |
242 | |
243 | def get_mock_service(self): |
244 | """Create only one instance of the mock service per test.""" |
245 | - if self.mock_service == None: |
246 | + if self.mock_service is None: |
247 | self.mock_service = MockSecretService() |
248 | return self.mock_service |
249 | |
250 | |
251 | === modified file 'ubuntu_sso/logger.py' |
252 | --- ubuntu_sso/logger.py 2012-04-09 17:38:24 +0000 |
253 | +++ ubuntu_sso/logger.py 2012-06-27 15:30:29 +0000 |
254 | @@ -37,11 +37,11 @@ |
255 | import os |
256 | import sys |
257 | |
258 | +from dirspec.basedir import xdg_cache_home |
259 | +from dirspec.utils import unicode_path |
260 | from functools import wraps |
261 | from logging.handlers import RotatingFileHandler |
262 | |
263 | -from ubuntu_sso.xdg_base_directory import unicode_path, xdg_cache_home |
264 | - |
265 | LOGFOLDER = os.path.join(xdg_cache_home, 'sso') |
266 | # create log folder if it doesn't exists |
267 | if not os.path.exists(unicode_path(LOGFOLDER)): |
268 | |
269 | === modified file 'ubuntu_sso/main/__init__.py' |
270 | --- ubuntu_sso/main/__init__.py 2012-05-21 14:28:14 +0000 |
271 | +++ ubuntu_sso/main/__init__.py 2012-06-27 15:30:29 +0000 |
272 | @@ -348,7 +348,7 @@ |
273 | |
274 | def _parse_args(self, args): |
275 | """Retrieve values from the generic param 'args'.""" |
276 | - result = dict(i for i in args.iteritems() if i[0] in self.valid_keys) |
277 | + result = dict(i for i in args.items() if i[0] in self.valid_keys) |
278 | result[WINDOW_ID_KEY] = int(args.get(WINDOW_ID_KEY, 0)) |
279 | return result |
280 | |
281 | |
282 | === modified file 'ubuntu_sso/main/linux.py' |
283 | --- ubuntu_sso/main/linux.py 2012-04-10 10:43:48 +0000 |
284 | +++ ubuntu_sso/main/linux.py 2012-06-27 15:30:29 +0000 |
285 | @@ -342,10 +342,15 @@ |
286 | |
287 | def __init__(self, root): |
288 | self.root = root |
289 | - self.bus = dbus.SessionBus() |
290 | self.sso_login = None |
291 | self.cred_manager = None |
292 | |
293 | + try: |
294 | + self.bus = dbus.SessionBus() |
295 | + except dbus.service.DBusException as e: |
296 | + logger.exception(e) |
297 | + shutdown_func() |
298 | + |
299 | def start(self): |
300 | """Start listening, nothing async to be done in this platform.""" |
301 | # Register DBus service for making sure we run only one instance |
302 | |
303 | === added file 'ubuntu_sso/main/tests/test_linux.py' |
304 | --- ubuntu_sso/main/tests/test_linux.py 1970-01-01 00:00:00 +0000 |
305 | +++ ubuntu_sso/main/tests/test_linux.py 2012-06-27 15:30:29 +0000 |
306 | @@ -0,0 +1,59 @@ |
307 | +# -*- coding: utf-8 -*- |
308 | +# |
309 | +# Copyright 2012 Canonical Ltd. |
310 | +# |
311 | +# This program is free software: you can redistribute it and/or modify it |
312 | +# under the terms of the GNU General Public License version 3, as published |
313 | +# by the Free Software Foundation. |
314 | +# |
315 | +# This program is distributed in the hope that it will be useful, but |
316 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
317 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
318 | +# PURPOSE. See the GNU General Public License for more details. |
319 | +# |
320 | +# You should have received a copy of the GNU General Public License along |
321 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
322 | +# |
323 | +# In addition, as a special exception, the copyright holders give |
324 | +# permission to link the code of portions of this program with the |
325 | +# OpenSSL library under certain conditions as described in each |
326 | +# individual source file, and distribute linked combinations |
327 | +# including the two. |
328 | +# You must obey the GNU General Public License in all respects |
329 | +# for all of the code used other than OpenSSL. If you modify |
330 | +# file(s) with this exception, you may extend this exception to your |
331 | +# version of the file(s), but you are not obligated to do so. If you |
332 | +# do not wish to do so, delete this exception statement from your |
333 | +# version. If you delete this exception statement from all source |
334 | +# files in the program, then also delete it here. |
335 | +"""Tests for the main SSO Linux client code.""" |
336 | + |
337 | +# pylint: disable=C0103 |
338 | +do_tests = False |
339 | +try: |
340 | + import dbus |
341 | + import dbus.service |
342 | + from ubuntu_sso.main import linux as main |
343 | + do_tests = True |
344 | +except ImportError: |
345 | + do_tests = False |
346 | +# pylint enable=C0103 |
347 | + |
348 | +from ubuntuone.devtools.testcases import BaseTestCase, skipIf |
349 | + |
350 | + |
351 | +@skipIf(not do_tests, 'Tests only work with DBus and linux imports.') |
352 | +class LinuxProxyTestCase(BaseTestCase): |
353 | + """Test some Linux specific cases.""" |
354 | + |
355 | + def test_dbus_missing_exists_clean(self): |
356 | + """Test that dbus-daemon not being available gives us a clean exit.""" |
357 | + def patched(*args, **kwargs): |
358 | + """Method to patch in for testing.""" |
359 | + raise dbus.service.DBusException( |
360 | + 'org.freedesktop.DBus.Error.NoServer') |
361 | + |
362 | + self.patch(dbus, "SessionBus", patched) |
363 | + self.patch(main, "shutdown_func", patched) |
364 | + self.assertRaises(dbus.service.DBusException, |
365 | + main.UbuntuSSOProxy, None) |
366 | |
367 | === modified file 'ubuntu_sso/networkstate/darwin.py' |
368 | --- ubuntu_sso/networkstate/darwin.py 2012-05-21 14:48:25 +0000 |
369 | +++ ubuntu_sso/networkstate/darwin.py 2012-06-27 15:30:29 +0000 |
370 | @@ -126,7 +126,7 @@ |
371 | CFRelease(target) |
372 | |
373 | if not ok: |
374 | - logger.error("Error getting reachability status of '%s'" % \ |
375 | + logger.error("Error getting reachability status of '%s'" % |
376 | HOSTNAME_TO_CHECK) |
377 | raise NetworkFailException() |
378 | |
379 | @@ -298,6 +298,6 @@ |
380 | """ |
381 | try: |
382 | return defer.succeed(check_connected_state()) |
383 | - except Exception, e: # pylint: disable=W0703 |
384 | + except Exception as e: # pylint: disable=W0703 |
385 | logger.exception("Exception calling check_connected_state:") |
386 | return defer.fail(NetworkFailException(e)) |
387 | |
388 | === modified file 'ubuntu_sso/networkstate/linux.py' |
389 | --- ubuntu_sso/networkstate/linux.py 2012-05-24 04:20:08 +0000 |
390 | +++ ubuntu_sso/networkstate/linux.py 2012-06-27 15:30:29 +0000 |
391 | @@ -79,7 +79,7 @@ |
392 | # the user has connected in some other way |
393 | self.call_result_cb(ONLINE) |
394 | else: |
395 | - logger.error("Error contacting NetworkManager: %s" % \ |
396 | + logger.error("Error contacting NetworkManager: %s" % |
397 | str(error)) |
398 | self.call_result_cb(UNKNOWN) |
399 | |
400 | @@ -107,7 +107,7 @@ |
401 | nm_proxy.Get(NM_DBUS_INTERFACE, "State", |
402 | reply_handler=self.got_state, |
403 | error_handler=self.got_error) |
404 | - except Exception, e: # pylint: disable=W0703 |
405 | + except Exception as e: # pylint: disable=W0703 |
406 | self.got_error(e) |
407 | |
408 | |
409 | @@ -127,7 +127,7 @@ |
410 | try: |
411 | network = NetworkManagerState(got_state) |
412 | network.find_online_state() |
413 | - except Exception, e: |
414 | + except Exception as e: |
415 | logger.exception('is_machine_connected failed with:') |
416 | d.errback(NetworkFailException(e)) |
417 | # pylint: enable=W0702, W0703 |
418 | |
419 | === modified file 'ubuntu_sso/networkstate/windows.py' |
420 | --- ubuntu_sso/networkstate/windows.py 2012-04-09 17:38:24 +0000 |
421 | +++ ubuntu_sso/networkstate/windows.py 2012-06-27 15:30:29 +0000 |
422 | @@ -184,7 +184,7 @@ |
423 | flags = DWORD() |
424 | connected = wininet.InternetGetConnectedState(byref(flags), None) |
425 | return defer.succeed(connected == 1) |
426 | - except Exception, e: |
427 | + except Exception as e: |
428 | logger.exception('is_machine_connected failed with:') |
429 | return defer.fail(NetworkFailException(e)) |
430 | # pylint: enable=W0703, W0702 |
431 | |
432 | === modified file 'ubuntu_sso/qt/__init__.py' |
433 | --- ubuntu_sso/qt/__init__.py 2012-04-23 13:32:52 +0000 |
434 | +++ ubuntu_sso/qt/__init__.py 2012-06-27 15:30:29 +0000 |
435 | @@ -75,7 +75,7 @@ |
436 | if 'errtype' in errordict: |
437 | del errordict['errtype'] |
438 | result = '\n'.join( |
439 | - [('%s: %s' % (k, v)) for k, v in errordict.iteritems()]) |
440 | + [('%s: %s' % (k, v)) for k, v in errordict.items()]) |
441 | else: |
442 | result = GENERIC_BACKEND_ERROR |
443 | logger.error('build_general_error_message with unknown error: %r', |
444 | |
445 | === modified file 'ubuntu_sso/qt/current_user_sign_in_page.py' |
446 | --- ubuntu_sso/qt/current_user_sign_in_page.py 2012-04-09 17:38:24 +0000 |
447 | +++ ubuntu_sso/qt/current_user_sign_in_page.py 2012-06-27 15:30:29 +0000 |
448 | @@ -97,9 +97,7 @@ |
449 | self.setButtonText(QtGui.QWizard.CancelButton, CANCEL_BUTTON) |
450 | # Layout without custom button 1, |
451 | # without finish button |
452 | - self.wizard().setButtonLayout([ |
453 | - QtGui.QWizard.BackButton, |
454 | - QtGui.QWizard.Stretch]) |
455 | + self.wizard().setButtonLayout([]) |
456 | |
457 | # Set sign_in_button as default when the page is shown. |
458 | self.ui.sign_in_button.setDefault(True) |
459 | |
460 | === modified file 'ubuntu_sso/qt/main/__init__.py' |
461 | --- ubuntu_sso/qt/main/__init__.py 2012-05-09 18:00:22 +0000 |
462 | +++ ubuntu_sso/qt/main/__init__.py 2012-06-27 15:30:29 +0000 |
463 | @@ -80,5 +80,7 @@ |
464 | ui.size(), app.desktop().availableGeometry()) |
465 | ui.setGeometry(style) |
466 | ui.show() |
467 | + if sys.platform == 'darwin': |
468 | + ui.raise_() |
469 | |
470 | source.main_start(app) |
471 | |
472 | === modified file 'ubuntu_sso/qt/main/tests/test_main.py' |
473 | --- ubuntu_sso/qt/main/tests/test_main.py 2012-05-09 17:48:32 +0000 |
474 | +++ ubuntu_sso/qt/main/tests/test_main.py 2012-06-27 15:30:29 +0000 |
475 | @@ -53,6 +53,7 @@ |
476 | """Fake setGeometry.""" |
477 | |
478 | show = setGeometry |
479 | + raise_ = lambda self: None |
480 | |
481 | |
482 | class FakeDesktop(object): |
483 | |
484 | === modified file 'ubuntu_sso/qt/proxy_dialog.py' |
485 | --- ubuntu_sso/qt/proxy_dialog.py 2012-04-09 17:38:24 +0000 |
486 | +++ ubuntu_sso/qt/proxy_dialog.py 2012-06-27 15:30:29 +0000 |
487 | @@ -116,7 +116,7 @@ |
488 | try: |
489 | logger.debug('Save credentials as for domain %s.', self.domain) |
490 | yield self.keyring.set_credentials(self.domain, creds) |
491 | - except Exception, e: |
492 | + except Exception as e: |
493 | logger.exception('Could not set credentials:') |
494 | self.done(EXCEPTION_RAISED) |
495 | logger.debug('Stored creds') |
496 | |
497 | === modified file 'ubuntu_sso/qt/setup_account_page.py' |
498 | --- ubuntu_sso/qt/setup_account_page.py 2012-05-01 12:48:42 +0000 |
499 | +++ ubuntu_sso/qt/setup_account_page.py 2012-06-27 15:30:29 +0000 |
500 | @@ -154,7 +154,6 @@ |
501 | |
502 | # Button setup |
503 | self.wizard().setButtonLayout([ |
504 | - QtGui.QWizard.BackButton, |
505 | QtGui.QWizard.Stretch, |
506 | QtGui.QWizard.CustomButton3]) |
507 | |
508 | @@ -246,8 +245,8 @@ |
509 | common.NORMAL)) |
510 | |
511 | self.ui.refresh_label.linkActivated.connect(self.hide_error) |
512 | - self.ui.refresh_label.linkActivated.connect(lambda url: \ |
513 | - self._refresh_captcha()) |
514 | + self.ui.refresh_label.linkActivated.connect( |
515 | + lambda url: self._refresh_captcha()) |
516 | # We need to check if we enable the button on many signals |
517 | self.ui.name_edit.textEdited.connect(self._enable_setup_button) |
518 | self.ui.email_edit.textEdited.connect(self._enable_setup_button) |
519 | |
520 | === modified file 'ubuntu_sso/qt/sso_wizard_page.py' |
521 | --- ubuntu_sso/qt/sso_wizard_page.py 2012-04-09 17:38:24 +0000 |
522 | +++ ubuntu_sso/qt/sso_wizard_page.py 2012-06-27 15:30:29 +0000 |
523 | @@ -253,7 +253,7 @@ |
524 | if app_name == self.app_name: |
525 | result = f(app_name, *args, **kwargs) |
526 | else: |
527 | - logger.info('%s: ignoring call since received app_name '\ |
528 | + logger.info('%s: ignoring call since received app_name ' |
529 | '"%s" (expected "%s")', |
530 | f.__name__, app_name, self.app_name) |
531 | return result |
532 | @@ -262,7 +262,7 @@ |
533 | |
534 | def _setup_signals(self): |
535 | """Bind signals to callbacks to be able to test the pages.""" |
536 | - for signal, method in self._signals.iteritems(): |
537 | + for signal, method in self._signals.items(): |
538 | actual = self._signals_receivers.get(signal) |
539 | if actual is not None: |
540 | msg = 'Signal %r is already connected with %r.' |
541 | |
542 | === modified file 'ubuntu_sso/qt/tests/test_arrow.py' |
543 | --- ubuntu_sso/qt/tests/test_arrow.py 2012-04-09 17:38:24 +0000 |
544 | +++ ubuntu_sso/qt/tests/test_arrow.py 2012-06-27 15:30:29 +0000 |
545 | @@ -96,7 +96,7 @@ |
546 | arrow = QArrow(QArrow.RIGHT) |
547 | self.patch(arrow, 'style', self.style) |
548 | |
549 | - for key, value in directions_map.iteritems(): |
550 | + for key, value in directions_map.items(): |
551 | self.style.called = [] |
552 | arrow.direction = key |
553 | arrow.paintEvent(None) |
554 | |
555 | === modified file 'ubuntu_sso/qt/tests/test_common.py' |
556 | --- ubuntu_sso/qt/tests/test_common.py 2012-04-09 17:38:24 +0000 |
557 | +++ ubuntu_sso/qt/tests/test_common.py 2012-06-27 15:30:29 +0000 |
558 | @@ -350,7 +350,7 @@ |
559 | result = build_general_error_message(err_dict) |
560 | |
561 | expected = '\n'.join( |
562 | - [('%s: %s' % (k, v)) for k, v in err_dict.iteritems()]) |
563 | + [('%s: %s' % (k, v)) for k, v in err_dict.items()]) |
564 | self.assertEqual(result, expected) |
565 | |
566 | def test_with_random_keys_with_errtype(self): |
567 | @@ -362,8 +362,8 @@ |
568 | result = build_general_error_message(err_dict) |
569 | |
570 | expected = '\n'.join( |
571 | - [('%s: %s' % (k, v)) \ |
572 | - for k, v in {'my_bad': error, 'odd_error': error2}.iteritems()]) |
573 | + [('%s: %s' % (k, v)) |
574 | + for k, v in {'my_bad': error, 'odd_error': error2}.items()]) |
575 | self.assertEqual(result, expected) |
576 | |
577 | def test_with_not_dict(self): |
578 | |
579 | === modified file 'ubuntu_sso/qt/tests/test_current_user_sign_in_page.py' |
580 | --- ubuntu_sso/qt/tests/test_current_user_sign_in_page.py 2012-04-09 17:38:24 +0000 |
581 | +++ ubuntu_sso/qt/tests/test_current_user_sign_in_page.py 2012-06-27 15:30:29 +0000 |
582 | @@ -59,7 +59,7 @@ |
583 | self.assertEqual(wizard.buttons_text[QtGui.QWizard.CancelButton], |
584 | "Cancel") |
585 | self.assertIn(('setButtonLayout', |
586 | - (([QtGui.QWizard.BackButton, QtGui.QWizard.Stretch],), {})), |
587 | + (([],), {})), |
588 | wizard.called) |
589 | self.assertTrue(button.properties['default']) |
590 | self.assertFalse(button.isEnabled()) |
591 | |
592 | === modified file 'ubuntu_sso/qt/tests/test_setup_account.py' |
593 | --- ubuntu_sso/qt/tests/test_setup_account.py 2012-04-09 17:38:24 +0000 |
594 | +++ ubuntu_sso/qt/tests/test_setup_account.py 2012-06-27 15:30:29 +0000 |
595 | @@ -207,8 +207,7 @@ |
596 | self.ui.initializePage() |
597 | |
598 | # set up account button |
599 | - expected = [QtGui.QWizard.BackButton, QtGui.QWizard.Stretch, |
600 | - QtGui.QWizard.CustomButton3] |
601 | + expected = [QtGui.QWizard.Stretch, QtGui.QWizard.CustomButton3] |
602 | self.assertIn(('setButtonLayout', ((expected,), {})), |
603 | self.ui.wizard().called) |
604 | self.assertEqual(gui.SET_UP_ACCOUNT_BUTTON, |
605 | |
606 | === modified file 'ubuntu_sso/tests/test_account.py' |
607 | --- ubuntu_sso/tests/test_account.py 2012-05-29 16:58:30 +0000 |
608 | +++ ubuntu_sso/tests/test_account.py 2012-06-27 15:30:29 +0000 |
609 | @@ -230,7 +230,7 @@ |
610 | |
611 | def verify_frc_shutdown(self): |
612 | """Verify that the FakeRestfulClient was stopped.""" |
613 | - assert self.frc.started == False, "Restfulclient must be shut down." |
614 | + assert self.frc.started is False, "Restfulclient must be shut down." |
615 | |
616 | @defer.inlineCallbacks |
617 | def test_generate_captcha(self): |
618 | |
619 | === modified file 'ubuntu_sso/tests/test_credentials.py' |
620 | --- ubuntu_sso/tests/test_credentials.py 2012-05-04 18:48:54 +0000 |
621 | +++ ubuntu_sso/tests/test_credentials.py 2012-06-27 15:30:29 +0000 |
622 | @@ -122,6 +122,7 @@ |
623 | self.memento = MementoHandler() |
624 | self.memento.setLevel(logging.DEBUG) |
625 | credentials.logger.addHandler(self.memento) |
626 | + self.addCleanup(credentials.logger.removeHandler, self.memento) |
627 | |
628 | self.patch(credentials, 'get_bin_dir', lambda: self.bin_dir) |
629 | |
630 | @@ -147,7 +148,7 @@ |
631 | |
632 | def test_creation_parameters_are_stored(self): |
633 | """Creation parameters are stored.""" |
634 | - for key, value in KWARGS.iteritems(): |
635 | + for key, value in KWARGS.items(): |
636 | self.assertEqual(getattr(self.obj, key), value) |
637 | |
638 | def test_tc_url_defaults_to_none(self): |
639 | |
640 | === modified file 'ubuntu_sso/utils/__init__.py' |
641 | --- ubuntu_sso/utils/__init__.py 2012-04-25 14:17:16 +0000 |
642 | +++ ubuntu_sso/utils/__init__.py 2012-06-27 15:30:29 +0000 |
643 | @@ -165,7 +165,7 @@ |
644 | logger.debug("Calculated server-local time skew: %r", |
645 | self.skew) |
646 | #pylint: disable=W0703 |
647 | - except Exception, server_error: |
648 | + except Exception as server_error: |
649 | logger.debug("Error while verifying the server time skew: %r", |
650 | server_error) |
651 | self.next_check = local_time + self.ERROR_INTERVAL |
652 | |
653 | === modified file 'ubuntu_sso/utils/ipc.py' |
654 | --- ubuntu_sso/utils/ipc.py 2012-05-16 09:48:55 +0000 |
655 | +++ ubuntu_sso/utils/ipc.py 2012-06-27 15:30:29 +0000 |
656 | @@ -132,7 +132,7 @@ |
657 | |
658 | def remote_unregister_to_signals(self, client): |
659 | """Allow a client to unregister from the signal.""" |
660 | - for connected_clients in self.clients_per_signal.itervalues(): |
661 | + for connected_clients in self.clients_per_signal.values(): |
662 | if client in connected_clients: |
663 | connected_clients.remove(client) |
664 | |
665 | @@ -198,7 +198,7 @@ |
666 | super(BaseService, self).__init__() |
667 | self.factory = None |
668 | self.listener = None |
669 | - for name, service_class in self.services.iteritems(): |
670 | + for name, service_class in self.services.items(): |
671 | service = service_class(*a, **kw) |
672 | setattr(self, name, service) |
673 | setattr(self, 'remote_get_%s' % name, |
674 | @@ -344,7 +344,7 @@ |
675 | """Request all the diff remote objects used for the communication.""" |
676 | logger.debug('Requesting remote objects (%r) for %s', |
677 | self.clients.keys(), self.__class__.__name__) |
678 | - for name, client_class in self.clients.iteritems(): |
679 | + for name, client_class in self.clients.items(): |
680 | remote = yield root.callRemote('get_%s' % name) |
681 | setattr(self, name, client_class(remote)) |
682 | |
683 | |
684 | === modified file 'ubuntu_sso/utils/runner/glib.py' |
685 | --- ubuntu_sso/utils/runner/glib.py 2012-04-09 17:38:24 +0000 |
686 | +++ ubuntu_sso/utils/runner/glib.py 2012-06-27 15:30:29 +0000 |
687 | @@ -89,7 +89,7 @@ |
688 | |
689 | try: |
690 | pid, _, _, _ = GLib.spawn_async(argv=bytes_args, flags=flags) |
691 | - except GLib.GError, e: |
692 | + except GLib.GError as e: |
693 | handle_error(e) |
694 | else: |
695 | logger.debug('Spawning the program %r with the glib mainloop ' |
696 | |
697 | === modified file 'ubuntu_sso/utils/runner/tests/test_glib.py' |
698 | --- ubuntu_sso/utils/runner/tests/test_glib.py 2012-04-09 17:38:24 +0000 |
699 | +++ ubuntu_sso/utils/runner/tests/test_glib.py 2012-06-27 15:30:29 +0000 |
700 | @@ -87,7 +87,7 @@ |
701 | |
702 | try: |
703 | subprocess.call(argv) |
704 | - except Exception, e: |
705 | + except Exception as e: |
706 | exc = GLib.GError() |
707 | exc.message = str(e) |
708 | exc.code = 42 |
709 | |
710 | === modified file 'ubuntu_sso/utils/runner/tests/test_qt.py' |
711 | --- ubuntu_sso/utils/runner/tests/test_qt.py 2012-04-09 17:38:24 +0000 |
712 | +++ ubuntu_sso/utils/runner/tests/test_qt.py 2012-06-27 15:30:29 +0000 |
713 | @@ -86,12 +86,12 @@ |
714 | |
715 | try: |
716 | subprocess.call(bytes_args) |
717 | - except OSError, e: |
718 | + except OSError as e: |
719 | if e.errno == 2: |
720 | self.error.emit(self.FailedToStart) |
721 | else: |
722 | self.error.emit(e) |
723 | - except Exception, e: |
724 | + except Exception as e: |
725 | self.error.emit(e) |
726 | else: |
727 | self.finished.emit(self._status_code) |
728 | |
729 | === modified file 'ubuntu_sso/utils/runner/tx.py' |
730 | --- ubuntu_sso/utils/runner/tx.py 2012-04-09 17:38:24 +0000 |
731 | +++ ubuntu_sso/utils/runner/tx.py 2012-06-27 15:30:29 +0000 |
732 | @@ -102,9 +102,9 @@ |
733 | |
734 | try: |
735 | d = utils.getProcessOutputAndValue(program, bytes_args, env=os.environ) |
736 | - except OSError, e: |
737 | + except OSError as e: |
738 | error_handler(msg=e, failed_to_start=True) |
739 | - except Exception, e: |
740 | + except Exception as e: |
741 | error_handler(msg=e, failed_to_start=False) |
742 | else: |
743 | logger.debug('Spawning the program %r with the twisted reactor ' |
744 | |
745 | === modified file 'ubuntu_sso/utils/tcpactivation.py' |
746 | --- ubuntu_sso/utils/tcpactivation.py 2012-05-03 11:42:55 +0000 |
747 | +++ ubuntu_sso/utils/tcpactivation.py 2012-06-27 15:30:29 +0000 |
748 | @@ -30,7 +30,7 @@ |
749 | |
750 | import subprocess |
751 | |
752 | -from twisted.internet import defer, error, protocol, reactor |
753 | +from twisted.internet import defer, error, protocol |
754 | from twisted.internet.endpoints import clientFromString |
755 | |
756 | LOCALHOST = "127.0.0.1" |
757 | @@ -43,6 +43,7 @@ |
758 | |
759 | def async_sleep(delay): |
760 | """Fire the returned deferred after some specified delay.""" |
761 | + from twisted.internet import reactor |
762 | d = defer.Deferred() |
763 | # pylint: disable=E1101 |
764 | reactor.callLater(delay, d.callback, None) |
765 | @@ -87,11 +88,13 @@ |
766 | |
767 | def clientConnectionLost(self, connector, reason): |
768 | """The connection was lost.""" |
769 | + protocol.ClientFactory.clientConnectionLost(self, connector, reason) |
770 | if not self.d.called: |
771 | self.d.callback(False) |
772 | |
773 | def clientConnectionFailed(self, connector, reason): |
774 | """The connection failed.""" |
775 | + protocol.ClientFactory.clientConnectionFailed(self, connector, reason) |
776 | if not self.d.called: |
777 | self.d.callback(False) |
778 | |
779 | @@ -116,6 +119,7 @@ |
780 | @defer.inlineCallbacks |
781 | def is_already_running(self): |
782 | """Check if the instance is already running.""" |
783 | + from twisted.internet import reactor |
784 | factory = PortDetectFactory() |
785 | client = clientFromString(reactor, self.config.description.client) |
786 | try: |
787 | |
788 | === modified file 'ubuntu_sso/utils/tests/test_common.py' |
789 | --- ubuntu_sso/utils/tests/test_common.py 2012-04-17 20:27:21 +0000 |
790 | +++ ubuntu_sso/utils/tests/test_common.py 2012-06-27 15:30:29 +0000 |
791 | @@ -106,6 +106,7 @@ |
792 | self.memento = MementoHandler() |
793 | self.memento.setLevel(logging.DEBUG) |
794 | utils.logger.addHandler(self.memento) |
795 | + self.addCleanup(utils.logger.removeHandler, self.memento) |
796 | |
797 | self.get_dir = getattr(utils, self.DIR_GETTER) |
798 | |
799 | |
800 | === modified file 'ubuntu_sso/utils/tests/test_tcpactivation.py' |
801 | --- ubuntu_sso/utils/tests/test_tcpactivation.py 2012-05-03 12:36:08 +0000 |
802 | +++ ubuntu_sso/utils/tests/test_tcpactivation.py 2012-06-27 15:30:29 +0000 |
803 | @@ -35,7 +35,8 @@ |
804 | # this test module access a few protected members (starting with _) |
805 | # pylint: disable=W0212 |
806 | |
807 | -from twisted.internet import defer, protocol, reactor, task |
808 | +import twisted.internet |
809 | +from twisted.internet import defer, protocol, task |
810 | from twisted.trial.unittest import TestCase |
811 | |
812 | # pylint: disable=W0611 |
813 | @@ -72,7 +73,7 @@ |
814 | self.transport.write(data) |
815 | |
816 | |
817 | -class FakeServerFactory(protocol.Factory): |
818 | +class FakeServerFactory(protocol.ServerFactory): |
819 | """A factory for the test server.""" |
820 | |
821 | protocol = FakeServerProtocol |
822 | @@ -97,37 +98,6 @@ |
823 | self.client = client_description |
824 | |
825 | |
826 | -class FakeConnectedClient(object): |
827 | - """Fake class use to patch connections.""" |
828 | - |
829 | - def __init__(self, testcase, inner): |
830 | - """Create a new instance.""" |
831 | - self.testcase = testcase |
832 | - self.inner = inner |
833 | - |
834 | - @defer.inlineCallbacks |
835 | - def connect(self, factory): |
836 | - """Connect using the given factory.""" |
837 | - # we need to get the class of the factory and patch it |
838 | - yield self.testcase.connect_client(PortDetectFactory) |
839 | - self.inner.factory = self.testcase.client_factory |
840 | - defer.returnValue(self.testcase.connector) |
841 | - |
842 | - |
843 | -class WrapperFactory(object): |
844 | - """Wrapps a factory so that it can be replaced in a test.""" |
845 | - |
846 | - def __init__(self, factory): |
847 | - self.factory = None |
848 | - |
849 | - def __call__(self, *args, **kwargs): |
850 | - return self |
851 | - |
852 | - def is_listening(self): |
853 | - """Return if the service is listening.""" |
854 | - return self.factory.is_listening() |
855 | - |
856 | - |
857 | class AsyncSleepTestCase(TestCase): |
858 | """Tests for the async_sleep function.""" |
859 | |
860 | @@ -137,7 +107,7 @@ |
861 | yield super(AsyncSleepTestCase, self).setUp() |
862 | self.test_timeout = 5.0 |
863 | self.clock = task.Clock() |
864 | - self.patch(tcpactivation, "reactor", self.clock) |
865 | + self.patch(twisted.internet, "reactor", self.clock) |
866 | self.d = tcpactivation.async_sleep(self.test_timeout) |
867 | |
868 | def test_async_sleep_not_fired_immediately(self): |
869 | @@ -231,7 +201,7 @@ |
870 | self.assertEqual(config.description, SAMPLE_CLIENT_DESCRIPTION) |
871 | |
872 | |
873 | -class ActivationDetectorTestCase(ServerTestCase): |
874 | +class ActivationDetectorTestCase(TestCase): |
875 | """Tests for the ActivationDetector class.""" |
876 | |
877 | timeoue = 3 |
878 | @@ -270,15 +240,29 @@ |
879 | @defer.inlineCallbacks |
880 | def test_is_already_running(self): |
881 | """The is_already_running method returns True if already started.""" |
882 | - inner = WrapperFactory(None) |
883 | - |
884 | - self.patch(tcpactivation, 'PortDetectFactory', inner) |
885 | - client = FakeConnectedClient(self, inner) |
886 | + server = self.get_server() |
887 | + self.addCleanup(server.clean_up) |
888 | + |
889 | + class TestConnect(object): |
890 | + """A fake connection object.""" |
891 | + |
892 | + # pylint: disable=E0213 |
893 | + @defer.inlineCallbacks |
894 | + def connect(my_self, factory): |
895 | + """A fake connection.""" |
896 | + |
897 | + connected_factory = yield server.connect_client( |
898 | + PortDetectFactory) |
899 | + self.patch(factory, 'is_listening', |
900 | + connected_factory.is_listening) |
901 | + defer.returnValue(connected_factory) |
902 | + # pylint: enable=E0213 |
903 | |
904 | self.patch(tcpactivation, 'clientFromString', |
905 | - lambda *args: client) |
906 | - |
907 | - yield self.listen_server(FakeServerFactory) |
908 | + lambda *args: TestConnect()) |
909 | + |
910 | + yield server.listen_server(protocol.ServerFactory) |
911 | + |
912 | # pylint: disable=E1101 |
913 | ad = ActivationDetector(self.config) |
914 | result = yield ad.is_already_running() |
915 | @@ -347,7 +331,7 @@ |
916 | """Test the _wait_server_active method.""" |
917 | ac = ActivationClient(self.config) |
918 | clock = task.Clock() |
919 | - self.patch(tcpactivation, "reactor", clock) |
920 | + self.patch(twisted.internet, "reactor", clock) |
921 | self.patch(ac, "is_already_running", lambda: defer.succeed(False)) |
922 | |
923 | d = ac._wait_server_active() |
924 | @@ -363,7 +347,7 @@ |
925 | """If the server takes too long to start then timeout.""" |
926 | ac = ActivationClient(self.config) |
927 | clock = task.Clock() |
928 | - self.patch(tcpactivation, "reactor", clock) |
929 | + self.patch(twisted.internet, "reactor", clock) |
930 | self.patch(ac, "is_already_running", lambda: defer.succeed(False)) |
931 | d = ac._wait_server_active() |
932 | clock.pump([tcpactivation.DELAY_BETWEEN_CHECKS] * |
933 | @@ -420,15 +404,28 @@ |
934 | @defer.inlineCallbacks |
935 | def test_get_description_fails_if_service_already_started(self): |
936 | """The get_description method fails if service already started.""" |
937 | - inner = WrapperFactory(None) |
938 | - |
939 | - self.patch(tcpactivation, 'PortDetectFactory', inner) |
940 | - client = FakeConnectedClient(self, inner) |
941 | + server = self.get_server() |
942 | + self.addCleanup(server.clean_up) |
943 | + |
944 | + class TestConnect(object): |
945 | + """A fake connection object.""" |
946 | + |
947 | + # pylint: disable=E0213 |
948 | + @defer.inlineCallbacks |
949 | + def connect(my_self, factory): |
950 | + """A fake connection.""" |
951 | + |
952 | + connected_factory = yield server.connect_client( |
953 | + PortDetectFactory) |
954 | + self.patch(factory, 'is_listening', |
955 | + connected_factory.is_listening) |
956 | + defer.returnValue(connected_factory) |
957 | + # pylint: enable=E0213 |
958 | |
959 | self.patch(tcpactivation, 'clientFromString', |
960 | - lambda *args: client) |
961 | + lambda *args: TestConnect()) |
962 | |
963 | - yield self.listen_server(FakeServerFactory) |
964 | + yield server.listen_server(protocol.ServerFactory) |
965 | |
966 | ai = ActivationInstance(self.config) |
967 | yield self.assertFailure(ai.get_server_description(), |
968 | @@ -438,6 +435,7 @@ |
969 | |
970 | def server_test(config): |
971 | """An IRL test of the server.""" |
972 | + from twisted.internet import reactor |
973 | |
974 | def got_description(description): |
975 | """The description was found.""" |
976 | @@ -472,6 +470,7 @@ |
977 | |
978 | def client_test(config): |
979 | """An IRL test of the client.""" |
980 | + from twisted.internet import reactor |
981 | print "starting the client." |
982 | ac = ActivationClient(config) |
983 | d = ac.get_active_client_description() |
984 | |
985 | === modified file 'ubuntu_sso/utils/txsecrets.py' |
986 | --- ubuntu_sso/utils/txsecrets.py 2012-04-09 17:38:24 +0000 |
987 | +++ ubuntu_sso/utils/txsecrets.py 2012-06-27 15:30:29 +0000 |
988 | @@ -100,7 +100,7 @@ |
989 | self.service.OpenSession(ALGORITHM, parameters, |
990 | reply_handler=session_opened, |
991 | error_handler=d.errback) |
992 | - except dbus.exceptions.DBusException, e: |
993 | + except dbus.exceptions.DBusException as e: |
994 | d.errback(e) |
995 | return d |
996 | |
997 | |
998 | === modified file 'ubuntu_sso/utils/webclient/common.py' |
999 | --- ubuntu_sso/utils/webclient/common.py 2012-04-12 12:07:46 +0000 |
1000 | +++ ubuntu_sso/utils/webclient/common.py 2012-06-27 15:30:29 +0000 |
1001 | @@ -206,7 +206,7 @@ |
1002 | try: |
1003 | creds = yield keyring.get_credentials(str(domain)) |
1004 | logger.debug('Got credentials from keyring.') |
1005 | - except Exception, e: |
1006 | + except Exception as e: |
1007 | logger.error('Error when retrieving the creds.') |
1008 | raise WebClientError('Error when retrieving the creds.', e) |
1009 | if creds is not None: |
1010 | @@ -249,7 +249,7 @@ |
1011 | |
1012 | try: |
1013 | return_code = yield self._launch_proxy_creds_dialog(domain, retry) |
1014 | - except Exception, e: |
1015 | + except Exception as e: |
1016 | logger.error('Error when running external ui process.') |
1017 | raise WebClientError('Error when running external ui process.', e) |
1018 | |
1019 | |
1020 | === modified file 'ubuntu_sso/utils/webclient/gsettings.py' |
1021 | --- ubuntu_sso/utils/webclient/gsettings.py 2012-04-09 17:38:24 +0000 |
1022 | +++ ubuntu_sso/utils/webclient/gsettings.py 2012-06-27 15:30:29 +0000 |
1023 | @@ -30,7 +30,11 @@ |
1024 | |
1025 | import subprocess |
1026 | |
1027 | +from ubuntu_sso.logger import setup_logging |
1028 | + |
1029 | +logger = setup_logging("ubuntu_sso.utils.webclient.gsettings") |
1030 | GSETTINGS_CMDLINE = "gsettings list-recursively org.gnome.system.proxy" |
1031 | +CANNOT_PARSE_WARNING = "Cannot parse gsettings value: %r" |
1032 | |
1033 | |
1034 | def parse_proxy_host(hostname): |
1035 | @@ -80,12 +84,15 @@ |
1036 | continue |
1037 | if value.startswith("'"): |
1038 | parsed_value = value[1:-1] |
1039 | - elif value.startswith('['): |
1040 | + elif value.startswith(('[', '@')): |
1041 | parsed_value = value |
1042 | elif value in ('true', 'false'): |
1043 | parsed_value = (value == 'true') |
1044 | + elif value.isdigit(): |
1045 | + parsed_value = int(value) |
1046 | else: |
1047 | - parsed_value = int(value) |
1048 | + logger.warning(CANNOT_PARSE_WARNING, value) |
1049 | + parsed_value = value |
1050 | relative_key = (path + "." + key)[base_len:] |
1051 | gsettings[relative_key] = parsed_value |
1052 | mode = gsettings["mode"] |
1053 | |
1054 | === modified file 'ubuntu_sso/utils/webclient/libsoup.py' |
1055 | --- ubuntu_sso/utils/webclient/libsoup.py 2012-04-12 12:07:46 +0000 |
1056 | +++ ubuntu_sso/utils/webclient/libsoup.py 2012-06-27 15:30:29 +0000 |
1057 | @@ -131,7 +131,7 @@ |
1058 | d = defer.Deferred() |
1059 | message = self.soup.Message.new(method, uri) |
1060 | |
1061 | - for key, value in headers.iteritems(): |
1062 | + for key, value in headers.items(): |
1063 | message.request_headers.append(key, value) |
1064 | |
1065 | if post_content: |
1066 | |
1067 | === modified file 'ubuntu_sso/utils/webclient/qtnetwork.py' |
1068 | --- ubuntu_sso/utils/webclient/qtnetwork.py 2012-04-24 14:05:22 +0000 |
1069 | +++ ubuntu_sso/utils/webclient/qtnetwork.py 2012-06-27 15:30:29 +0000 |
1070 | @@ -158,14 +158,14 @@ |
1071 | headers = yield self.build_request_headers(uri, method, extra_headers, |
1072 | oauth_credentials) |
1073 | |
1074 | - for key, value in headers.iteritems(): |
1075 | + for key, value in headers.items(): |
1076 | request.setRawHeader(key, value) |
1077 | |
1078 | post_buffer = QBuffer() |
1079 | post_buffer.setData(post_content) |
1080 | try: |
1081 | result = yield self._perform_request(request, method, post_buffer) |
1082 | - except ProxyUnauthorizedError, e: |
1083 | + except ProxyUnauthorizedError as e: |
1084 | app_proxy = QNetworkProxy.applicationProxy() |
1085 | proxy_host = app_proxy.hostName() if app_proxy else "proxy server" |
1086 | got_creds = yield self.request_proxy_auth_credentials( |
1087 | @@ -221,7 +221,7 @@ |
1088 | QSslCertificate.CountryName: 'country_name', |
1089 | QSslCertificate.StateOrProvinceName: 'state_name'} |
1090 | details = {} |
1091 | - for info, title in detail_titles.iteritems(): |
1092 | + for info, title in detail_titles.items(): |
1093 | details[title] = str(cert.issuerInfo(info)) |
1094 | return self.format_ssl_details(details) |
1095 | |
1096 | |
1097 | === modified file 'ubuntu_sso/utils/webclient/restful.py' |
1098 | --- ubuntu_sso/utils/webclient/restful.py 2012-04-09 17:38:24 +0000 |
1099 | +++ ubuntu_sso/utils/webclient/restful.py 2012-06-27 15:30:29 +0000 |
1100 | @@ -33,8 +33,11 @@ |
1101 | |
1102 | from twisted.internet import defer |
1103 | |
1104 | +from ubuntu_sso.logger import setup_logging |
1105 | from ubuntu_sso.utils import webclient |
1106 | |
1107 | +logger = setup_logging("ubuntu_sso.utils.webclient.restful") |
1108 | + |
1109 | POST_HEADERS = { |
1110 | "content-type": "application/x-www-form-urlencoded", |
1111 | } |
1112 | @@ -67,11 +70,19 @@ |
1113 | encoded_args = urllib.urlencode(params) |
1114 | iri = self.service_iri + namespace |
1115 | creds = self.oauth_credentials |
1116 | + logger.debug('Performing REST call to %r.', iri) |
1117 | result = yield self.webclient.request(iri, method="POST", |
1118 | oauth_credentials=creds, |
1119 | post_content=encoded_args, |
1120 | extra_headers=POST_HEADERS) |
1121 | - defer.returnValue(json.loads(result.content)) |
1122 | + try: |
1123 | + response = json.loads(result.content) |
1124 | + except: |
1125 | + logger.exception('Can not load json from REST request response ' |
1126 | + '(content is %r).', result.content) |
1127 | + raise |
1128 | + else: |
1129 | + defer.returnValue(response) |
1130 | |
1131 | def shutdown(self): |
1132 | """Stop the webclient used by this class.""" |
1133 | |
1134 | === modified file 'ubuntu_sso/utils/webclient/tests/test_gsettings.py' |
1135 | --- ubuntu_sso/utils/webclient/tests/test_gsettings.py 2012-04-09 17:38:24 +0000 |
1136 | +++ ubuntu_sso/utils/webclient/tests/test_gsettings.py 2012-06-27 15:30:29 +0000 |
1137 | @@ -28,7 +28,10 @@ |
1138 | # files in the program, then also delete it here. |
1139 | """Test the gsettings parser.""" |
1140 | |
1141 | +import logging |
1142 | + |
1143 | from twisted.trial.unittest import TestCase |
1144 | +from ubuntuone.devtools.handlers import MementoHandler |
1145 | |
1146 | from ubuntu_sso.utils.webclient import gsettings |
1147 | from ubuntu_sso.utils.webclient.tests import ( |
1148 | @@ -91,6 +94,35 @@ |
1149 | """Test a parser of gsettings.""" |
1150 | self._assert_parser_anonymous('https') |
1151 | |
1152 | + def test_gsettings_empty_ignore_hosts(self): |
1153 | + """Missing values in the ignore hosts.""" |
1154 | + troublesome_value = "@as []" |
1155 | + template_values = dict(BASE_GSETTINGS_VALUES) |
1156 | + template_values["ignore_hosts"] = troublesome_value |
1157 | + fake_output = TEMPLATE_GSETTINGS_OUTPUT.format(**template_values) |
1158 | + self.patch(gsettings.subprocess, "check_output", |
1159 | + lambda _: fake_output) |
1160 | + ps = gsettings.get_proxy_settings() |
1161 | + self.assertEqual(ps, {}) |
1162 | + |
1163 | + def test_gsettings_cannot_parse(self): |
1164 | + """Some weird setting that cannot be parsed is logged with warning.""" |
1165 | + memento = MementoHandler() |
1166 | + memento.setLevel(logging.DEBUG) |
1167 | + gsettings.logger.addHandler(memento) |
1168 | + self.addCleanup(gsettings.logger.removeHandler, memento) |
1169 | + |
1170 | + troublesome_value = "#bang" |
1171 | + template_values = dict(BASE_GSETTINGS_VALUES) |
1172 | + template_values["ignore_hosts"] = troublesome_value |
1173 | + fake_output = TEMPLATE_GSETTINGS_OUTPUT.format(**template_values) |
1174 | + self.patch(gsettings.subprocess, "check_output", |
1175 | + lambda _: fake_output) |
1176 | + ps = gsettings.get_proxy_settings() |
1177 | + self.assertTrue(memento.check_warning(gsettings.CANNOT_PARSE_WARNING % |
1178 | + troublesome_value)) |
1179 | + self.assertEqual(ps, {}) |
1180 | + |
1181 | def test_gsettings_parser_http_authenticated(self): |
1182 | """Test a parser of gsettings.""" |
1183 | template_values = dict(BASE_GSETTINGS_VALUES) |
1184 | |
1185 | === modified file 'ubuntu_sso/utils/webclient/tests/test_restful.py' |
1186 | --- ubuntu_sso/utils/webclient/tests/test_restful.py 2012-04-09 17:38:24 +0000 |
1187 | +++ ubuntu_sso/utils/webclient/tests/test_restful.py 2012-06-27 15:30:29 +0000 |
1188 | @@ -28,9 +28,11 @@ |
1189 | # files in the program, then also delete it here. |
1190 | """Tests for the proxy-enabled restful client.""" |
1191 | |
1192 | +import logging |
1193 | import urlparse |
1194 | |
1195 | from twisted.internet import defer |
1196 | +from ubuntuone.devtools.handlers import MementoHandler |
1197 | from ubuntuone.devtools.testcases import TestCase |
1198 | |
1199 | from ubuntu_sso.utils.webclient import restful |
1200 | @@ -184,3 +186,45 @@ |
1201 | yield rc.restcall(SAMPLE_OPERATION, **SAMPLE_ARGS) |
1202 | _, _, kwargs = self.wc.called[0] |
1203 | self.assertEqual(kwargs["oauth_credentials"], SAMPLE_OAUTH_CREDS) |
1204 | + |
1205 | + |
1206 | +class LogginTestCase(BaseTestCase): |
1207 | + """Ensure that proper debug logging is done.""" |
1208 | + |
1209 | + @defer.inlineCallbacks |
1210 | + def setUp(self): |
1211 | + """Initialize this testcase.""" |
1212 | + yield super(LogginTestCase, self).setUp() |
1213 | + self.memento = MementoHandler() |
1214 | + restful.logger.addHandler(self.memento) |
1215 | + restful.logger.setLevel(logging.DEBUG) |
1216 | + self.addCleanup(restful.logger.removeHandler, self.memento) |
1217 | + |
1218 | + self.rc = restful.RestfulClient(SAMPLE_SERVICE_IRI) |
1219 | + self.addCleanup(self.rc.shutdown) |
1220 | + |
1221 | + @defer.inlineCallbacks |
1222 | + def test_log_rest_call(self): |
1223 | + """Check that proper DEBUG is made for every REST call.""" |
1224 | + yield self.rc.restcall(SAMPLE_OPERATION, **SAMPLE_ARGS) |
1225 | + |
1226 | + expected_msgs = ( |
1227 | + SAMPLE_SERVICE_IRI + SAMPLE_NAMESPACE, |
1228 | + ) |
1229 | + self.assertTrue(self.memento.check_debug(*expected_msgs)) |
1230 | + |
1231 | + @defer.inlineCallbacks |
1232 | + def test_log_json_loads_exception(self): |
1233 | + """Check that json load errors are properly logged.""" |
1234 | + invalid_json = 'NOTAVALIDJSON' |
1235 | + self.patch(self.wc, 'return_value', invalid_json) |
1236 | + yield self.assertFailure(self.rc.restcall(SAMPLE_OPERATION), |
1237 | + ValueError) |
1238 | + |
1239 | + self.memento.debug = True |
1240 | + expected_msgs = ( |
1241 | + ValueError, |
1242 | + 'Can not load json from REST request response', |
1243 | + invalid_json |
1244 | + ) |
1245 | + self.assertTrue(self.memento.check_exception(*expected_msgs)) |
1246 | |
1247 | === modified file 'ubuntu_sso/utils/webclient/tests/test_webclient.py' |
1248 | --- ubuntu_sso/utils/webclient/tests/test_webclient.py 2012-04-24 14:05:22 +0000 |
1249 | +++ ubuntu_sso/utils/webclient/tests/test_webclient.py 2012-06-27 15:30:29 +0000 |
1250 | @@ -753,7 +753,7 @@ |
1251 | |
1252 | self.assertEqual(method, "OAuth") |
1253 | |
1254 | - for k, expected_value in self.expected_params.iteritems(): |
1255 | + for k, expected_value in self.expected_params.items(): |
1256 | self.assertIn(k, params) |
1257 | if expected_value is not ANY_VALUE: |
1258 | self.assertEqual(params[k], expected_value) |
1259 | @@ -782,7 +782,7 @@ |
1260 | self.assert_headers_correct(request.to_header()) |
1261 | self.assertEqual(request.http_url, self.sample_url) |
1262 | if params is not None: |
1263 | - for param, value in params.iteritems(): |
1264 | + for param, value in params.items(): |
1265 | self.assertIn(param, request.parameters) |
1266 | actual = request.parameters[param] |
1267 | self.assertEqual(value, actual) |
1268 | |
1269 | === modified file 'ubuntu_sso/utils/webclient/timestamp.py' |
1270 | --- ubuntu_sso/utils/webclient/timestamp.py 2012-04-09 17:38:24 +0000 |
1271 | +++ ubuntu_sso/utils/webclient/timestamp.py 2012-06-27 15:30:29 +0000 |
1272 | @@ -83,7 +83,7 @@ |
1273 | logger.debug("Calculated server time skew: %r", self.skew) |
1274 | # We just log all exceptions while trying to get the server time |
1275 | # pylint: disable=W0703 |
1276 | - except Exception, e: |
1277 | + except Exception as e: |
1278 | logger.debug("Error while verifying server time skew: %r", e) |
1279 | self.next_check = local_time + self.ERROR_INTERVAL |
1280 | # delay import, otherwise a default reactor gets installed |
1281 | |
1282 | === removed directory 'ubuntu_sso/xdg_base_directory' |
1283 | === removed file 'ubuntu_sso/xdg_base_directory/__init__.py' |
1284 | --- ubuntu_sso/xdg_base_directory/__init__.py 2012-04-09 17:38:24 +0000 |
1285 | +++ ubuntu_sso/xdg_base_directory/__init__.py 1970-01-01 00:00:00 +0000 |
1286 | @@ -1,104 +0,0 @@ |
1287 | -# -*- coding: utf-8 -*- |
1288 | -# |
1289 | -# Copyright 2011-2012 Canonical Ltd. |
1290 | -# |
1291 | -# This program is free software: you can redistribute it and/or modify it |
1292 | -# under the terms of the GNU General Public License version 3, as published |
1293 | -# by the Free Software Foundation. |
1294 | -# |
1295 | -# This program is distributed in the hope that it will be useful, but |
1296 | -# WITHOUT ANY WARRANTY; without even the implied warranties of |
1297 | -# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1298 | -# PURPOSE. See the GNU General Public License for more details. |
1299 | -# |
1300 | -# You should have received a copy of the GNU General Public License along |
1301 | -# with this program. If not, see <http://www.gnu.org/licenses/>. |
1302 | -# |
1303 | -# In addition, as a special exception, the copyright holders give |
1304 | -# permission to link the code of portions of this program with the |
1305 | -# OpenSSL library under certain conditions as described in each |
1306 | -# individual source file, and distribute linked combinations |
1307 | -# including the two. |
1308 | -# You must obey the GNU General Public License in all respects |
1309 | -# for all of the code used other than OpenSSL. If you modify |
1310 | -# file(s) with this exception, you may extend this exception to your |
1311 | -# version of the file(s), but you are not obligated to do so. If you |
1312 | -# do not wish to do so, delete this exception statement from your |
1313 | -# version. If you delete this exception statement from all source |
1314 | -# files in the program, then also delete it here. |
1315 | -"""XDG multiplatform.""" |
1316 | - |
1317 | -import os |
1318 | -import sys |
1319 | -import warnings |
1320 | - |
1321 | - |
1322 | -def unicode_path(utf8path): |
1323 | - """Turn an utf8 path into a unicode path.""" |
1324 | - return utf8path.decode("utf-8") |
1325 | - |
1326 | - |
1327 | -def native_path(utf8path): |
1328 | - """Turn an utf8 path into a path useable in the current encoding.""" |
1329 | - warnings.warn('native_path will be removed soon', DeprecationWarning) |
1330 | - return unicode_path(utf8path) |
1331 | - |
1332 | - |
1333 | -def syncdaemon_path(mbcspath): |
1334 | - """Turn a mbcs path in a utf-8 path as CURRENTLY used inside syncdaemon.""" |
1335 | - warnings.warn('syncdaemon_path will be removed soon', DeprecationWarning) |
1336 | - return mbcspath.decode(sys.getfilesystemencoding()).encode("utf-8") |
1337 | - |
1338 | - |
1339 | -# pylint: disable=C0103,F0401,E0611,E1101 |
1340 | -if sys.platform == "win32": |
1341 | - from ubuntu_sso.xdg_base_directory import windows |
1342 | - source = windows |
1343 | - xdg_home = source.home_path |
1344 | -else: |
1345 | - import xdg.BaseDirectory |
1346 | - source = xdg.BaseDirectory |
1347 | - xdg_home = os.path.expanduser('~') |
1348 | - |
1349 | -xdg_cache_home = source.xdg_cache_home |
1350 | - |
1351 | -xdg_config_home = source.xdg_config_home |
1352 | -xdg_config_dirs = source.xdg_config_dirs |
1353 | - |
1354 | -xdg_data_home = source.xdg_data_home |
1355 | -xdg_data_dirs = source.xdg_data_dirs |
1356 | - |
1357 | - |
1358 | -def load_config_paths(*resource): |
1359 | - """Iterator of configuration paths. |
1360 | - |
1361 | - Return an iterator which gives each directory named 'resource' in |
1362 | - the configuration search path. Information provided by earlier |
1363 | - directories should take precedence over later ones (ie, the user's |
1364 | - config dir comes first). |
1365 | - """ |
1366 | - resource = os.path.join(*resource) |
1367 | - for config_dir in xdg_config_dirs: |
1368 | - path = os.path.join(config_dir, resource) |
1369 | - # access the file system always with unicode |
1370 | - # to properly behave in some operating systems |
1371 | - if os.path.exists(unicode_path(path)): |
1372 | - yield path |
1373 | - |
1374 | - |
1375 | -def save_config_path(*resource): |
1376 | - """Path to save configuration. |
1377 | - |
1378 | - Ensure $XDG_CONFIG_HOME/<resource>/ exists, and return its path. |
1379 | - 'resource' should normally be the name of your application. Use this |
1380 | - when SAVING configuration settings. Use the xdg_config_dirs variable |
1381 | - for loading. |
1382 | - """ |
1383 | - resource = os.path.join(*resource) |
1384 | - assert not resource.startswith('/') |
1385 | - path = os.path.join(xdg_config_home, resource) |
1386 | - # access the file system always with unicode |
1387 | - # to properly behave in some operating systems |
1388 | - if not os.path.isdir(unicode_path(path)): |
1389 | - os.makedirs(unicode_path(path), 0700) |
1390 | - return path |
1391 | |
1392 | === removed directory 'ubuntu_sso/xdg_base_directory/tests' |
1393 | === removed file 'ubuntu_sso/xdg_base_directory/tests/__init__.py' |
1394 | --- ubuntu_sso/xdg_base_directory/tests/__init__.py 2012-04-09 17:38:24 +0000 |
1395 | +++ ubuntu_sso/xdg_base_directory/tests/__init__.py 1970-01-01 00:00:00 +0000 |
1396 | @@ -1,29 +0,0 @@ |
1397 | -# ubuntu_sso - Ubuntu Single Sign On client support for desktop apps |
1398 | -# |
1399 | -# Copyright 2009-2012 Canonical Ltd. |
1400 | -# |
1401 | -# This program is free software: you can redistribute it and/or modify it |
1402 | -# under the terms of the GNU General Public License version 3, as published |
1403 | -# by the Free Software Foundation. |
1404 | -# |
1405 | -# This program is distributed in the hope that it will be useful, but |
1406 | -# WITHOUT ANY WARRANTY; without even the implied warranties of |
1407 | -# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1408 | -# PURPOSE. See the GNU General Public License for more details. |
1409 | -# |
1410 | -# You should have received a copy of the GNU General Public License along |
1411 | -# with this program. If not, see <http://www.gnu.org/licenses/>. |
1412 | -# |
1413 | -# In addition, as a special exception, the copyright holders give |
1414 | -# permission to link the code of portions of this program with the |
1415 | -# OpenSSL library under certain conditions as described in each |
1416 | -# individual source file, and distribute linked combinations |
1417 | -# including the two. |
1418 | -# You must obey the GNU General Public License in all respects |
1419 | -# for all of the code used other than OpenSSL. If you modify |
1420 | -# file(s) with this exception, you may extend this exception to your |
1421 | -# version of the file(s), but you are not obligated to do so. If you |
1422 | -# do not wish to do so, delete this exception statement from your |
1423 | -# version. If you delete this exception statement from all source |
1424 | -# files in the program, then also delete it here. |
1425 | -"""XDG tests.""" |
1426 | |
1427 | === removed file 'ubuntu_sso/xdg_base_directory/tests/test_common.py' |
1428 | --- ubuntu_sso/xdg_base_directory/tests/test_common.py 2012-04-09 17:38:24 +0000 |
1429 | +++ ubuntu_sso/xdg_base_directory/tests/test_common.py 1970-01-01 00:00:00 +0000 |
1430 | @@ -1,91 +0,0 @@ |
1431 | -# -*- coding: utf-8 -*- |
1432 | -# |
1433 | -# Authors: Natalia B. Bidart <natalia.bidart@canonical.com> |
1434 | -# |
1435 | -# Copyright 2011-2012 Canonical Ltd. |
1436 | -# |
1437 | -# This program is free software: you can redistribute it and/or modify it |
1438 | -# under the terms of the GNU General Public License version 3, as published |
1439 | -# by the Free Software Foundation. |
1440 | -# |
1441 | -# This program is distributed in the hope that it will be useful, but |
1442 | -# WITHOUT ANY WARRANTY; without even the implied warranties of |
1443 | -# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1444 | -# PURPOSE. See the GNU General Public License for more details. |
1445 | -# |
1446 | -# You should have received a copy of the GNU General Public License along |
1447 | -# with this program. If not, see <http://www.gnu.org/licenses/>. |
1448 | -# |
1449 | -# In addition, as a special exception, the copyright holders give |
1450 | -# permission to link the code of portions of this program with the |
1451 | -# OpenSSL library under certain conditions as described in each |
1452 | -# individual source file, and distribute linked combinations |
1453 | -# including the two. |
1454 | -# You must obey the GNU General Public License in all respects |
1455 | -# for all of the code used other than OpenSSL. If you modify |
1456 | -# file(s) with this exception, you may extend this exception to your |
1457 | -# version of the file(s), but you are not obligated to do so. If you |
1458 | -# do not wish to do so, delete this exception statement from your |
1459 | -# version. If you delete this exception statement from all source |
1460 | -# files in the program, then also delete it here. |
1461 | -"""Platform independent tests for the XDG constants.""" |
1462 | - |
1463 | -import os |
1464 | - |
1465 | -from twisted.trial.unittest import TestCase |
1466 | - |
1467 | -from ubuntu_sso import xdg_base_directory |
1468 | - |
1469 | - |
1470 | -class TestBaseDirectory(TestCase): |
1471 | - """Tests for the BaseDirectory module.""" |
1472 | - |
1473 | - def assert_utf8_bytes(self, value): |
1474 | - """Check that 'value' is a bytes sequence encoded with utf-8.""" |
1475 | - self.assertIsInstance(value, str) |
1476 | - try: |
1477 | - value.decode('utf-8') |
1478 | - except UnicodeDecodeError: |
1479 | - self.fail('%r should be a utf8 encoded string.' % value) |
1480 | - |
1481 | - def test_xdg_home_is_utf8_bytes(self): |
1482 | - """The returned path is bytes.""" |
1483 | - actual = xdg_base_directory.xdg_home |
1484 | - self.assert_utf8_bytes(actual) |
1485 | - |
1486 | - def test_xdg_cache_home_is_utf8_bytes(self): |
1487 | - """The returned path is bytes.""" |
1488 | - actual = xdg_base_directory.xdg_cache_home |
1489 | - self.assert_utf8_bytes(actual) |
1490 | - |
1491 | - def test_xdg_config_home_is_utf8_bytes(self): |
1492 | - """The returned path is bytes.""" |
1493 | - actual = xdg_base_directory.xdg_config_home |
1494 | - self.assert_utf8_bytes(actual) |
1495 | - |
1496 | - def test_xdg_config_dirs_are_bytes(self): |
1497 | - """The returned path is bytes.""" |
1498 | - result = xdg_base_directory.xdg_config_dirs |
1499 | - for actual in result: |
1500 | - self.assert_utf8_bytes(actual) |
1501 | - |
1502 | - def test_xdg_data_home_is_utf8_bytes(self): |
1503 | - """The returned path is bytes.""" |
1504 | - actual = xdg_base_directory.xdg_data_home |
1505 | - self.assert_utf8_bytes(actual) |
1506 | - |
1507 | - def test_xdg_data_dirs_are_bytes(self): |
1508 | - """The returned path is bytes.""" |
1509 | - result = xdg_base_directory.xdg_data_dirs |
1510 | - for actual in result: |
1511 | - self.assert_utf8_bytes(actual) |
1512 | - |
1513 | - def test_load_config_paths_filter(self): |
1514 | - """Since those folders don't exist, this should be empty.""" |
1515 | - self.assertEqual(list(xdg_base_directory.load_config_paths("x")), []) |
1516 | - |
1517 | - def test_save_config_path(self): |
1518 | - """The path should end with xdg_config/x (respecting the separator).""" |
1519 | - self.patch(os, "makedirs", lambda *args: None) |
1520 | - result = xdg_base_directory.save_config_path("x") |
1521 | - self.assertEqual(result.split(os.sep)[-2:], ['xdg_config', 'x']) |
1522 | |
1523 | === removed file 'ubuntu_sso/xdg_base_directory/tests/test_windows.py' |
1524 | --- ubuntu_sso/xdg_base_directory/tests/test_windows.py 2012-04-09 17:38:24 +0000 |
1525 | +++ ubuntu_sso/xdg_base_directory/tests/test_windows.py 1970-01-01 00:00:00 +0000 |
1526 | @@ -1,157 +0,0 @@ |
1527 | -# -*- coding: utf-8 -*- |
1528 | -# |
1529 | -# Copyright 2011-2012 Canonical Ltd. |
1530 | -# |
1531 | -# This program is free software: you can redistribute it and/or modify it |
1532 | -# under the terms of the GNU General Public License version 3, as published |
1533 | -# by the Free Software Foundation. |
1534 | -# |
1535 | -# This program is distributed in the hope that it will be useful, but |
1536 | -# WITHOUT ANY WARRANTY; without even the implied warranties of |
1537 | -# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1538 | -# PURPOSE. See the GNU General Public License for more details. |
1539 | -# |
1540 | -# You should have received a copy of the GNU General Public License along |
1541 | -# with this program. If not, see <http://www.gnu.org/licenses/>. |
1542 | -# |
1543 | -# In addition, as a special exception, the copyright holders give |
1544 | -# permission to link the code of portions of this program with the |
1545 | -# OpenSSL library under certain conditions as described in each |
1546 | -# individual source file, and distribute linked combinations |
1547 | -# including the two. |
1548 | -# You must obey the GNU General Public License in all respects |
1549 | -# for all of the code used other than OpenSSL. If you modify |
1550 | -# file(s) with this exception, you may extend this exception to your |
1551 | -# version of the file(s), but you are not obligated to do so. If you |
1552 | -# do not wish to do so, delete this exception statement from your |
1553 | -# version. If you delete this exception statement from all source |
1554 | -# files in the program, then also delete it here. |
1555 | -"""Windows-specific tests for the XDG constants.""" |
1556 | - |
1557 | -import os |
1558 | -import sys |
1559 | - |
1560 | -from twisted.trial.unittest import TestCase |
1561 | - |
1562 | - |
1563 | -# pylint: disable=E1101, E0611, F0401 |
1564 | -import win32com.shell |
1565 | -from ubuntu_sso.xdg_base_directory.windows import ( |
1566 | - get_config_dirs, |
1567 | - get_data_dirs, |
1568 | - get_env_path, |
1569 | - get_special_folders, |
1570 | -) |
1571 | - |
1572 | - |
1573 | -class FakeShellConModule(object): |
1574 | - """Override CSIDL_ constants.""" |
1575 | - |
1576 | - CSIDL_PROFILE = 0 |
1577 | - CSIDL_LOCAL_APPDATA = 1 |
1578 | - CSIDL_COMMON_APPDATA = 2 |
1579 | - |
1580 | - |
1581 | -class FakeShellModule(object): |
1582 | - |
1583 | - """Fake Shell Module.""" |
1584 | - |
1585 | - def __init__(self): |
1586 | - """Set the proper mapping between CSIDL_ consts.""" |
1587 | - self.values = { |
1588 | - 0: u'c:\\path\\to\\users\\home', |
1589 | - 1: u'c:\\path\\to\\users\\home\\appData\\local', |
1590 | - 2: u'c:\\programData', |
1591 | - } |
1592 | - |
1593 | - # pylint: disable=C0103 |
1594 | - def SHGetFolderPath(self, dummy0, shellconValue, dummy2, dummy3): |
1595 | - """Override SHGetFolderPath functionality.""" |
1596 | - return self.values[shellconValue] |
1597 | - # pylint: enable=C0103 |
1598 | - |
1599 | - |
1600 | -class TestBaseDirectoryWindows(TestCase): |
1601 | - """Tests for the BaseDirectory module.""" |
1602 | - |
1603 | - def test_get_special_folders(self): |
1604 | - """Make sure we can import the platform module.""" |
1605 | - |
1606 | - shell_module = FakeShellModule() |
1607 | - self.patch(win32com.shell, "shell", shell_module) |
1608 | - self.patch(win32com.shell, "shellcon", FakeShellConModule()) |
1609 | - special_folders = get_special_folders() |
1610 | - self.assertTrue('Personal' in special_folders) |
1611 | - self.assertTrue('Local AppData' in special_folders) |
1612 | - self.assertTrue('AppData' in special_folders) |
1613 | - self.assertTrue('Common AppData' in special_folders) |
1614 | - |
1615 | - self.assertTrue(special_folders['Personal'] == \ |
1616 | - shell_module.values[FakeShellConModule.CSIDL_PROFILE]) |
1617 | - self.assertTrue(special_folders['Local AppData'] == \ |
1618 | - shell_module.values[FakeShellConModule.CSIDL_LOCAL_APPDATA]) |
1619 | - self.assertTrue(special_folders['Local AppData'].startswith( |
1620 | - special_folders['AppData'])) |
1621 | - self.assertTrue(special_folders['Common AppData'] == \ |
1622 | - shell_module.values[FakeShellConModule.CSIDL_COMMON_APPDATA]) |
1623 | - |
1624 | - for val in special_folders.itervalues(): |
1625 | - self.assertIsInstance(val, str) |
1626 | - val.decode('utf8') |
1627 | - # Should not raise exceptions |
1628 | - |
1629 | - def test_get_data_dirs(self): |
1630 | - """Check thet get_data_dirs uses pathsep correctly.""" |
1631 | - bad_sep = filter(lambda x: x not in os.pathsep, ":;") |
1632 | - dir_list = ["A", "B", bad_sep, "C"] |
1633 | - self.patch(os, "environ", |
1634 | - dict(XDG_DATA_DIRS=os.pathsep.join( |
1635 | - dir_list))) |
1636 | - dirs = get_data_dirs() |
1637 | - self.assertEqual(dirs, dir_list) |
1638 | - |
1639 | - def test_get_config_dirs(self): |
1640 | - """Check thet get_data_dirs uses pathsep correctly.""" |
1641 | - bad_sep = filter(lambda x: x not in os.pathsep, ":;") |
1642 | - dir_list = ["A", "B", bad_sep, "C"] |
1643 | - self.patch(os, "environ", |
1644 | - dict(XDG_CONFIG_DIRS=os.pathsep.join( |
1645 | - dir_list))) |
1646 | - dirs = get_config_dirs()[1:] |
1647 | - self.assertEqual(dirs, dir_list) |
1648 | - |
1649 | - def set_fake_environ(self, key, value): |
1650 | - """Set (and restore) a fake environ variable.""" |
1651 | - if key in os.environ: |
1652 | - prev = os.environ[key] |
1653 | - self.addCleanup(os.environ.__setitem__, key, prev) |
1654 | - else: |
1655 | - self.addCleanup(os.environ.__delitem__, key) |
1656 | - os.environ[key] = value |
1657 | - |
1658 | - def unset_fake_environ(self, key): |
1659 | - """Unset (and restore) a fake environ variable.""" |
1660 | - if key in os.environ: |
1661 | - current_value = os.environ[key] |
1662 | - self.addCleanup(os.environ.__setitem__, key, current_value) |
1663 | - del(os.environ[key]) |
1664 | - |
1665 | - def test_get_env_path_var(self): |
1666 | - """Test that get_env_path transforms an env var.""" |
1667 | - fake_path = u"C:\\Users\\Ñandú" |
1668 | - fake_env_var = "FAKE_ENV_VAR" |
1669 | - |
1670 | - mbcs_path = fake_path.encode(sys.getfilesystemencoding()) |
1671 | - utf8_path = fake_path.encode("utf-8") |
1672 | - |
1673 | - self.set_fake_environ(fake_env_var, mbcs_path) |
1674 | - self.assertEqual(get_env_path(fake_env_var, "unexpected"), utf8_path) |
1675 | - |
1676 | - def test_get_env_path_no_var(self): |
1677 | - """Test that get_env_path returns the default when env var not set.""" |
1678 | - fake_path = u"C:\\Users\\Ñandú" |
1679 | - fake_env_var = "fake_env_var" |
1680 | - default = fake_path.encode(sys.getfilesystemencoding()) |
1681 | - |
1682 | - self.unset_fake_environ(fake_env_var) |
1683 | - self.assertEqual(get_env_path(fake_env_var, default), default) |
1684 | |
1685 | === removed file 'ubuntu_sso/xdg_base_directory/windows.py' |
1686 | --- ubuntu_sso/xdg_base_directory/windows.py 2012-04-09 17:38:24 +0000 |
1687 | +++ ubuntu_sso/xdg_base_directory/windows.py 1970-01-01 00:00:00 +0000 |
1688 | @@ -1,113 +0,0 @@ |
1689 | -# -*- coding: utf-8 -*- |
1690 | -# |
1691 | -# Copyright 2011-2012 Canonical Ltd. |
1692 | -# |
1693 | -# This program is free software: you can redistribute it and/or modify it |
1694 | -# under the terms of the GNU General Public License version 3, as published |
1695 | -# by the Free Software Foundation. |
1696 | -# |
1697 | -# This program is distributed in the hope that it will be useful, but |
1698 | -# WITHOUT ANY WARRANTY; without even the implied warranties of |
1699 | -# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1700 | -# PURPOSE. See the GNU General Public License for more details. |
1701 | -# |
1702 | -# You should have received a copy of the GNU General Public License along |
1703 | -# with this program. If not, see <http://www.gnu.org/licenses/>. |
1704 | -# |
1705 | -# In addition, as a special exception, the copyright holders give |
1706 | -# permission to link the code of portions of this program with the |
1707 | -# OpenSSL library under certain conditions as described in each |
1708 | -# individual source file, and distribute linked combinations |
1709 | -# including the two. |
1710 | -# You must obey the GNU General Public License in all respects |
1711 | -# for all of the code used other than OpenSSL. If you modify |
1712 | -# file(s) with this exception, you may extend this exception to your |
1713 | -# version of the file(s), but you are not obligated to do so. If you |
1714 | -# do not wish to do so, delete this exception statement from your |
1715 | -# version. If you delete this exception statement from all source |
1716 | -# files in the program, then also delete it here. |
1717 | -"""XDG helpers for windows.""" |
1718 | - |
1719 | -import os |
1720 | -import sys |
1721 | - |
1722 | - |
1723 | -# pylint: disable=C0103 |
1724 | -def get_special_folders(): |
1725 | - """ Routine to grab all the Windows Special Folders locations. |
1726 | - |
1727 | - If successful, returns dictionary |
1728 | - of shell folder locations indexed on Windows keyword for each; |
1729 | - otherwise, returns an empty dictionary. |
1730 | - """ |
1731 | - # pylint: disable=W0621, F0401, E0611 |
1732 | - special_folders = {} |
1733 | - |
1734 | - from win32com.shell import shell, shellcon |
1735 | - # CSIDL_LOCAL_APPDATA = C:\Users\<username>\AppData\Local |
1736 | - # CSIDL_PROFILE = C:\Users\<username> |
1737 | - # CSIDL_COMMON_APPDATA = C:\ProgramData |
1738 | - # More information on these constants at |
1739 | - # http://msdn.microsoft.com/en-us/library/bb762494 |
1740 | - |
1741 | - # as per http://msdn.microsoft.com/en-us/library/windows/desktop/bb762181, |
1742 | - # SHGetFolderPath is deprecated, we should migrate to SHGetKnownFolderPath |
1743 | - # (http://msdn.microsoft.com/en-us/library/windows/desktop/bb762188) |
1744 | - get_path = lambda name: shell.SHGetFolderPath( |
1745 | - 0, getattr(shellcon, name), None, 0).encode('utf8') |
1746 | - special_folders['Personal'] = get_path("CSIDL_PROFILE") |
1747 | - special_folders['Local AppData'] = get_path("CSIDL_LOCAL_APPDATA") |
1748 | - special_folders['AppData'] = os.path.dirname( |
1749 | - special_folders['Local AppData']) |
1750 | - special_folders['Common AppData'] = get_path("CSIDL_COMMON_APPDATA") |
1751 | - return special_folders |
1752 | - |
1753 | - |
1754 | -def get_env_path(key, default): |
1755 | - """Get a utf8 path from an environment variable.""" |
1756 | - if key in os.environ: |
1757 | - # on windows, environment variables are mbcs bytes |
1758 | - # so we must turn them into utf-8 Syncdaemon paths |
1759 | - path = os.environ.get(key) |
1760 | - return path.decode(sys.getfilesystemencoding()).encode("utf-8") |
1761 | - else: |
1762 | - return default |
1763 | - |
1764 | - |
1765 | -special_folders = get_special_folders() |
1766 | - |
1767 | -home_path = special_folders['Personal'] |
1768 | -app_local_data_path = special_folders['Local AppData'] |
1769 | -app_global_data_path = special_folders['Common AppData'] |
1770 | - |
1771 | -xdg_data_home = get_env_path('XDG_DATA_HOME', |
1772 | - os.path.join(app_local_data_path, 'xdg')) |
1773 | - |
1774 | -xdg_cache_home = get_env_path('XDG_CACHE_HOME', |
1775 | - os.path.join(xdg_data_home, 'cache')) |
1776 | - |
1777 | -xdg_config_home = get_env_path('XDG_CONFIG_HOME', |
1778 | - app_local_data_path) |
1779 | - |
1780 | - |
1781 | -def get_data_dirs(): |
1782 | - """Returns XDG data directories.""" |
1783 | - return get_env_path('XDG_DATA_DIRS', |
1784 | - '{0}{1}{2}'.format(app_local_data_path, os.pathsep, |
1785 | - app_global_data_path)).split(os.pathsep) |
1786 | - |
1787 | - |
1788 | -xdg_data_dirs = get_data_dirs() |
1789 | - |
1790 | - |
1791 | -def get_config_dirs(): |
1792 | - """Return XDG config directories.""" |
1793 | - return [xdg_config_home] + \ |
1794 | - get_env_path('XDG_CONFIG_DIRS', |
1795 | - app_global_data_path, |
1796 | - ).split(os.pathsep) |
1797 | - |
1798 | -xdg_config_dirs = get_config_dirs() |
1799 | - |
1800 | -xdg_data_dirs = filter(lambda x: x, xdg_data_dirs) |
1801 | -xdg_config_dirs = filter(lambda x: x, xdg_config_dirs) |
+1 looks good