Merge lp:~diegosarmentero/ubuntu-sso-client/main-moved into lp:ubuntu-sso-client

Proposed by Diego Sarmentero on 2012-03-21
Status: Merged
Approved by: Roberto Alsina on 2012-03-25
Approved revision: 938
Merged at revision: 933
Proposed branch: lp:~diegosarmentero/ubuntu-sso-client/main-moved
Merge into: lp:ubuntu-sso-client
Diff against target: 282 lines (+160/-20)
7 files modified
bin/ubuntu-sso-login-qt (+3/-4)
run-tests (+1/-1)
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)
To merge this branch: bzr merge lp:~diegosarmentero/ubuntu-sso-client/main-moved
Reviewer Review Type Date Requested Status
Natalia Bidart 2012-03-21 Approve on 2012-03-23
Review via email: mp+98703@code.launchpad.net

Commit Message

- 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)

To post a comment you must log in.
933. By Diego Sarmentero on 2012-03-21

Installing qtreactor

934. By Diego Sarmentero on 2012-03-21

main updated

935. By Diego Sarmentero on 2012-03-21

Linking bug number.

Natalia Bidart (nataliabidart) wrote :

* By popping the 'close_callback' param, you're no longer testing that the proper close_callback is passed to the GUI. Can you please restore that?

* Is better to have self.called to be a list so you can test that a given method (and only a given method) was called.

* These two tests have a lot of code duplication:

def test_main_source_main(self):
def test_main_source_main_start(self):

You could improve all the above by doing something like:

class BasicTestCase(TestCase):
    """Test case with a helper tracker."""

    @defer.inlineCallbacks
    def setUp(self):
        yield super(BasicTestCase, self).setUp()
        self.called = []

        def called_ui(**kw):
            """record ui call."""
            kw.pop('close_callback')
            self.called['called_ui'] = ('GUI', kw)
            return FakeUi()

        self.patch(main.QtGui, 'QApplication', FakeApplication)
        self.patch(main, 'UbuntuSSOClientGUI',
                   lambda *a, **kw: self.called.append(('GUI', a, kw)))
        self.patch(main.source, 'main',
                   lambda *a, **kw: self.called.append(('source.main', a, kw)))
        self.patch(main.source, 'main_start',
                   lambda *a, **kw: self.called.append(('source.main_start', a, kw)))

    def test_main(self):
        """Calling main.main() a UI instance is created."""
        kwargs = dict(app_name='APP_NAME', foo='foo', bar='bar',
            baz='yadda', yadda=0)
        main.main(**kwargs)

        kwargs['close_callback'] = main.source.main_quit
        self.assertEqual(self.called, [('GUI', (), kwargs), ('source.main', ...), ('source.main_start', ...)])

and thus you can safely remove:

    def test_main_source_main(self):
    def test_main_source_main_start(self):

* You're adding old copyright notices (new files say 2011 or 2011-2012, they should be only 2012).

review: Needs Fixing
936. By Diego Sarmentero on 2012-03-22

Fixing tests.

937. By Diego Sarmentero on 2012-03-22

Adding a python to ignore during gtk tests

Natalia Bidart (nataliabidart) wrote :

The refactored test is not testing that the proper methods were called, since, having this list:

        expected = [((FakeApplication.instance(),), {}),
            ((), kwargs), ((FakeApplication.instance(),), {})]

how can you tell that the first item ((FakeApplication.instance(),), {}) was added by the proper call, and not by the call that adds the last ((FakeApplication.instance(),), {})? (or viceversa).

In my proposal the name of the method is added to the 'called' list, so you can ensure the desired methods were called when needed and in the right order.

On the other hand, I liked how you solved the close_callback issue :-).

review: Needs Fixing
938. By Diego Sarmentero on 2012-03-23

fixing tests.

Natalia Bidart (nataliabidart) wrote :

Looks great, thanks!

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-23 15:33:17 +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 'run-tests'
24--- run-tests 2012-03-13 03:10:00 +0000
25+++ run-tests 2012-03-23 15:33:17 +0000
26@@ -16,7 +16,7 @@
27 # You should have received a copy of the GNU General Public License along
28 # with this program. If not, see <http://www.gnu.org/licenses/>.
29
30-QT_TESTS_PATH=ubuntu_sso/qt/tests
31+QT_TESTS_PATH="ubuntu_sso/qt/tests, ubuntu_sso/qt/main/tests"
32 GTK_TESTS_PATH=ubuntu_sso/gtk/tests
33 WINDOWS_TESTS=test_windows.py
34
35
36=== added directory 'ubuntu_sso/qt/main'
37=== renamed file 'ubuntu_sso/qt/main.py' => 'ubuntu_sso/qt/main/__init__.py'
38--- ubuntu_sso/qt/main.py 2012-03-19 20:10:32 +0000
39+++ ubuntu_sso/qt/main/__init__.py 2012-03-23 15:33:17 +0000
40@@ -14,7 +14,7 @@
41 # You should have received a copy of the GNU General Public License along
42 # with this program. If not, see <http://www.gnu.org/licenses/>.
43
44-"""Main module to open the GTK UI."""
45+"""Main module to open the QT UI."""
46
47 import sys
48
49@@ -28,12 +28,21 @@
50 from ubuntu_sso.utils import PLATFORM_QSS
51
52
53+# Invalid name "source", pylint: disable=C0103
54+if sys.platform == 'win32':
55+ from ubuntu_sso.qt.main import windows
56+ source = windows
57+else:
58+ from ubuntu_sso.qt.main import linux
59+ source = linux
60+# pylint: enable=C0103
61+
62+
63 def main(**kwargs):
64 """Start the QT mainloop and open the main window."""
65 app = QtGui.QApplication(sys.argv)
66
67- QtGui.QFontDatabase.addApplicationFont(':/Ubuntu-R.ttf')
68- QtGui.QFontDatabase.addApplicationFont(':/Ubuntu-B.ttf')
69+ source.main(app)
70
71 data = []
72 for qss_name in (PLATFORM_QSS, ":/stylesheet.qss"):
73@@ -48,10 +57,12 @@
74 kwargs[key] = value.decode('utf-8')
75
76 # Unused variable 'ui', pylint: disable=W0612
77- ui = UbuntuSSOClientGUI(close_callback=app.exit, **kwargs)
78+ close_callback = lambda: source.main_quit(app)
79+ ui = UbuntuSSOClientGUI(close_callback=close_callback, **kwargs)
80 style = QtGui.QStyle.alignedRect(
81 QtCore.Qt.LeftToRight, QtCore.Qt.AlignCenter,
82 ui.size(), app.desktop().availableGeometry())
83 ui.setGeometry(style)
84 ui.show()
85- app.exec_()
86+
87+ source.main_start(app)
88
89=== added file 'ubuntu_sso/qt/main/linux.py'
90--- ubuntu_sso/qt/main/linux.py 1970-01-01 00:00:00 +0000
91+++ ubuntu_sso/qt/main/linux.py 2012-03-23 15:33:17 +0000
92@@ -0,0 +1,35 @@
93+# -*- coding: utf-8 -*-
94+#
95+# Copyright 2012 Canonical Ltd.
96+#
97+# This program is free software: you can redistribute it and/or modify it
98+# under the terms of the GNU General Public License version 3, as published
99+# by the Free Software Foundation.
100+#
101+# This program is distributed in the hope that it will be useful, but
102+# WITHOUT ANY WARRANTY; without even the implied warranties of
103+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
104+# PURPOSE. See the GNU General Public License for more details.
105+#
106+# You should have received a copy of the GNU General Public License along
107+# with this program. If not, see <http://www.gnu.org/licenses/>.
108+
109+"""Main method to be used on linux."""
110+
111+
112+def main(app):
113+ """Apply style sheet."""
114+ from dbus.mainloop.qt import DBusQtMainLoop
115+ DBusQtMainLoop(set_as_default=True)
116+
117+
118+def main_start(app):
119+ """Start the mainloop."""
120+ app.exec_()
121+
122+
123+def main_quit(app):
124+ """Stop the mainloop."""
125+ app.exit()
126+
127+PLATFORM_QSS = ":/linux.qss"
128
129=== added directory 'ubuntu_sso/qt/main/tests'
130=== added file 'ubuntu_sso/qt/main/tests/__init__.py'
131--- ubuntu_sso/qt/main/tests/__init__.py 1970-01-01 00:00:00 +0000
132+++ ubuntu_sso/qt/main/tests/__init__.py 2012-03-23 15:33:17 +0000
133@@ -0,0 +1,17 @@
134+# -*- coding: utf-8 -*-
135+#
136+# Copyright 2012 Canonical Ltd.
137+#
138+# This program is free software: you can redistribute it and/or modify it
139+# under the terms of the GNU General Public License version 3, as published
140+# by the Free Software Foundation.
141+#
142+# This program is distributed in the hope that it will be useful, but
143+# WITHOUT ANY WARRANTY; without even the implied warranties of
144+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
145+# PURPOSE. See the GNU General Public License for more details.
146+#
147+# You should have received a copy of the GNU General Public License along
148+# with this program. If not, see <http://www.gnu.org/licenses/>.
149+
150+"""The test suite for the Qt UI for SSO."""
151
152=== renamed file 'ubuntu_sso/qt/tests/test_main.py' => 'ubuntu_sso/qt/main/tests/test_main.py'
153--- ubuntu_sso/qt/tests/test_main.py 2012-03-19 20:17:49 +0000
154+++ ubuntu_sso/qt/main/tests/test_main.py 2012-03-23 15:33:17 +0000
155@@ -91,13 +91,22 @@
156 def setUp(self):
157 yield super(BasicTestCase, self).setUp()
158 self.called = []
159+ self._close_callback = None
160+ self._app = None
161
162- def called_ui(**kw):
163+ def called_ui(method, *args, **kw):
164 """record ui call."""
165- self.called.append(('GUI', kw))
166+ if 'close_callback' in kw:
167+ self._close_callback = kw.pop('close_callback')
168+ self.called.append((method, args, kw))
169 return FakeUi()
170
171- self.patch(main, 'UbuntuSSOClientGUI', called_ui)
172+ self.patch(main, 'UbuntuSSOClientGUI',
173+ lambda *arg, **kw: called_ui('GUI', *arg, **kw))
174+ self.patch(main.source, 'main',
175+ lambda *arg, **kw: called_ui('main', *arg, **kw))
176+ self.patch(main.source, 'main_start',
177+ lambda *arg, **kw: called_ui('main_start', *arg, **kw))
178 self.patch(main.QtGui, 'QApplication', FakeApplication)
179
180 def test_main(self):
181@@ -106,8 +115,30 @@
182 baz='yadda', yadda=0)
183 main.main(**kwargs)
184
185- kwargs['close_callback'] = main.QtGui.QApplication.instance().exit
186- self.assertEqual(self.called, [('GUI', kwargs)])
187+ expected = [('main', (FakeApplication.instance(),), {}),
188+ ('GUI', (), kwargs),
189+ ('main_start', (FakeApplication.instance(),), {})]
190+ self.assertEqual(self.called, expected)
191+
192+ def test_check_close_callback(self):
193+ """Check that the close callback is main_quit."""
194+
195+ def called_quit(app):
196+ """Record the call to quit."""
197+ self._app = app
198+
199+ self.patch(main.source, 'main_quit', called_quit)
200+
201+ kwargs = dict(app_name='APP_NAME', foo='foo', bar='bar',
202+ baz='yadda', yadda=0)
203+ main.main(**kwargs)
204+
205+ expected = [('main', (FakeApplication.instance(),), {}),
206+ ('GUI', (), kwargs),
207+ ('main_start', (FakeApplication.instance(),), {})]
208+ self._close_callback()
209+ self.assertEqual(self.called, expected)
210+ self.assertEqual(self._app, FakeApplication.instance())
211
212 def test_main_args(self):
213 """Calling main.main() a UI instance is created."""
214@@ -119,11 +150,12 @@
215 baz=arg_list[3].encode('utf-8'))
216 main.main(**kwargs)
217
218- kwargs['close_callback'] = main.QtGui.QApplication.instance().exit
219- expected = dict(app_name=arg_list[0], foo=arg_list[1],
220- bar=arg_list[2], baz=arg_list[3],
221- close_callback=main.QtGui.QApplication.instance().exit)
222- self.assertEqual(self.called, [('GUI', expected)])
223+ args_unicode = dict(app_name=arg_list[0], foo=arg_list[1],
224+ bar=arg_list[2], baz=arg_list[3])
225+ expected = [('main', (FakeApplication.instance(),), {}),
226+ ('GUI', (), args_unicode),
227+ ('main_start', (FakeApplication.instance(),), {})]
228+ self.assertEqual(self.called, expected)
229
230 def test_styles_load(self):
231 """Test that all stylesheets load."""
232
233=== added file 'ubuntu_sso/qt/main/windows.py'
234--- ubuntu_sso/qt/main/windows.py 1970-01-01 00:00:00 +0000
235+++ ubuntu_sso/qt/main/windows.py 2012-03-23 15:33:17 +0000
236@@ -0,0 +1,46 @@
237+# -*- coding: utf-8 -*-
238+#
239+# Copyright 2012 Canonical Ltd.
240+#
241+# This program is free software: you can redistribute it and/or modify it
242+# under the terms of the GNU General Public License version 3, as published
243+# by the Free Software Foundation.
244+#
245+# This program is distributed in the hope that it will be useful, but
246+# WITHOUT ANY WARRANTY; without even the implied warranties of
247+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
248+# PURPOSE. See the GNU General Public License for more details.
249+#
250+# You should have received a copy of the GNU General Public License along
251+# with this program. If not, see <http://www.gnu.org/licenses/>.
252+
253+"""Main method to be used on windows."""
254+
255+from PyQt4 import QtGui
256+
257+
258+def main(app):
259+ """Apply style sheet and fonts."""
260+ # Apply font to the entire application
261+ QtGui.QFontDatabase.addApplicationFont(':/Ubuntu-R.ttf')
262+ QtGui.QFontDatabase.addApplicationFont(':/Ubuntu-B.ttf')
263+
264+
265+# Module 'reactor' has no 'run'/'stop' member, pylint: disable=E1101
266+
267+
268+def main_start(app):
269+ """Start the mainloop."""
270+ from twisted.internet import reactor
271+ reactor.run()
272+
273+
274+def main_quit(app):
275+ """Stop the mainloop."""
276+ from twisted.internet import reactor
277+ reactor.stop()
278+
279+
280+# pylint: enable=E1101
281+
282+PLATFORM_QSS = ":/windows.qss"

Subscribers

People subscribed via source and target branches