Merge lp:~mikemc/ubuntuone-control-panel/launch-separate-darwin-menu into lp:ubuntuone-control-panel
- launch-separate-darwin-menu
- Merge into trunk
Proposed by
Mike McCracken
Status: | Merged |
---|---|
Approved by: | Mike McCracken |
Approved revision: | 383 |
Merged at revision: | 385 |
Proposed branch: | lp:~mikemc/ubuntuone-control-panel/launch-separate-darwin-menu |
Merge into: | lp:ubuntuone-control-panel |
Diff against target: |
420 lines (+226/-26) 6 files modified
ubuntuone/controlpanel/backend.py (+5/-0) ubuntuone/controlpanel/gui/qt/main/__init__.py (+22/-6) ubuntuone/controlpanel/gui/qt/main/darwin.py (+52/-8) ubuntuone/controlpanel/gui/qt/main/tests/test_darwin.py (+104/-5) ubuntuone/controlpanel/gui/qt/main/tests/test_main.py (+17/-7) ubuntuone/controlpanel/tests/test_backend.py (+26/-0) |
To merge this branch: | bzr merge lp:~mikemc/ubuntuone-control-panel/launch-separate-darwin-menu |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Diego Sarmentero (community) | Approve | ||
dobey (community) | Approve | ||
Review via email: mp+135268@code.launchpad.net |
Commit message
- Add support for menu in separate process on darwin. (LP: #1045939)
Description of the change
- Add support for menu in separate process on darwin. (LP: #1045939)
- cmd-q handler in control panel no longer kills syncdaemon
- control panel waits until it gets first syncdaemon status update then launches menu to avoid IPC race in syncdaemontool.
Tests pass on darwin and linux P+Q.
To test IRL on darwin, you need lp:ubuntuone-cocoa-menu, and then you *MUST* package the entire app.
The ubuntuone-
PyObjC works from source in general, but the Cocoa UI loading code doesn't handle that case.
To post a comment you must log in.
Revision history for this message
dobey (dobey) : | # |
review:
Approve
- 383. By Mike McCracken
-
add docstring for dummy class
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'ubuntuone/controlpanel/backend.py' | |||
2 | --- ubuntuone/controlpanel/backend.py 2012-11-29 20:15:08 +0000 | |||
3 | +++ ubuntuone/controlpanel/backend.py 2012-11-30 18:08:22 +0000 | |||
4 | @@ -226,6 +226,11 @@ | |||
5 | 226 | self.sd_client.set_status_changed_handler(cb) | 226 | self.sd_client.set_status_changed_handler(cb) |
6 | 227 | self.is_sd_client_handler_set = True | 227 | self.is_sd_client_handler_set = True |
7 | 228 | 228 | ||
8 | 229 | def remove_status_changed_handler(self, handler): | ||
9 | 230 | """Remove 'handler' from callbacks list.""" | ||
10 | 231 | if handler in self._status_changed_handlers: | ||
11 | 232 | self._status_changed_handlers.remove(handler) | ||
12 | 233 | |||
13 | 229 | @inlineCallbacks | 234 | @inlineCallbacks |
14 | 230 | def _process_device_web_info(self, devices, | 235 | def _process_device_web_info(self, devices, |
15 | 231 | enabled=None, limit_bw=None, | 236 | enabled=None, limit_bw=None, |
16 | 232 | 237 | ||
17 | === modified file 'ubuntuone/controlpanel/gui/qt/main/__init__.py' | |||
18 | --- ubuntuone/controlpanel/gui/qt/main/__init__.py 2012-10-23 19:26:30 +0000 | |||
19 | +++ ubuntuone/controlpanel/gui/qt/main/__init__.py 2012-11-30 18:08:22 +0000 | |||
20 | @@ -40,10 +40,14 @@ | |||
21 | 40 | 40 | ||
22 | 41 | if sys.platform == 'darwin': | 41 | if sys.platform == 'darwin': |
23 | 42 | from ubuntuone.controlpanel.gui.qt.main.darwin import ( | 42 | from ubuntuone.controlpanel.gui.qt.main.darwin import ( |
25 | 43 | install_platform_event_handlers) | 43 | install_platform_event_handlers, MenubarIconLauncher) |
26 | 44 | assert(install_platform_event_handlers) | 44 | assert(install_platform_event_handlers) |
27 | 45 | assert(MenubarIconLauncher) | ||
28 | 45 | else: | 46 | else: |
30 | 46 | install_platform_event_handlers = lambda app: None | 47 | class MenubarIconLauncher: |
31 | 48 | """Dummy. Separate menu launcher not used on win/linux.""" | ||
32 | 49 | install_platform_event_handlers = lambda app, **kwargs: None | ||
33 | 50 | |||
34 | 47 | # pylint: enable=C0103 | 51 | # pylint: enable=C0103 |
35 | 48 | 52 | ||
36 | 49 | from ubuntuone.controlpanel.utils import install_config_and_daemons | 53 | from ubuntuone.controlpanel.utils import install_config_and_daemons |
37 | @@ -118,9 +122,7 @@ | |||
38 | 118 | args = parser.parse_args(args=arg_list[bin_position:]) | 122 | args = parser.parse_args(args=arg_list[bin_position:]) |
39 | 119 | switch_to = args.switch_to | 123 | switch_to = args.switch_to |
40 | 120 | minimized = args.minimized | 124 | minimized = args.minimized |
44 | 121 | # On Darwin, because of how apps are started, we need | 125 | with_icon = args.with_icon |
42 | 122 | # this by default. | ||
43 | 123 | with_icon = args.with_icon or sys.platform == 'darwin' | ||
45 | 124 | installer = args.installer | 126 | installer = args.installer |
46 | 125 | source.main(app) | 127 | source.main(app) |
47 | 126 | 128 | ||
48 | @@ -135,9 +137,17 @@ | |||
49 | 135 | 137 | ||
50 | 136 | install_config_and_daemons() | 138 | install_config_and_daemons() |
51 | 137 | 139 | ||
52 | 140 | if sys.platform == 'darwin': | ||
53 | 141 | with_icon = False | ||
54 | 142 | # cmd-q in CP shouldn't kill SD or the menu: | ||
55 | 143 | quit_kills_sd = False | ||
56 | 144 | else: | ||
57 | 145 | quit_kills_sd = not with_icon | ||
58 | 146 | |||
59 | 138 | # need to keep a reference to the menu or our handler will be | 147 | # need to keep a reference to the menu or our handler will be |
60 | 139 | # removed | 148 | # removed |
62 | 140 | menubar = install_platform_event_handlers(app) | 149 | menubar = install_platform_event_handlers(app, |
63 | 150 | quit_kills_sd=quit_kills_sd) | ||
64 | 141 | menubar | 151 | menubar |
65 | 142 | 152 | ||
66 | 143 | # Unused variable 'window', 'icon', pylint: disable=W0612 | 153 | # Unused variable 'window', 'icon', pylint: disable=W0612 |
67 | @@ -151,4 +161,10 @@ | |||
68 | 151 | if icon: | 161 | if icon: |
69 | 152 | app.new_instance.connect(icon.restore_window) | 162 | app.new_instance.connect(icon.restore_window) |
70 | 153 | 163 | ||
71 | 164 | if sys.platform == 'darwin': | ||
72 | 165 | # start separate menu app instead of Qt systray menu, waiting | ||
73 | 166 | # until it is safe to do so without IPC races: | ||
74 | 167 | menu_launcher = MenubarIconLauncher() | ||
75 | 168 | assert(menu_launcher) | ||
76 | 169 | |||
77 | 154 | source.main_start(app) | 170 | source.main_start(app) |
78 | 155 | 171 | ||
79 | === modified file 'ubuntuone/controlpanel/gui/qt/main/darwin.py' | |||
80 | --- ubuntuone/controlpanel/gui/qt/main/darwin.py 2012-10-04 20:34:22 +0000 | |||
81 | +++ ubuntuone/controlpanel/gui/qt/main/darwin.py 2012-11-30 18:08:22 +0000 | |||
82 | @@ -16,28 +16,40 @@ | |||
83 | 16 | 16 | ||
84 | 17 | """Darwin-specific GUI event handling code.""" | 17 | """Darwin-specific GUI event handling code.""" |
85 | 18 | 18 | ||
86 | 19 | import sys | ||
87 | 20 | import subprocess | ||
88 | 21 | |||
89 | 19 | from PyQt4 import QtGui | 22 | from PyQt4 import QtGui |
90 | 20 | from twisted.internet.defer import inlineCallbacks | 23 | from twisted.internet.defer import inlineCallbacks |
91 | 21 | 24 | ||
92 | 25 | from dirspec.utils import get_program_path | ||
93 | 26 | |||
94 | 22 | from ubuntuone.platform.tools import SyncDaemonTool | 27 | from ubuntuone.platform.tools import SyncDaemonTool |
95 | 23 | 28 | ||
96 | 29 | from ubuntuone.controlpanel import cache | ||
97 | 30 | from ubuntuone.controlpanel.backend import (STATUS_KEY, FILE_SYNC_ERROR) | ||
98 | 24 | from ubuntuone.controlpanel.gui.qt.main import twisted_main | 31 | from ubuntuone.controlpanel.gui.qt.main import twisted_main |
99 | 32 | from ubuntuone.controlpanel.logger import setup_logging | ||
100 | 33 | |||
101 | 34 | |||
102 | 35 | logger = setup_logging('qt.main.darwin') | ||
103 | 25 | 36 | ||
104 | 26 | 37 | ||
105 | 27 | @inlineCallbacks | 38 | @inlineCallbacks |
107 | 28 | def handle_cmd_q(app, event): | 39 | def handle_cmd_q(app, event, should_quit_sd=False): |
108 | 29 | """Handle the quit event on darwin.""" | 40 | """Handle the quit event on darwin.""" |
109 | 30 | # pylint: disable=W0702 | 41 | # pylint: disable=W0702 |
115 | 31 | try: | 42 | if should_quit_sd: |
116 | 32 | st = SyncDaemonTool() | 43 | try: |
117 | 33 | yield st.quit() | 44 | st = SyncDaemonTool() |
118 | 34 | except: | 45 | yield st.quit() |
119 | 35 | pass | 46 | except: |
120 | 47 | pass | ||
121 | 36 | twisted_main.main_quit(app) | 48 | twisted_main.main_quit(app) |
122 | 37 | app.aboutToQuit.emit() | 49 | app.aboutToQuit.emit() |
123 | 38 | 50 | ||
124 | 39 | 51 | ||
126 | 40 | def install_platform_event_handlers(app): | 52 | def install_platform_event_handlers(app, quit_kills_sd=False): |
127 | 41 | """Add code to catch cmd-Q.""" | 53 | """Add code to catch cmd-Q.""" |
128 | 42 | # on darwin, a menu item with 'quit' in its title is moved to | 54 | # on darwin, a menu item with 'quit' in its title is moved to |
129 | 43 | # the application menu and given the cmd-Q shortcut by Qt. If | 55 | # the application menu and given the cmd-Q shortcut by Qt. If |
130 | @@ -52,9 +64,41 @@ | |||
131 | 52 | 64 | ||
132 | 53 | quit_action = QtGui.QAction("quit", menubar, | 65 | quit_action = QtGui.QAction("quit", menubar, |
133 | 54 | triggered=lambda x: | 66 | triggered=lambda x: |
135 | 55 | handle_cmd_q(app, x)) | 67 | handle_cmd_q(app, |
136 | 68 | x, | ||
137 | 69 | quit_kills_sd)) | ||
138 | 56 | quit_action.setObjectName("darwin-cmd-q") | 70 | quit_action.setObjectName("darwin-cmd-q") |
139 | 57 | menu = menubar.addMenu("This string is not used.") | 71 | menu = menubar.addMenu("This string is not used.") |
140 | 58 | menu.addAction(quit_action) | 72 | menu.addAction(quit_action) |
141 | 59 | 73 | ||
142 | 60 | return menubar | 74 | return menubar |
143 | 75 | |||
144 | 76 | |||
145 | 77 | class MenubarIconLauncher(cache.Cache): | ||
146 | 78 | """Listens to status, launches the menubar app once it is safe to do so.""" | ||
147 | 79 | |||
148 | 80 | def __init__(self): | ||
149 | 81 | """Register as listener.""" | ||
150 | 82 | super(MenubarIconLauncher, self).__init__() | ||
151 | 83 | self.backend.add_status_changed_handler(self.handle_status_update) | ||
152 | 84 | |||
153 | 85 | def handle_status_update(self, result): | ||
154 | 86 | """Process updates, launch menu on non-error""" | ||
155 | 87 | |||
156 | 88 | if result[STATUS_KEY] == FILE_SYNC_ERROR: | ||
157 | 89 | logger.warning("not starting menu, file sync in error state") | ||
158 | 90 | return | ||
159 | 91 | |||
160 | 92 | self.start_menu_process() | ||
161 | 93 | self.backend.remove_status_changed_handler(self.handle_status_update) | ||
162 | 94 | |||
163 | 95 | def start_menu_process(self): | ||
164 | 96 | """Find and launch separate menu process.""" | ||
165 | 97 | if getattr(sys, 'frozen', None) is None: | ||
166 | 98 | logger.warning("Can not launch pyobjc menu from source, ignoring.") | ||
167 | 99 | return | ||
168 | 100 | menu_app_name = 'Ubuntu One Menu' | ||
169 | 101 | path = get_program_path(menu_app_name, | ||
170 | 102 | app_names={menu_app_name: | ||
171 | 103 | 'Ubuntu One Menu.app'}) | ||
172 | 104 | subprocess.Popen(path) | ||
173 | 61 | 105 | ||
174 | === modified file 'ubuntuone/controlpanel/gui/qt/main/tests/test_darwin.py' | |||
175 | --- ubuntuone/controlpanel/gui/qt/main/tests/test_darwin.py 2012-10-04 20:34:22 +0000 | |||
176 | +++ ubuntuone/controlpanel/gui/qt/main/tests/test_darwin.py 2012-11-30 18:08:22 +0000 | |||
177 | @@ -18,8 +18,12 @@ | |||
178 | 18 | 18 | ||
179 | 19 | from PyQt4 import QtGui | 19 | from PyQt4 import QtGui |
180 | 20 | 20 | ||
181 | 21 | import subprocess | ||
182 | 22 | import sys | ||
183 | 23 | |||
184 | 21 | from twisted.internet.defer import (inlineCallbacks, succeed) | 24 | from twisted.internet.defer import (inlineCallbacks, succeed) |
185 | 22 | 25 | ||
186 | 26 | from ubuntuone.controlpanel import backend | ||
187 | 23 | from ubuntuone.controlpanel.gui.qt import main | 27 | from ubuntuone.controlpanel.gui.qt import main |
188 | 24 | from ubuntuone.controlpanel.tests import TestCase | 28 | from ubuntuone.controlpanel.tests import TestCase |
189 | 25 | from ubuntuone.controlpanel.gui.tests import FakeSignal | 29 | from ubuntuone.controlpanel.gui.tests import FakeSignal |
190 | @@ -60,6 +64,28 @@ | |||
191 | 60 | raise Exception("exception") | 64 | raise Exception("exception") |
192 | 61 | 65 | ||
193 | 62 | 66 | ||
194 | 67 | class FakeBackend(object): | ||
195 | 68 | """Mock backend""" | ||
196 | 69 | |||
197 | 70 | def __init__(self): | ||
198 | 71 | """init""" | ||
199 | 72 | |||
200 | 73 | super(FakeBackend, self).__init__() | ||
201 | 74 | self.handlers = [] | ||
202 | 75 | |||
203 | 76 | def add_status_changed_handler(self, h): | ||
204 | 77 | """add handler""" | ||
205 | 78 | self.handlers.append(h) | ||
206 | 79 | |||
207 | 80 | def remove_status_changed_handler(self, h): | ||
208 | 81 | """remove handler """ | ||
209 | 82 | self.handlers.remove(h) | ||
210 | 83 | |||
211 | 84 | def clear(self): | ||
212 | 85 | """reset handlers""" | ||
213 | 86 | self.handlers = [] | ||
214 | 87 | |||
215 | 88 | |||
216 | 63 | class QuitTestCase(TestCase): | 89 | class QuitTestCase(TestCase): |
217 | 64 | """Test quit event handling.""" | 90 | """Test quit event handling.""" |
218 | 65 | 91 | ||
219 | @@ -73,13 +99,22 @@ | |||
220 | 73 | 99 | ||
221 | 74 | @inlineCallbacks | 100 | @inlineCallbacks |
222 | 75 | def test_cmd_q_func_quits_sd(self): | 101 | def test_cmd_q_func_quits_sd(self): |
224 | 76 | """Test that we call syncdaemontool.quit """ | 102 | """Test that we call syncdaemontool.quit when asked""" |
225 | 77 | self.patch(main.darwin, 'SyncDaemonTool', FakeSDTool) | 103 | self.patch(main.darwin, 'SyncDaemonTool', FakeSDTool) |
226 | 78 | 104 | ||
228 | 79 | yield main.darwin.handle_cmd_q(self.fake_app, None) | 105 | yield main.darwin.handle_cmd_q(self.fake_app, None, |
229 | 106 | should_quit_sd=True) | ||
230 | 80 | self.assertEqual(FakeSDTool.called, True) | 107 | self.assertEqual(FakeSDTool.called, True) |
231 | 81 | 108 | ||
232 | 82 | @inlineCallbacks | 109 | @inlineCallbacks |
233 | 110 | def test_cmd_q_func_doesnt_quit_sd(self): | ||
234 | 111 | """Test that we don't call syncdaemontool.quit by default""" | ||
235 | 112 | self.patch(main.darwin, 'SyncDaemonTool', FakeSDTool) | ||
236 | 113 | |||
237 | 114 | yield main.darwin.handle_cmd_q(self.fake_app, None) | ||
238 | 115 | self.assertEqual(FakeSDTool.called, False) | ||
239 | 116 | |||
240 | 117 | @inlineCallbacks | ||
241 | 83 | def test_cmd_q_func_ignores_exception(self): | 118 | def test_cmd_q_func_ignores_exception(self): |
242 | 84 | """Test that we keep going when SDT raises.""" | 119 | """Test that we keep going when SDT raises.""" |
243 | 85 | self.patch(main.darwin, 'SyncDaemonTool', FakeSDToolRaising) | 120 | self.patch(main.darwin, 'SyncDaemonTool', FakeSDToolRaising) |
244 | @@ -93,12 +128,76 @@ | |||
245 | 93 | class InstallEventHandlersTestCase(TestCase): | 128 | class InstallEventHandlersTestCase(TestCase): |
246 | 94 | """Test creating Qt menu items.""" | 129 | """Test creating Qt menu items.""" |
247 | 95 | 130 | ||
250 | 96 | def test_install_handlers_creates_action(self): | 131 | def test_install_handlers_creates_kill_action(self): |
251 | 97 | """Test menu items created""" | 132 | """Test creating menu item that will kill sd""" |
252 | 133 | self.patch(main.darwin, 'handle_cmd_q', | ||
253 | 134 | self._set_called) | ||
254 | 135 | app = QtGui.QApplication.instance() | ||
255 | 136 | k = dict(quit_kills_sd=True) | ||
256 | 137 | menubar = main.darwin.install_platform_event_handlers(app, **k) | ||
257 | 138 | quit_action = menubar.findChild(QtGui.QAction, "darwin-cmd-q") | ||
258 | 139 | quit_action.trigger() | ||
259 | 140 | self.assertEqual(self._called, ((app, False, True), {})) | ||
260 | 141 | |||
261 | 142 | def test_install_handlers_creates_nonkill_action(self): | ||
262 | 143 | """Test creating menu item that will not kill sd""" | ||
263 | 98 | self.patch(main.darwin, 'handle_cmd_q', | 144 | self.patch(main.darwin, 'handle_cmd_q', |
264 | 99 | self._set_called) | 145 | self._set_called) |
265 | 100 | app = QtGui.QApplication.instance() | 146 | app = QtGui.QApplication.instance() |
266 | 101 | menubar = main.darwin.install_platform_event_handlers(app) | 147 | menubar = main.darwin.install_platform_event_handlers(app) |
267 | 102 | quit_action = menubar.findChild(QtGui.QAction, "darwin-cmd-q") | 148 | quit_action = menubar.findChild(QtGui.QAction, "darwin-cmd-q") |
268 | 103 | quit_action.trigger() | 149 | quit_action.trigger() |
270 | 104 | self.assertEqual(self._called, ((app, False), {})) | 150 | self.assertEqual(self._called, ((app, False, False), {})) |
271 | 151 | |||
272 | 152 | |||
273 | 153 | class LauncherTestCase(TestCase): | ||
274 | 154 | """Test pyobjc menu launcher.""" | ||
275 | 155 | |||
276 | 156 | @inlineCallbacks | ||
277 | 157 | def setUp(self): | ||
278 | 158 | """Set up launcher and patches""" | ||
279 | 159 | yield super(LauncherTestCase, self).setUp() | ||
280 | 160 | |||
281 | 161 | self.patch(backend, 'ControlBackend', FakeBackend) | ||
282 | 162 | self.patch(main.darwin, 'get_program_path', | ||
283 | 163 | lambda a, **kw: 'testpath') | ||
284 | 164 | self.addCleanup(lambda: self.launcher.backend.clear()) | ||
285 | 165 | |||
286 | 166 | self.launcher = main.darwin.MenubarIconLauncher() | ||
287 | 167 | |||
288 | 168 | def test_add_on_init(self): | ||
289 | 169 | """Test adding to handler.""" | ||
290 | 170 | self.assertEqual(self.launcher.backend.handlers, | ||
291 | 171 | [self.launcher.handle_status_update]) | ||
292 | 172 | |||
293 | 173 | def test_handle_status_update_error(self): | ||
294 | 174 | """Test doing nothing on error in handle_status_update""" | ||
295 | 175 | self.patch(self.launcher, 'start_menu_process', self._set_called) | ||
296 | 176 | self.launcher.handle_status_update({backend.STATUS_KEY: | ||
297 | 177 | backend.FILE_SYNC_ERROR}) | ||
298 | 178 | self.assertEqual(self._called, False) | ||
299 | 179 | |||
300 | 180 | def test_handle_status_update(self): | ||
301 | 181 | """Test calling start_menu_process and removing handler""" | ||
302 | 182 | self.patch(self.launcher, 'start_menu_process', self._set_called) | ||
303 | 183 | self.launcher.handle_status_update({backend.STATUS_KEY: 'copacetic'}) | ||
304 | 184 | self.assertEqual(self._called, ((), {})) | ||
305 | 185 | self.assertEqual(self.launcher.backend.handlers, []) | ||
306 | 186 | |||
307 | 187 | def test_start_menu_process_nonfrozen(self): | ||
308 | 188 | """Start does nothing when not frozen.""" | ||
309 | 189 | sys.frozen = None | ||
310 | 190 | self.addCleanup(delattr, sys, 'frozen') | ||
311 | 191 | |||
312 | 192 | self.patch(subprocess, 'Popen', self._set_called) | ||
313 | 193 | self.launcher.start_menu_process() | ||
314 | 194 | self.assertEqual(self._called, False) | ||
315 | 195 | |||
316 | 196 | def test_start_menu_process_frozen(self): | ||
317 | 197 | """Start launches menu when frozen.""" | ||
318 | 198 | sys.frozen = 'macosx' | ||
319 | 199 | self.addCleanup(delattr, sys, 'frozen') | ||
320 | 200 | |||
321 | 201 | self.patch(subprocess, 'Popen', self._set_called) | ||
322 | 202 | self.launcher.start_menu_process() | ||
323 | 203 | self.assertEqual(self._called, (('testpath',), {})) | ||
324 | 105 | 204 | ||
325 | === modified file 'ubuntuone/controlpanel/gui/qt/main/tests/test_main.py' | |||
326 | --- ubuntuone/controlpanel/gui/qt/main/tests/test_main.py 2012-10-31 19:32:18 +0000 | |||
327 | +++ ubuntuone/controlpanel/gui/qt/main/tests/test_main.py 2012-11-30 18:08:22 +0000 | |||
328 | @@ -137,7 +137,7 @@ | |||
329 | 137 | self.patch(main.source, "main_start", lambda app: None) | 137 | self.patch(main.source, "main_start", lambda app: None) |
330 | 138 | self.patch(QtCore, "QTranslator", lambda: self.translator) | 138 | self.patch(QtCore, "QTranslator", lambda: self.translator) |
331 | 139 | self.patch(main, 'install_platform_event_handlers', | 139 | self.patch(main, 'install_platform_event_handlers', |
333 | 140 | lambda app: None) | 140 | lambda app, **kwargs: None) |
334 | 141 | 141 | ||
335 | 142 | self.qt4reactor_installed = False | 142 | self.qt4reactor_installed = False |
336 | 143 | 143 | ||
337 | @@ -194,11 +194,11 @@ | |||
338 | 194 | {'minimized': True, 'with_icon': False, 'installer': False}) | 194 | {'minimized': True, 'with_icon': False, 'installer': False}) |
339 | 195 | 195 | ||
340 | 196 | def test_darwin_defult_is_with_icon(self): | 196 | def test_darwin_defult_is_with_icon(self): |
342 | 197 | """On Darwin, the default is to show the icon.""" | 197 | """On Darwin, the default is not to show the icon.""" |
343 | 198 | self.patch(sys, 'platform', 'darwin') | 198 | self.patch(sys, 'platform', 'darwin') |
344 | 199 | main.main([sys.argv[0]]) | 199 | main.main([sys.argv[0]]) |
345 | 200 | self.assertEqual(self.start.args[1], | 200 | self.assertEqual(self.start.args[1], |
347 | 201 | {'minimized': False, 'with_icon': True, 'installer': False}) | 201 | {'minimized': False, 'with_icon': False, 'installer': False}) |
348 | 202 | 202 | ||
349 | 203 | def test_not_darwin_defult_is_with_icon(self): | 203 | def test_not_darwin_defult_is_with_icon(self): |
350 | 204 | """On Not-darwin, the default is to not show the icon.""" | 204 | """On Not-darwin, the default is to not show the icon.""" |
351 | @@ -215,7 +215,7 @@ | |||
352 | 215 | {'minimized': True, 'with_icon': False, 'installer': False}) | 215 | {'minimized': True, 'with_icon': False, 'installer': False}) |
353 | 216 | 216 | ||
354 | 217 | def test_with_icon_option(self): | 217 | def test_with_icon_option(self): |
356 | 218 | """Ensure the --minimized option is parsed and passed correctly.""" | 218 | """Ensure the --with-icon option is parsed and passed correctly.""" |
357 | 219 | self.patch(sys, 'platform', 'not-darwin') | 219 | self.patch(sys, 'platform', 'not-darwin') |
358 | 220 | main.main([sys.argv[0], "--with-icon"]) | 220 | main.main([sys.argv[0], "--with-icon"]) |
359 | 221 | self.assertEqual(self.start.args[1], | 221 | self.assertEqual(self.start.args[1], |
360 | @@ -308,10 +308,20 @@ | |||
361 | 308 | main.main([sys.argv[0]], install_reactor_darwin=False) | 308 | main.main([sys.argv[0]], install_reactor_darwin=False) |
362 | 309 | self.assertEqual(self._called, ((), {})) | 309 | self.assertEqual(self._called, ((), {})) |
363 | 310 | 310 | ||
366 | 311 | def test_install_event_handlers(self): | 311 | def test_install_event_handlers_darwin(self): |
367 | 312 | """Test that install_platform_event_handlers is called.""" | 312 | """Test that install_platform_event_handlers is called on darwin.""" |
368 | 313 | self.patch(sys, 'platform', 'darwin') | ||
369 | 313 | self.patch(main, 'install_platform_event_handlers', | 314 | self.patch(main, 'install_platform_event_handlers', |
370 | 314 | self._set_called) | 315 | self._set_called) |
371 | 315 | 316 | ||
372 | 316 | main.main([sys.argv[0]], install_reactor_darwin=False) | 317 | main.main([sys.argv[0]], install_reactor_darwin=False) |
374 | 317 | self.assertEqual(self._called, ((self.app,), {})) | 318 | self.assertEqual(self._called, ((self.app,), {'quit_kills_sd': False})) |
375 | 319 | |||
376 | 320 | def test_install_event_handlers_non_darwin(self): | ||
377 | 321 | """Test install_platform_event_handlers is called on not-darwin.""" | ||
378 | 322 | self.patch(sys, 'platform', 'not-darwin') | ||
379 | 323 | self.patch(main, 'install_platform_event_handlers', | ||
380 | 324 | self._set_called) | ||
381 | 325 | |||
382 | 326 | main.main([sys.argv[0], '--with-icon'], install_reactor_darwin=False) | ||
383 | 327 | self.assertEqual(self._called, ((self.app,), {'quit_kills_sd': False})) | ||
384 | 318 | 328 | ||
385 | === modified file 'ubuntuone/controlpanel/tests/test_backend.py' | |||
386 | --- ubuntuone/controlpanel/tests/test_backend.py 2012-11-29 20:15:08 +0000 | |||
387 | +++ ubuntuone/controlpanel/tests/test_backend.py 2012-11-30 18:08:22 +0000 | |||
388 | @@ -1485,6 +1485,32 @@ | |||
389 | 1485 | self.assertEqual(self.call_count_b, 1) | 1485 | self.assertEqual(self.call_count_b, 1) |
390 | 1486 | self.assertEqual(self.call_count_a, 1) | 1486 | self.assertEqual(self.call_count_a, 1) |
391 | 1487 | 1487 | ||
392 | 1488 | def test_remove_status_handler(self): | ||
393 | 1489 | """Test removing a handler.""" | ||
394 | 1490 | self.call_count_a = 0 | ||
395 | 1491 | self.call_count_b = 0 | ||
396 | 1492 | |||
397 | 1493 | def inc_a(status): | ||
398 | 1494 | """Fake status handler #1""" | ||
399 | 1495 | self.call_count_a += 1 | ||
400 | 1496 | |||
401 | 1497 | def inc_b(status): | ||
402 | 1498 | """Fake status handler #2""" | ||
403 | 1499 | self.call_count_b += 1 | ||
404 | 1500 | |||
405 | 1501 | self.addCleanup(delattr, self, "call_count_a") | ||
406 | 1502 | self.addCleanup(delattr, self, "call_count_b") | ||
407 | 1503 | |||
408 | 1504 | self.be.add_status_changed_handler(inc_a) | ||
409 | 1505 | self.be.add_status_changed_handler(inc_b) | ||
410 | 1506 | |||
411 | 1507 | self.be.sd_client.status_changed_handler({}) | ||
412 | 1508 | self.be.remove_status_changed_handler(inc_b) | ||
413 | 1509 | self.be.sd_client.status_changed_handler({}) | ||
414 | 1510 | |||
415 | 1511 | self.assertEqual(self.call_count_b, 1) | ||
416 | 1512 | self.assertEqual(self.call_count_a, 2) | ||
417 | 1513 | |||
418 | 1488 | 1514 | ||
419 | 1489 | class BackendSyncStatusIfDisabledTestCase(BackendSyncStatusTestCase): | 1515 | class BackendSyncStatusIfDisabledTestCase(BackendSyncStatusTestCase): |
420 | 1490 | """Syncdaemon state for the backend when file sync is disabled.""" | 1516 | """Syncdaemon state for the backend when file sync is disabled.""" |
+1
"Let's put a smile on that face!" [The Dark Knight]