Merge lp:~mterry/update-manager/stop-update into lp:update-manager

Proposed by Michael Terry
Status: Merged
Merged at revision: 2538
Proposed branch: lp:~mterry/update-manager/stop-update
Merge into: lp:update-manager
Diff against target: 389 lines (+173/-65)
7 files modified
UpdateManager/Dialogs.py (+12/-0)
UpdateManager/UpdateManager.py (+31/-14)
UpdateManager/UpdateProgress.py (+1/-6)
UpdateManager/UpdatesAvailable.py (+36/-36)
UpdateManager/backend/InstallBackendAptdaemon.py (+3/-0)
data/gtkbuilder/UpdateManager.ui (+40/-9)
tests/test_stop_update.py (+50/-0)
To merge this branch: bzr merge lp:~mterry/update-manager/stop-update
Reviewer Review Type Date Requested Status
Michael Vogt (community) Approve
Review via email: mp+120318@code.launchpad.net

Description of the change

mpt added some dialogs recently to the update-manager experience if the user stops an apt update. See https://wiki.ubuntu.com/SoftwareUpdates#Launching

This branch implements those changes (and does a little minor cleanup in UpdatesAvailable by dropping some support for num_updates == 0 which shouldn't ever happen now, after the redesign).

To post a comment you must log in.
Revision history for this message
Michael Vogt (mvo) wrote :

On Mon, Aug 20, 2012 at 02:45:38AM -0000, Michael Terry wrote:
[..]
> @@ -162,7 +163,7 @@
>
> self._start_pane(UpdateProgress(self))
>
> - def start_available(self):
> + def start_available(self, cancelled_update = False):
> self._look_busy()
> self.refresh_cache()
[..]
> === modified file 'UpdateManager/UpdatesAvailable.py'
> --- UpdateManager/UpdatesAvailable.py 2012-06-28 00:09:03 +0000
> +++ UpdateManager/UpdatesAvailable.py 2012-08-20 02:44:22 +0000
> @@ -81,7 +81,7 @@
>
> class UpdatesAvailable(SimpleGtkbuilderApp):
>
> - def __init__(self, app):
> + def __init__(self, app, header = None, desc = None):
> self.window_main = app
> self.datadir = app.datadir
> self.options = app.options

pep8 suggests to use "cancelled_update=False" (no space around the
"=").

Otherwise this looks good, would be nice to have a test, but to get it
in before UIF I'm fine with merging it now.

Thanks,
 Michael

Revision history for this message
Michael Vogt (mvo) :
review: Approve
2536. By Michael Terry

merge from trunk

2537. By Michael Terry

merge from trunk again

2538. By Michael Terry

fix pep8 and pyflakes issues

2539. By Michael Terry

adjust code to make the UpdateManager class slightly easier to unit test; add tests for stop-update code

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'UpdateManager/Dialogs.py'
--- UpdateManager/Dialogs.py 2012-07-06 19:30:02 +0000
+++ UpdateManager/Dialogs.py 2012-08-24 23:06:30 +0000
@@ -106,6 +106,18 @@
106 self.label_desc.set_visible(bool(label))106 self.label_desc.set_visible(bool(label))
107107
108108
109class StoppedUpdatesDialog(Dialog):
110 def __init__(self, window_main):
111 Dialog.__init__(self, window_main)
112 self.set_header(_("You stopped the check for updates."))
113 self.add_settings_button()
114 self.add_button(_("_Check Again"), self.check)
115 self.focus_button = self.add_button(Gtk.STOCK_OK, self.close)
116
117 def check(self):
118 self.window_main.start_update()
119
120
109class NoUpdatesDialog(Dialog):121class NoUpdatesDialog(Dialog):
110 def __init__(self, window_main):122 def __init__(self, window_main):
111 Dialog.__init__(self, window_main)123 Dialog.__init__(self, window_main)
112124
=== modified file 'UpdateManager/UpdateManager.py'
--- UpdateManager/UpdateManager.py 2012-08-24 20:20:11 +0000
+++ UpdateManager/UpdateManager.py 2012-08-24 23:06:30 +0000
@@ -46,6 +46,7 @@
46 ErrorDialog,46 ErrorDialog,
47 NeedRestartDialog,47 NeedRestartDialog,
48 NoUpdatesDialog,48 NoUpdatesDialog,
49 StoppedUpdatesDialog,
49 PartialUpgradeDialog,50 PartialUpgradeDialog,
50 UnsupportedDialog)51 UnsupportedDialog)
51from .InstallProgress import InstallProgress52from .InstallProgress import InstallProgress
@@ -162,18 +163,36 @@
162163
163 self._start_pane(UpdateProgress(self))164 self._start_pane(UpdateProgress(self))
164165
165 def start_available(self):166 def start_available(self, cancelled_update=False):
166 self._look_busy()167 self._look_busy()
167 self.refresh_cache()168 self.refresh_cache()
168169
169 if self.cache.install_count == 0:170 pane = self._make_available_pane(self.cache.install_count,
171 os.path.exists(REBOOT_REQUIRED_FILE),
172 cancelled_update)
173 self._start_pane(pane)
174
175 def _make_available_pane(self, install_count, need_reboot,
176 cancelled_update):
177 if install_count == 0:
170 # Need Restart > New Release > No Updates178 # Need Restart > New Release > No Updates
171 if os.path.exists(REBOOT_REQUIRED_FILE):179 if need_reboot:
172 self._start_pane(NeedRestartDialog(self))180 return NeedRestartDialog(self)
173 elif not self._check_meta_release():181 pane = self._check_meta_release()
174 self._start_pane(NoUpdatesDialog(self))182 if pane:
183 return pane
184 elif cancelled_update:
185 return StoppedUpdatesDialog(self)
186 else:
187 return NoUpdatesDialog(self)
175 else:188 else:
176 self._start_pane(UpdatesAvailable(self))189 header = None
190 desc = None
191 if cancelled_update:
192 header = _("You stopped the check for updates.")
193 desc = _("Updated software is available from "
194 "a previous check.")
195 return UpdatesAvailable(self, header, desc)
177196
178 def start_install(self):197 def start_install(self):
179 self._start_pane(InstallProgress(self))198 self._start_pane(InstallProgress(self))
@@ -192,7 +211,7 @@
192211
193 def _check_meta_release(self):212 def _check_meta_release(self):
194 if self.meta_release is None:213 if self.meta_release is None:
195 return False214 return None
196215
197 if self.meta_release.downloading:216 if self.meta_release.downloading:
198 # Block until we get an answer217 # Block until we get an answer
@@ -202,22 +221,20 @@
202 # Check if there is anything to upgrade to or a known-broken upgrade221 # Check if there is anything to upgrade to or a known-broken upgrade
203 next = self.meta_release.upgradable_to222 next = self.meta_release.upgradable_to
204 if not next or next.upgrade_broken:223 if not next or next.upgrade_broken:
205 return False224 return None
206225
207 # Check for end-of-life226 # Check for end-of-life
208 if self.meta_release.no_longer_supported:227 if self.meta_release.no_longer_supported:
209 self._start_pane(UnsupportedDialog(self, self.meta_release))228 return UnsupportedDialog(self, self.meta_release)
210 return True
211229
212 # Check for new fresh release230 # Check for new fresh release
213 settings = Gio.Settings("com.ubuntu.update-manager")231 settings = Gio.Settings("com.ubuntu.update-manager")
214 if (self.meta_release.new_dist and232 if (self.meta_release.new_dist and
215 (self.options.check_dist_upgrades or233 (self.options.check_dist_upgrades or
216 settings.get_boolean("check-dist-upgrades"))):234 settings.get_boolean("check-dist-upgrades"))):
217 self._start_pane(DistUpgradeDialog(self, self.meta_release))235 return DistUpgradeDialog(self, self.meta_release)
218 return True
219236
220 return False237 return None
221238
222 def _meta_release_wait_idle(self):239 def _meta_release_wait_idle(self):
223 # 'downloading' is changed in a thread, but the signal240 # 'downloading' is changed in a thread, but the signal
224241
=== modified file 'UpdateManager/UpdateProgress.py'
--- UpdateManager/UpdateProgress.py 2012-06-27 22:01:50 +0000
+++ UpdateManager/UpdateProgress.py 2012-08-24 23:06:30 +0000
@@ -35,7 +35,6 @@
35 DeprecationWarning)35 DeprecationWarning)
3636
37import os37import os
38import sys
3938
40from .backend import get_backend39from .backend import get_backend
4140
@@ -72,11 +71,7 @@
72 allow_sleep(self.sleep_dev, self.sleep_cookie)71 allow_sleep(self.sleep_dev, self.sleep_cookie)
73 self.sleep_cookie = self.sleep_dev = None72 self.sleep_cookie = self.sleep_dev = None
7473
75 # Either launch main dialog and continue or quit altogether74 self.window_main.start_available(not success)
76 if success:
77 self.window_main.start_available()
78 else:
79 sys.exit(0)
8075
81 def main(self):76 def main(self):
82 self.invoke_manager()77 self.invoke_manager()
8378
=== modified file 'UpdateManager/UpdatesAvailable.py'
--- UpdateManager/UpdatesAvailable.py 2012-06-28 00:09:03 +0000
+++ UpdateManager/UpdatesAvailable.py 2012-08-24 23:06:30 +0000
@@ -81,7 +81,7 @@
8181
82class UpdatesAvailable(SimpleGtkbuilderApp):82class UpdatesAvailable(SimpleGtkbuilderApp):
8383
84 def __init__(self, app):84 def __init__(self, app, header=None, desc=None):
85 self.window_main = app85 self.window_main = app
86 self.datadir = app.datadir86 self.datadir = app.datadir
87 self.options = app.options87 self.options = app.options
@@ -99,6 +99,9 @@
99 # workaround for LP: #94553699 # workaround for LP: #945536
100 self.clearing_store = False100 self.clearing_store = False
101101
102 self.custom_header = header
103 self.custom_desc = desc
104
102 self.button_close.grab_focus()105 self.button_close.grab_focus()
103 self.dl_size = 0106 self.dl_size = 0
104 self.connected = True107 self.connected = True
@@ -360,9 +363,6 @@
360 Gtk.MenuItem.new_with_mnemonic(_("_Deselect All"))363 Gtk.MenuItem.new_with_mnemonic(_("_Deselect All"))
361 item_select_none.connect("activate", self.select_none_updgrades)364 item_select_none.connect("activate", self.select_none_updgrades)
362 menu.append(item_select_none)365 menu.append(item_select_none)
363 num_updates = self.cache.install_count
364 if num_updates == 0:
365 item_select_none.set_property("sensitive", False)
366 item_select_all = Gtk.MenuItem.new_with_mnemonic(_("Select _All"))366 item_select_all = Gtk.MenuItem.new_with_mnemonic(_("Select _All"))
367 item_select_all.connect("activate", self.select_all_updgrades)367 item_select_all.connect("activate", self.select_all_updgrades)
368 menu.append(item_select_all)368 menu.append(item_select_all)
@@ -462,38 +462,38 @@
462 """activate or disable widgets and show dialog texts correspoding to462 """activate or disable widgets and show dialog texts correspoding to
463 the number of available updates"""463 the number of available updates"""
464 self.refresh_updates_count()464 self.refresh_updates_count()
465 num_updates = self.cache.install_count465
466466 text_header = None
467 if num_updates == 0:467 text_desc = None
468 text_header = _("The software on this computer is up to date.")468
469 self.label_downsize.set_text("\n")469 if self.custom_header is not None:
470 if self.cache.keep_count() == 0:470 text_header = self.custom_header
471 self.notebook_details.set_sensitive(False)471 text_desc = self.custom_desc
472 self.treeview_update.set_sensitive(False)472 # show different text on first run (UX team suggestion)
473 self.button_install.set_sensitive(False)473 elif self.settings.get_boolean("first-run"):
474 self.unity.set_install_menuitem_visible(False)474 flavor = self.window_main.meta_release.flavor_name
475 self.button_close.grab_default()475 version = self.window_main.meta_release.current_dist_version
476 self.textview_changes.get_buffer().set_text("")476 text_header = _("Updated software has been issued since %s %s "
477 self.textview_descr.get_buffer().set_text("")477 "was released. Do you want to install "
478 else:478 "it now?") % (flavor, version)
479 # show different text on first run (UX team suggestion)479 self.settings.set_boolean("first-run", False)
480 firstrun = self.settings.get_boolean("first-run")480 else:
481 if firstrun:481 text_header = _("Updated software is available for this "
482 flavor = self.window_main.meta_release.flavor_name482 "computer. Do you want to install it now?")
483 version = self.window_main.meta_release.current_dist_version483
484 text_header = _("Updated software has been issued since %s %s "484 self.notebook_details.set_sensitive(True)
485 "was released. Do you want to install "485 self.treeview_update.set_sensitive(True)
486 "it now?") % (flavor, version)486 self.button_install.grab_default()
487 self.settings.set_boolean("first-run", False)487 self.treeview_update.set_cursor(Gtk.TreePath.new_from_string("1"),
488 else:488 None, False)
489 text_header = _("Updated software is available for this "489 self.label_header.set_label(text_header)
490 "computer. Do you want to install it now?")490
491 self.notebook_details.set_sensitive(True)491 if text_desc is not None:
492 self.treeview_update.set_sensitive(True)492 self.label_desc.set_label(text_desc)
493 self.button_install.grab_default()493 self.label_desc.show()
494 self.treeview_update.set_cursor(Gtk.TreePath.new_from_string("1"),494 else:
495 None, False)495 self.label_desc.hide()
496 self.label_header.set_markup(text_header)496
497 return True497 return True
498498
499 # Before we shrink the window, capture the size499 # Before we shrink the window, capture the size
500500
=== modified file 'UpdateManager/backend/InstallBackendAptdaemon.py'
--- UpdateManager/backend/InstallBackendAptdaemon.py 2012-06-28 00:10:23 +0000
+++ UpdateManager/backend/InstallBackendAptdaemon.py 2012-08-24 23:06:30 +0000
@@ -125,6 +125,8 @@
125 progressbar_slot.add(progressbar)125 progressbar_slot.add(progressbar)
126126
127 self.button_cancel = AptCancelButton(trans)127 self.button_cancel = AptCancelButton(trans)
128 if action == self.UPDATE:
129 self.button_cancel.set_label(Gtk.STOCK_STOP)
128 self.button_cancel.show()130 self.button_cancel.show()
129 button_cancel_slot = builder.get_object("button_cancel_slot")131 button_cancel_slot = builder.get_object("button_cancel_slot")
130 button_cancel_slot.add(self.button_cancel)132 button_cancel_slot.add(self.button_cancel)
@@ -225,6 +227,7 @@
225 err_dia = AptErrorDialog(trans.error, self.window_main)227 err_dia = AptErrorDialog(trans.error, self.window_main)
226 err_dia.run()228 err_dia.run()
227 err_dia.hide()229 err_dia.hide()
230 sys.exit(0)
228 elif status == EXIT_SUCCESS and close_on_done:231 elif status == EXIT_SUCCESS and close_on_done:
229 sys.exit(0)232 sys.exit(0)
230 # tell unity to hide the progress again233 # tell unity to hide the progress again
231234
=== modified file 'data/gtkbuilder/UpdateManager.ui'
--- data/gtkbuilder/UpdateManager.ui 2012-06-18 21:14:43 +0000
+++ data/gtkbuilder/UpdateManager.ui 2012-08-24 23:06:30 +0000
@@ -40,16 +40,47 @@
40 </packing>40 </packing>
41 </child>41 </child>
42 <child>42 <child>
43 <object class="GtkLabel" id="label_header">43 <object class="GtkGrid" id="grid1">
44 <property name="visible">True</property>44 <property name="visible">True</property>
45 <property name="can_focus">False</property>45 <property name="can_focus">False</property>
46 <property name="xalign">0</property>46 <property name="margin_bottom">6</property>
47 <property name="use_underline">True</property>47 <property name="row_spacing">6</property>
48 <property name="wrap">True</property>48 <property name="column_spacing">12</property>
49 <attributes>49 <child>
50 <attribute name="weight" value="bold"/>50 <object class="GtkLabel" id="label_header">
51 <attribute name="scale" value="1.25"/>51 <property name="visible">True</property>
52 </attributes>52 <property name="can_focus">False</property>
53 <property name="hexpand">True</property>
54 <property name="xalign">0</property>
55 <property name="wrap">True</property>
56 <attributes>
57 <attribute name="weight" value="bold"/>
58 <attribute name="scale" value="1.25"/>
59 </attributes>
60 </object>
61 <packing>
62 <property name="left_attach">0</property>
63 <property name="top_attach">0</property>
64 <property name="width">1</property>
65 <property name="height">1</property>
66 </packing>
67 </child>
68 <child>
69 <object class="GtkLabel" id="label_desc">
70 <property name="can_focus">False</property>
71 <property name="no_show_all">True</property>
72 <property name="hexpand">True</property>
73 <property name="xalign">0</property>
74 <property name="wrap">True</property>
75 <property name="max_width_chars">20</property>
76 </object>
77 <packing>
78 <property name="left_attach">0</property>
79 <property name="top_attach">1</property>
80 <property name="width">1</property>
81 <property name="height">1</property>
82 </packing>
83 </child>
53 </object>84 </object>
54 <packing>85 <packing>
55 <property name="expand">False</property>86 <property name="expand">False</property>
@@ -462,8 +493,8 @@
462 <property name="receives_default">True</property>493 <property name="receives_default">True</property>
463 <property name="use_action_appearance">False</property>494 <property name="use_action_appearance">False</property>
464 <property name="use_stock">True</property>495 <property name="use_stock">True</property>
496 <accelerator key="Q" signal="clicked" modifiers="GDK_CONTROL_MASK"/>
465 <accelerator key="W" signal="clicked" modifiers="GDK_CONTROL_MASK"/>497 <accelerator key="W" signal="clicked" modifiers="GDK_CONTROL_MASK"/>
466 <accelerator key="Q" signal="clicked" modifiers="GDK_CONTROL_MASK"/>
467 </object>498 </object>
468 <packing>499 <packing>
469 <property name="expand">False</property>500 <property name="expand">False</property>
470501
=== added file 'tests/test_stop_update.py'
--- tests/test_stop_update.py 1970-01-01 00:00:00 +0000
+++ tests/test_stop_update.py 2012-08-24 23:06:30 +0000
@@ -0,0 +1,50 @@
1#!/usr/bin/python3
2# -*- Mode: Python; indent-tabs-mode: nil; tab-width: 4; coding: utf-8 -*-
3
4import logging
5import sys
6import unittest
7from mock import patch
8
9from UpdateManager.UpdateManager import UpdateManager
10from UpdateManager.UpdatesAvailable import UpdatesAvailable
11from UpdateManager import Dialogs
12
13import os
14CURDIR = os.path.dirname(os.path.abspath(__file__))
15
16
17class TestStopUpdate(unittest.TestCase):
18
19 def setUp(self):
20 patcher = patch('UpdateManager.UpdateManager.UpdateManager')
21 self.addCleanup(patcher.stop)
22 self.manager = patcher.start()
23 self.manager._check_meta_release.return_value = False
24 self.manager.datadir = os.path.join(CURDIR, '..', 'data')
25
26 def test_stop_no_updates(self):
27 # install_count, need_reboot, cancelled_update
28 p = UpdateManager._make_available_pane(self.manager, 0, False, True)
29 self.assertIsInstance(p, Dialogs.StoppedUpdatesDialog)
30
31 def test_no_stop_no_updates(self):
32 # install_count, need_reboot, cancelled_update
33 p = UpdateManager._make_available_pane(self.manager, 0, False, False)
34 self.assertNotIsInstance(p, Dialogs.StoppedUpdatesDialog)
35
36 def test_stop_updates(self):
37 # install_count, need_reboot, cancelled_update
38 p = UpdateManager._make_available_pane(self.manager, 1, False, True)
39 self.assertIsInstance(p, UpdatesAvailable)
40 self.assertIsNotNone(p.custom_header)
41
42 def test_no_stop_updates(self):
43 p = UpdateManager._make_available_pane(self.manager, 1, False, False)
44 self.assertIsInstance(p, UpdatesAvailable)
45 self.assertIsNone(p.custom_header)
46
47if __name__ == '__main__':
48 if len(sys.argv) > 1 and sys.argv[1] == "-v":
49 logging.basicConfig(level=logging.DEBUG)
50 unittest.main()

Subscribers

People subscribed via source and target branches

to status/vote changes: