Merge lp:~nataliabidart/ubuntu-sso-client/stable-3-0-update-2.99.91.1 into lp:ubuntu-sso-client/stable-3-0

Proposed by Natalia Bidart on 2012-03-27
Status: Merged
Approved by: dobey on 2012-03-27
Approved revision: 833
Merged at revision: 832
Proposed branch: lp:~nataliabidart/ubuntu-sso-client/stable-3-0-update-2.99.91.1
Merge into: lp:ubuntu-sso-client/stable-3-0
Diff against target: 603 lines (+352/-39)
14 files modified
bin/ubuntu-sso-login-qt (+3/-4)
data/qt/stylesheet.qss (+1/-0)
run-tests (+1/-1)
setup.py (+1/-0)
ubuntu_sso/main/tests/test_common.py (+12/-0)
ubuntu_sso/qt/main/__init__.py (+16/-5)
ubuntu_sso/qt/main/linux.py (+35/-0)
ubuntu_sso/qt/main/tests/__init__.py (+17/-0)
ubuntu_sso/qt/main/tests/test_main.py (+42/-10)
ubuntu_sso/qt/main/windows.py (+46/-0)
ubuntu_sso/qt/proxy_dialog.py (+31/-2)
ubuntu_sso/qt/tests/test_proxy_dialog.py (+137/-16)
ubuntu_sso/utils/webclient/qtnetwork.py (+2/-1)
ubuntu_sso/utils/webclient/tests/test_webclient.py (+8/-0)
To merge this branch: bzr merge lp:~nataliabidart/ubuntu-sso-client/stable-3-0-update-2.99.91.1
Reviewer Review Type Date Requested Status
Manuel de la Peña (community) Approve on 2012-03-27
Roberto Alsina (community) 2012-03-27 Approve on 2012-03-27
Review via email: mp+99544@code.launchpad.net

Commit Message

[ Diego Sarmentero <email address hidden> ]
  - Converting to unicode some data returned by webclient in
    QByteArray format (LP: #961315).
  - Adding ubuntu_sso.qt.main module to the setup script (LP: #965377).
  - Fixed the backend getting stuck installing the qtreactor before
    the qt process is executed and running the application in the
    twisted process (This fix affects only Windows OS) (LP: #961511).

[ Roberto Alsina <email address hidden> ]
   - Forced white background (LP: #961346).

[ Manuel de la Pena <email address hidden> ]
  - Fixed dialog on window by using show so that the QEventLoop does
    not block the execution of the main loop of the reactor which did
    not allow the deferreds to be fired (LP: #960481).

To post a comment you must log in.
Roberto Alsina (ralsina) wrote :

+1

review: Approve
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bin/ubuntu-sso-login-qt'
2--- bin/ubuntu-sso-login-qt 2012-03-15 20:16:16 +0000
3+++ bin/ubuntu-sso-login-qt 2012-03-27 15:37:32 +0000
4@@ -21,14 +21,13 @@
5 # Access to a protected member, pylint: disable=W0212
6
7 import sys
8+if sys.platform == 'win32':
9+ import qt4reactor
10+ qt4reactor.install()
11
12 from ubuntu_sso.qt.main import main
13 from ubuntu_sso.utils.ui import parse_args
14
15-if sys.platform.startswith('linux'):
16- from dbus.mainloop.qt import DBusQtMainLoop
17- DBusQtMainLoop(set_as_default=True)
18-
19
20 if __name__ == "__main__":
21 args = parse_args()
22
23=== modified file 'data/qt/stylesheet.qss'
24--- data/qt/stylesheet.qss 2012-03-16 21:24:05 +0000
25+++ data/qt/stylesheet.qss 2012-03-27 15:37:32 +0000
26@@ -1,5 +1,6 @@
27 QWidget {
28 color: #333333;
29+ background-color: white;
30 }
31
32 QFrame#ubuntussoframe {
33
34=== modified file 'run-tests'
35--- run-tests 2012-03-13 03:10:00 +0000
36+++ run-tests 2012-03-27 15:37:32 +0000
37@@ -16,7 +16,7 @@
38 # You should have received a copy of the GNU General Public License along
39 # with this program. If not, see <http://www.gnu.org/licenses/>.
40
41-QT_TESTS_PATH=ubuntu_sso/qt/tests
42+QT_TESTS_PATH="ubuntu_sso/qt/tests, ubuntu_sso/qt/main/tests"
43 GTK_TESTS_PATH=ubuntu_sso/gtk/tests
44 WINDOWS_TESTS=test_windows.py
45
46
47=== modified file 'setup.py'
48--- setup.py 2012-03-21 13:43:30 +0000
49+++ setup.py 2012-03-27 15:37:32 +0000
50@@ -355,6 +355,7 @@
51 'ubuntu_sso.networkstate',
52 'ubuntu_sso.networkstate.tests',
53 'ubuntu_sso.qt',
54+ 'ubuntu_sso.qt.main',
55 'ubuntu_sso.qt.ui',
56 'ubuntu_sso.utils',
57 'ubuntu_sso.utils.tests',
58
59=== modified file 'ubuntu_sso/main/tests/test_common.py'
60--- ubuntu_sso/main/tests/test_common.py 2012-02-17 18:43:17 +0000
61+++ ubuntu_sso/main/tests/test_common.py 2012-03-27 15:37:32 +0000
62@@ -118,6 +118,18 @@
63 self.assertEqual(result["errtype"], e.__class__.__name__)
64 self.assertEqual(result["message"], sample_string)
65
66+ def test_first_arg_is_exception(self):
67+ """If the first arg is an Exception, use it's message attribute'."""
68+
69+ class MyException(Exception):
70+ """Custom Exception."""
71+
72+ message = u'My custom error for ♥ Ubuntu'
73+ my_exc = MyException(message)
74+ result = except_to_errdict(my_exc)
75+ self.assertEqual(result["errtype"], my_exc.__class__.__name__)
76+ self.assertEqual(result["message"], message)
77+
78 def test_first_arg_is_unicode(self):
79 """If the first arg is a unicode, use it as the message."""
80 sample_string = u"a sample string"
81
82=== added directory 'ubuntu_sso/qt/main'
83=== renamed file 'ubuntu_sso/qt/main.py' => 'ubuntu_sso/qt/main/__init__.py'
84--- ubuntu_sso/qt/main.py 2012-03-19 20:10:32 +0000
85+++ ubuntu_sso/qt/main/__init__.py 2012-03-27 15:37:32 +0000
86@@ -14,7 +14,7 @@
87 # You should have received a copy of the GNU General Public License along
88 # with this program. If not, see <http://www.gnu.org/licenses/>.
89
90-"""Main module to open the GTK UI."""
91+"""Main module to open the QT UI."""
92
93 import sys
94
95@@ -28,12 +28,21 @@
96 from ubuntu_sso.utils import PLATFORM_QSS
97
98
99+# Invalid name "source", pylint: disable=C0103
100+if sys.platform == 'win32':
101+ from ubuntu_sso.qt.main import windows
102+ source = windows
103+else:
104+ from ubuntu_sso.qt.main import linux
105+ source = linux
106+# pylint: enable=C0103
107+
108+
109 def main(**kwargs):
110 """Start the QT mainloop and open the main window."""
111 app = QtGui.QApplication(sys.argv)
112
113- QtGui.QFontDatabase.addApplicationFont(':/Ubuntu-R.ttf')
114- QtGui.QFontDatabase.addApplicationFont(':/Ubuntu-B.ttf')
115+ source.main(app)
116
117 data = []
118 for qss_name in (PLATFORM_QSS, ":/stylesheet.qss"):
119@@ -48,10 +57,12 @@
120 kwargs[key] = value.decode('utf-8')
121
122 # Unused variable 'ui', pylint: disable=W0612
123- ui = UbuntuSSOClientGUI(close_callback=app.exit, **kwargs)
124+ close_callback = lambda: source.main_quit(app)
125+ ui = UbuntuSSOClientGUI(close_callback=close_callback, **kwargs)
126 style = QtGui.QStyle.alignedRect(
127 QtCore.Qt.LeftToRight, QtCore.Qt.AlignCenter,
128 ui.size(), app.desktop().availableGeometry())
129 ui.setGeometry(style)
130 ui.show()
131- app.exec_()
132+
133+ source.main_start(app)
134
135=== added file 'ubuntu_sso/qt/main/linux.py'
136--- ubuntu_sso/qt/main/linux.py 1970-01-01 00:00:00 +0000
137+++ ubuntu_sso/qt/main/linux.py 2012-03-27 15:37:32 +0000
138@@ -0,0 +1,35 @@
139+# -*- coding: utf-8 -*-
140+#
141+# Copyright 2012 Canonical Ltd.
142+#
143+# This program is free software: you can redistribute it and/or modify it
144+# under the terms of the GNU General Public License version 3, as published
145+# by the Free Software Foundation.
146+#
147+# This program is distributed in the hope that it will be useful, but
148+# WITHOUT ANY WARRANTY; without even the implied warranties of
149+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
150+# PURPOSE. See the GNU General Public License for more details.
151+#
152+# You should have received a copy of the GNU General Public License along
153+# with this program. If not, see <http://www.gnu.org/licenses/>.
154+
155+"""Main method to be used on linux."""
156+
157+
158+def main(app):
159+ """Apply style sheet."""
160+ from dbus.mainloop.qt import DBusQtMainLoop
161+ DBusQtMainLoop(set_as_default=True)
162+
163+
164+def main_start(app):
165+ """Start the mainloop."""
166+ app.exec_()
167+
168+
169+def main_quit(app):
170+ """Stop the mainloop."""
171+ app.exit()
172+
173+PLATFORM_QSS = ":/linux.qss"
174
175=== added directory 'ubuntu_sso/qt/main/tests'
176=== added file 'ubuntu_sso/qt/main/tests/__init__.py'
177--- ubuntu_sso/qt/main/tests/__init__.py 1970-01-01 00:00:00 +0000
178+++ ubuntu_sso/qt/main/tests/__init__.py 2012-03-27 15:37:32 +0000
179@@ -0,0 +1,17 @@
180+# -*- coding: utf-8 -*-
181+#
182+# Copyright 2012 Canonical Ltd.
183+#
184+# This program is free software: you can redistribute it and/or modify it
185+# under the terms of the GNU General Public License version 3, as published
186+# by the Free Software Foundation.
187+#
188+# This program is distributed in the hope that it will be useful, but
189+# WITHOUT ANY WARRANTY; without even the implied warranties of
190+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
191+# PURPOSE. See the GNU General Public License for more details.
192+#
193+# You should have received a copy of the GNU General Public License along
194+# with this program. If not, see <http://www.gnu.org/licenses/>.
195+
196+"""The test suite for the Qt UI for SSO."""
197
198=== renamed file 'ubuntu_sso/qt/tests/test_main.py' => 'ubuntu_sso/qt/main/tests/test_main.py'
199--- ubuntu_sso/qt/tests/test_main.py 2012-03-19 20:17:49 +0000
200+++ ubuntu_sso/qt/main/tests/test_main.py 2012-03-27 15:37:32 +0000
201@@ -91,13 +91,22 @@
202 def setUp(self):
203 yield super(BasicTestCase, self).setUp()
204 self.called = []
205+ self._close_callback = None
206+ self._app = None
207
208- def called_ui(**kw):
209+ def called_ui(method, *args, **kw):
210 """record ui call."""
211- self.called.append(('GUI', kw))
212+ if 'close_callback' in kw:
213+ self._close_callback = kw.pop('close_callback')
214+ self.called.append((method, args, kw))
215 return FakeUi()
216
217- self.patch(main, 'UbuntuSSOClientGUI', called_ui)
218+ self.patch(main, 'UbuntuSSOClientGUI',
219+ lambda *arg, **kw: called_ui('GUI', *arg, **kw))
220+ self.patch(main.source, 'main',
221+ lambda *arg, **kw: called_ui('main', *arg, **kw))
222+ self.patch(main.source, 'main_start',
223+ lambda *arg, **kw: called_ui('main_start', *arg, **kw))
224 self.patch(main.QtGui, 'QApplication', FakeApplication)
225
226 def test_main(self):
227@@ -106,8 +115,30 @@
228 baz='yadda', yadda=0)
229 main.main(**kwargs)
230
231- kwargs['close_callback'] = main.QtGui.QApplication.instance().exit
232- self.assertEqual(self.called, [('GUI', kwargs)])
233+ expected = [('main', (FakeApplication.instance(),), {}),
234+ ('GUI', (), kwargs),
235+ ('main_start', (FakeApplication.instance(),), {})]
236+ self.assertEqual(self.called, expected)
237+
238+ def test_check_close_callback(self):
239+ """Check that the close callback is main_quit."""
240+
241+ def called_quit(app):
242+ """Record the call to quit."""
243+ self._app = app
244+
245+ self.patch(main.source, 'main_quit', called_quit)
246+
247+ kwargs = dict(app_name='APP_NAME', foo='foo', bar='bar',
248+ baz='yadda', yadda=0)
249+ main.main(**kwargs)
250+
251+ expected = [('main', (FakeApplication.instance(),), {}),
252+ ('GUI', (), kwargs),
253+ ('main_start', (FakeApplication.instance(),), {})]
254+ self._close_callback()
255+ self.assertEqual(self.called, expected)
256+ self.assertEqual(self._app, FakeApplication.instance())
257
258 def test_main_args(self):
259 """Calling main.main() a UI instance is created."""
260@@ -119,11 +150,12 @@
261 baz=arg_list[3].encode('utf-8'))
262 main.main(**kwargs)
263
264- kwargs['close_callback'] = main.QtGui.QApplication.instance().exit
265- expected = dict(app_name=arg_list[0], foo=arg_list[1],
266- bar=arg_list[2], baz=arg_list[3],
267- close_callback=main.QtGui.QApplication.instance().exit)
268- self.assertEqual(self.called, [('GUI', expected)])
269+ args_unicode = dict(app_name=arg_list[0], foo=arg_list[1],
270+ bar=arg_list[2], baz=arg_list[3])
271+ expected = [('main', (FakeApplication.instance(),), {}),
272+ ('GUI', (), args_unicode),
273+ ('main_start', (FakeApplication.instance(),), {})]
274+ self.assertEqual(self.called, expected)
275
276 def test_styles_load(self):
277 """Test that all stylesheets load."""
278
279=== added file 'ubuntu_sso/qt/main/windows.py'
280--- ubuntu_sso/qt/main/windows.py 1970-01-01 00:00:00 +0000
281+++ ubuntu_sso/qt/main/windows.py 2012-03-27 15:37:32 +0000
282@@ -0,0 +1,46 @@
283+# -*- coding: utf-8 -*-
284+#
285+# Copyright 2012 Canonical Ltd.
286+#
287+# This program is free software: you can redistribute it and/or modify it
288+# under the terms of the GNU General Public License version 3, as published
289+# by the Free Software Foundation.
290+#
291+# This program is distributed in the hope that it will be useful, but
292+# WITHOUT ANY WARRANTY; without even the implied warranties of
293+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
294+# PURPOSE. See the GNU General Public License for more details.
295+#
296+# You should have received a copy of the GNU General Public License along
297+# with this program. If not, see <http://www.gnu.org/licenses/>.
298+
299+"""Main method to be used on windows."""
300+
301+from PyQt4 import QtGui
302+
303+
304+def main(app):
305+ """Apply style sheet and fonts."""
306+ # Apply font to the entire application
307+ QtGui.QFontDatabase.addApplicationFont(':/Ubuntu-R.ttf')
308+ QtGui.QFontDatabase.addApplicationFont(':/Ubuntu-B.ttf')
309+
310+
311+# Module 'reactor' has no 'run'/'stop' member, pylint: disable=E1101
312+
313+
314+def main_start(app):
315+ """Start the mainloop."""
316+ from twisted.internet import reactor
317+ reactor.run()
318+
319+
320+def main_quit(app):
321+ """Stop the mainloop."""
322+ from twisted.internet import reactor
323+ reactor.stop()
324+
325+
326+# pylint: enable=E1101
327+
328+PLATFORM_QSS = ":/windows.qss"
329
330=== modified file 'ubuntu_sso/qt/proxy_dialog.py'
331--- ubuntu_sso/qt/proxy_dialog.py 2012-03-08 12:35:25 +0000
332+++ ubuntu_sso/qt/proxy_dialog.py 2012-03-27 15:37:32 +0000
333@@ -106,6 +106,7 @@
334 except Exception, e:
335 logger.exception('Could not set credentials:')
336 self.done(EXCEPTION_RAISED)
337+ logger.debug('Stored creds')
338 # pylint: disable=W0703, W0612
339 self.done(USER_SUCCESS)
340
341@@ -140,13 +141,41 @@
342 return parser.parse_args()
343
344
345+def exit_code(return_code):
346+ """Use the window result code and the sys.exit."""
347+ logger.debug('exit %s', return_code)
348+ QApplication.instance().exit(return_code)
349+ if sys.platform == 'win32':
350+ logger.debug('Stop qt reactor')
351+ from twisted.internet import reactor
352+ reactor.stop()
353+
354+
355 def main():
356 """Main method used to show the creds dialog."""
357 # Keep ref to avoid core dump, pylint: disable=W0612
358+
359+ if sys.platform == 'win32':
360+ import qt4reactor
361+ qt4reactor.install()
362+ logger.debug('Qt reactor installed.')
363+
364 app = QApplication(sys.argv)
365 # pylint: enable=W0612
366 args = parse_args()
367 win = ProxyCredsDialog(domain=args.domain,
368 retry=args.retry)
369- return_code = win.exec_()
370- sys.exit(return_code)
371+
372+ if sys.platform == 'win32':
373+ win.show()
374+ win.finished.connect(exit_code)
375+
376+ logger.debug('Starting reactor')
377+ # pylint: disable=E1101
378+ from twisted.internet import reactor
379+ logger.debug('QApp is %s', reactor.qApp)
380+ reactor.run()
381+ # pylint: enable=E1101
382+ else:
383+ return_code = win.exec_()
384+ sys.exit(return_code)
385
386=== modified file 'ubuntu_sso/qt/tests/test_proxy_dialog.py'
387--- ubuntu_sso/qt/tests/test_proxy_dialog.py 2012-03-07 18:13:04 +0000
388+++ ubuntu_sso/qt/tests/test_proxy_dialog.py 2012-03-27 15:37:32 +0000
389@@ -15,7 +15,10 @@
390 # with this program. If not, see <http://www.gnu.org/licenses/>.
391 """Test the proxy UI."""
392
393-from twisted.internet import defer
394+import qt4reactor
395+
396+from PyQt4.QtCore import QObject, pyqtSignal
397+from twisted.internet import defer, reactor
398 from twisted.trial.unittest import TestCase
399
400 from ubuntu_sso.qt import proxy_dialog
401@@ -301,6 +304,62 @@
402 self.retry = retry
403
404
405+class FakeCredsDialog(QObject):
406+ """A fake dialog."""
407+
408+ finished = pyqtSignal(int)
409+
410+ def __init__(self, called, code):
411+ """Create a new instance."""
412+ super(FakeCredsDialog, self).__init__()
413+ self.domain = None
414+ self.retry = None
415+ self.called = called
416+ self.return_code = code
417+
418+ def __call__(self, domain, retry):
419+ """Fake init."""
420+ self.domain = domain
421+ self.retry = retry
422+ return self
423+
424+ def show(self):
425+ """Show the dialog."""
426+ self.called.append(('show',))
427+
428+ def exec_(self):
429+ """Show the dialog."""
430+ self.called.append(('exec_',))
431+ return self.return_code
432+
433+
434+class FakeQApplication(object):
435+ """A fake QApplication."""
436+
437+ test_instance = None
438+
439+ def __init__(self, called):
440+ """Create a new instance."""
441+ self.called = called
442+ self.args = None
443+ self.code = None
444+ FakeQApplication.test_instance = self
445+
446+ def __call__(self, args):
447+ """Fake construntor."""
448+ self.args = args
449+
450+ @classmethod
451+ def instance(cls):
452+ """Return the instance."""
453+ return FakeQApplication.test_instance
454+
455+ def exit(self, code):
456+ """Exit the app."""
457+ self.called.append(('exit', code))
458+ self.code = code
459+
460+
461 class MainTest(TestCase):
462 """Test the main method."""
463
464@@ -310,29 +369,91 @@
465 yield super(MainTest, self).setUp()
466 self.called = []
467
468+ self.return_code = 0
469+ self.dialog = FakeCredsDialog(self.called, self.return_code)
470+ self.patch(proxy_dialog, 'ProxyCredsDialog', self.dialog)
471+
472 self.args = FakeArgs(domain='domain', retry=False)
473 self.patch(proxy_dialog, 'parse_args', lambda: self.args)
474
475- self.return_code = 0
476- self.patch(proxy_dialog.ProxyCredsDialog, 'exec_', lambda x:
477- self.return_code)
478 self.exit_code = None
479
480+ self.app = FakeQApplication(self.called)
481+
482+ self.patch(proxy_dialog, 'QApplication', self.app)
483+
484+ def _set_old_platform(self, platform):
485+ """Set back the platform."""
486+ proxy_dialog.sys.platform = platform
487+
488+ def _assert_basic_start(self):
489+ """Assert the common code is actually ran."""
490+ self.assertEqual(self.args.domain, self.dialog.domain)
491+ self.assertEqual(self.args.retry, self.dialog.retry)
492+
493+ def test_linux_main(self):
494+ """Test the main method on linux."""
495+ old_platform = proxy_dialog.sys.platform
496+ proxy_dialog.sys.platform = 'linux'
497+ self.addCleanup(self._set_old_platform, old_platform)
498+
499 def fake_exit(code):
500- """Fake the sys.exit."""
501+ """Fake sys exit."""
502 self.called.append(('exit', code))
503- self.exit_code = code
504
505 self.patch(proxy_dialog.sys, 'exit', fake_exit)
506
507- def fake_application(args):
508- """Fake a QApplication."""
509- self.called.append(('QApplication', args))
510-
511- self.patch(proxy_dialog, 'QApplication', fake_application)
512-
513- def test_main(self):
514- """Test the main method."""
515- proxy_dialog.main()
516- self.assertIn('QApplication', self.called[0])
517+ proxy_dialog.main()
518+
519+ self._assert_basic_start()
520+ self.assertIn(('exec_',), self.called)
521+ self.assertIn(('exit', self.return_code), self.called)
522+
523+ def test_windows_main(self):
524+ """Test the main method on windows."""
525+ old_platform = proxy_dialog.sys.platform
526+ proxy_dialog.sys.platform = 'win32'
527+ self.addCleanup(self._set_old_platform, old_platform)
528+
529+ def fake_install():
530+ """Fake the reactor installation."""
531+ self.called.append(('install',))
532+
533+ self.patch(qt4reactor, 'install', fake_install)
534+
535+ def fake_start():
536+ """Fake reactor.start."""
537+ self.called.append(('run',))
538+
539+ self.patch(reactor, 'run', fake_start)
540+
541+ def fake_exit(code):
542+ """Fake the exit method."""
543+ self.called.append(('exit_code', code))
544+
545+ self.patch(proxy_dialog, 'exit_code', fake_exit)
546+
547+ proxy_dialog.main()
548+
549+ self._assert_basic_start()
550+ self.assertIn(('show',), self.called)
551+ self.assertIn(('run',), self.called)
552+
553+ self.dialog.finished.emit(self.return_code)
554+ self.assertIn(('exit_code', self.return_code), self.called)
555+
556+ def test_exit_code_windows(self):
557+ """"Test the exit code function."""
558+ old_platform = proxy_dialog.sys.platform
559+ proxy_dialog.sys.platform = 'win32'
560+ self.addCleanup(self._set_old_platform, old_platform)
561+
562+ def fake_stop():
563+ """Fake reactor.start."""
564+ self.called.append(('stop',))
565+
566+ self.patch(reactor, 'stop', fake_stop)
567+
568+ proxy_dialog.exit_code(self.return_code)
569+ self.assertIn(('stop',), self.called)
570 self.assertIn(('exit', self.return_code), self.called)
571
572=== modified file 'ubuntu_sso/utils/webclient/qtnetwork.py'
573--- ubuntu_sso/utils/webclient/qtnetwork.py 2012-03-19 23:53:06 +0000
574+++ ubuntu_sso/utils/webclient/qtnetwork.py 2012-03-27 15:37:32 +0000
575@@ -188,7 +188,8 @@
576 response = Response(bytes(content), headers)
577 d.callback(response)
578 else:
579- error_string = reply.errorString()
580+ content = unicode(content)
581+ error_string = unicode(reply.errorString())
582 logger.debug('_handle_finished error (%s,%s).', error,
583 error_string)
584 if error == QNetworkReply.AuthenticationRequiredError:
585
586=== modified file 'ubuntu_sso/utils/webclient/tests/test_webclient.py'
587--- ubuntu_sso/utils/webclient/tests/test_webclient.py 2012-03-19 23:43:56 +0000
588+++ ubuntu_sso/utils/webclient/tests/test_webclient.py 2012-03-27 15:37:32 +0000
589@@ -373,6 +373,14 @@
590 self.assertTrue(isinstance(result.content, bytes),
591 "The type of %r must be bytes" % result.content)
592
593+ @defer.inlineCallbacks
594+ def test_webclienterror_not_string(self):
595+ """The returned exception contains unicode data."""
596+ deferred = self.wc.request(self.base_iri + THROWERROR)
597+ failure = yield self.assertFailure(deferred, webclient.WebClientError)
598+ for error in failure.args:
599+ self.assertTrue(isinstance(error, basestring))
600+
601
602 class FakeSavingReactor(object):
603 """A fake reactor that saves connection attempts."""

Subscribers

People subscribed via source and target branches