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 on 2012-06-27 |
| 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 on 2012-06-27 | ||
| Roberto Alsina (community) | 2012-06-27 | Approve on 2012-06-27 | |
|
Review via email:
|
|||
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.
- 960. By Brian Curtin on 2012-06-27
-
[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