Merge pull request #1324 from ogayot/remove_overlay_no_overlay_ok

ui: avoid crashing when removing overlay that does not exist
This commit is contained in:
Olivier Gayot 2022-12-12 09:09:19 +01:00 committed by GitHub
commit e47f667e15
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 42 additions and 8 deletions

View File

@ -297,5 +297,7 @@ class SSHView(BaseView):
ConfirmSSHKeys(self, ssh_data, identities)) ConfirmSSHKeys(self, ssh_data, identities))
def fetching_ssh_keys_failed(self, msg, stderr): def fetching_ssh_keys_failed(self, msg, stderr):
self.remove_overlay() # FIXME in answers-based runs, the overlay does not exist so we pass
# not_found_ok=True.
self.remove_overlay(not_found_ok=True)
self.show_stretchy_overlay(SomethingFailed(self, msg, stderr)) self.show_stretchy_overlay(SomethingFailed(self, msg, stderr))

View File

@ -16,7 +16,7 @@
import urwid import urwid
from subiquitycore.tests import SubiTestCase from subiquitycore.tests import SubiTestCase
from subiquitycore.view import BaseView from subiquitycore.view import BaseView, OverlayNotFoundError
from subiquitycore.ui.stretchy import Stretchy, StretchyOverlay from subiquitycore.ui.stretchy import Stretchy, StretchyOverlay
from subiquitycore.ui.utils import undisabled from subiquitycore.ui.utils import undisabled
@ -93,3 +93,20 @@ class TestBaseView(SubiTestCase):
bv.remove_overlay() bv.remove_overlay()
self.assertTrue(c.was_closed) self.assertTrue(c.was_closed)
self.assertEqual(self.get_stretchy_chain(bv), [b, a]) self.assertEqual(self.get_stretchy_chain(bv), [b, a])
def test_remove_overlay_not_found(self):
bv, a, b, c = self.make_view_with_overlays()
bv.remove_overlay(not_found_ok=False)
bv.remove_overlay(not_found_ok=False)
bv.remove_overlay(not_found_ok=False)
# At this point, there is no more overlay.
with self.assertRaises(OverlayNotFoundError):
bv.remove_overlay(not_found_ok=False)
bv.remove_overlay(not_found_ok=True)
with self.assertRaises(OverlayNotFoundError):
bv.remove_overlay(stretchy=a, not_found_ok=False)
bv.remove_overlay(stretchy=a, not_found_ok=True)

View File

@ -38,6 +38,10 @@ from subiquitycore.ui.utils import disabled, undisabled
log = logging.getLogger('subiquitycore.view') log = logging.getLogger('subiquitycore.view')
class OverlayNotFoundError(Exception):
""" Exception to raise when trying to remove a non-existent overlay. """
class BaseView(WidgetWrap): class BaseView(WidgetWrap):
def local_help(self): def local_help(self):
@ -78,7 +82,9 @@ class BaseView(WidgetWrap):
stretchy.opened() stretchy.opened()
self._w = StretchyOverlay(disabled(self._w), stretchy) self._w = StretchyOverlay(disabled(self._w), stretchy)
def remove_overlay(self, stretchy=None): def remove_overlay(self, stretchy=None,
*, not_found_ok=False) -> None:
""" Remove (frontmost) overlay from the view. """
if stretchy is not None: if stretchy is not None:
one_above = None one_above = None
cur = self._w cur = self._w
@ -95,10 +101,20 @@ class BaseView(WidgetWrap):
one_above = cur one_above = cur
cur = undisabled(cur.bottom_w) cur = undisabled(cur.bottom_w)
else: else:
if not not_found_ok:
raise OverlayNotFoundError
else:
try:
behind_overlay = self._w.bottom_w
except AttributeError:
if not_found_ok:
return
raise OverlayNotFoundError
if isinstance(self._w, StretchyOverlay): if isinstance(self._w, StretchyOverlay):
emit_signal(self._w.stretchy, 'closed') emit_signal(self._w.stretchy, 'closed')
self._w.stretchy.closed() self._w.stretchy.closed()
self._w = undisabled(self._w.bottom_w) self._w = undisabled(behind_overlay)
def cancel(self): def cancel(self):
pass pass
@ -106,10 +122,9 @@ class BaseView(WidgetWrap):
def keypress(self, size, key): def keypress(self, size, key):
key = super().keypress(size, key) key = super().keypress(size, key)
if key == 'esc': if key == 'esc':
if hasattr(self._w, 'bottom_w'): try:
self.remove_overlay() self.remove_overlay(not_found_ok=False)
return None except OverlayNotFoundError:
else:
self.cancel() self.cancel()
return None return None
return key return key