2024-02-08 10:24:38 +00:00
|
|
|
import asyncio
|
2017-11-07 22:59:13 +00:00
|
|
|
import re
|
2024-02-08 10:24:38 +00:00
|
|
|
from typing import Type
|
2023-07-25 21:26:25 +00:00
|
|
|
|
2017-11-07 22:59:13 +00:00
|
|
|
import urwid
|
|
|
|
|
2024-02-08 10:24:38 +00:00
|
|
|
from subiquitycore.ui.frame import SubiquityCoreUI
|
|
|
|
from subiquitycore.ui.stretchy import Stretchy, StretchyOverlay
|
2018-07-06 02:44:19 +00:00
|
|
|
|
2018-05-21 20:39:31 +00:00
|
|
|
|
2017-12-21 01:41:05 +00:00
|
|
|
def find_with_pred(w, pred, return_path=False):
|
|
|
|
def _walk(w, path):
|
2018-05-01 00:17:53 +00:00
|
|
|
if not isinstance(w, urwid.Widget):
|
2018-05-21 20:39:31 +00:00
|
|
|
raise RuntimeError("_walk walked to non-widget %r via %r" % (w, path))
|
2017-11-07 22:59:13 +00:00
|
|
|
if pred(w):
|
2017-12-21 01:41:05 +00:00
|
|
|
return w, path
|
2017-11-07 22:59:13 +00:00
|
|
|
if hasattr(w, "_wrapped_widget"):
|
2017-12-21 01:41:05 +00:00
|
|
|
return _walk(w._wrapped_widget, (w,) + path)
|
2017-11-07 22:59:13 +00:00
|
|
|
if hasattr(w, "original_widget"):
|
2017-12-21 01:41:05 +00:00
|
|
|
return _walk(w.original_widget, (w,) + path)
|
2017-11-07 22:59:13 +00:00
|
|
|
if isinstance(w, urwid.ListBox):
|
|
|
|
for w in w.body:
|
2017-12-21 01:41:05 +00:00
|
|
|
r, p = _walk(w, (w,) + path)
|
2017-11-07 22:59:13 +00:00
|
|
|
if r:
|
2017-12-21 01:41:05 +00:00
|
|
|
return r, p
|
2018-05-01 00:17:53 +00:00
|
|
|
elif isinstance(w, urwid.Frame):
|
|
|
|
for w, _ in w.contents.values():
|
|
|
|
r, p = _walk(w, (w,) + path)
|
|
|
|
if r:
|
|
|
|
return r, p
|
2017-11-07 22:59:13 +00:00
|
|
|
elif hasattr(w, "contents"):
|
|
|
|
contents = w.contents
|
|
|
|
for w, _ in contents:
|
2017-12-21 01:41:05 +00:00
|
|
|
r, p = _walk(w, (w,) + path)
|
2017-11-07 22:59:13 +00:00
|
|
|
if r:
|
2017-12-21 01:41:05 +00:00
|
|
|
return r, p
|
2018-07-06 02:44:19 +00:00
|
|
|
elif isinstance(w, StretchyOverlay):
|
|
|
|
r, p = _walk(w.top_w, (w,) + path)
|
|
|
|
if r:
|
|
|
|
return r, p
|
2017-12-21 01:41:05 +00:00
|
|
|
return None, None
|
2023-07-25 21:26:25 +00:00
|
|
|
|
2017-12-21 01:41:05 +00:00
|
|
|
r, p = _walk(w, ())
|
|
|
|
if return_path:
|
|
|
|
return r, p
|
|
|
|
else:
|
|
|
|
return r
|
2017-11-07 22:59:13 +00:00
|
|
|
|
2018-05-21 20:39:31 +00:00
|
|
|
|
2017-12-21 01:41:05 +00:00
|
|
|
def find_button_matching(w, pat, return_path=False):
|
2017-11-07 22:59:13 +00:00
|
|
|
def pred(w):
|
|
|
|
return isinstance(w, urwid.Button) and re.match(pat, w.label)
|
2023-07-25 21:26:25 +00:00
|
|
|
|
2017-12-21 01:41:05 +00:00
|
|
|
return find_with_pred(w, pred, return_path)
|
2017-11-07 22:59:13 +00:00
|
|
|
|
2018-05-21 20:39:31 +00:00
|
|
|
|
2017-11-07 22:59:13 +00:00
|
|
|
def click(but):
|
|
|
|
but._emit("click")
|
|
|
|
|
2018-05-21 20:39:31 +00:00
|
|
|
|
2017-11-07 22:59:13 +00:00
|
|
|
def keypress(w, key, size=(30, 1)):
|
|
|
|
w.keypress(size, key)
|
|
|
|
|
2018-05-21 20:39:31 +00:00
|
|
|
|
2017-11-07 22:59:13 +00:00
|
|
|
def get_focus_path(w):
|
|
|
|
path = []
|
|
|
|
while True:
|
|
|
|
path.append(w)
|
2018-05-21 20:39:31 +00:00
|
|
|
if isinstance(w, urwid.ListBox) and (w.set_focus_pending == "first selectable"):
|
2017-12-03 21:29:06 +00:00
|
|
|
for w2 in w.body:
|
|
|
|
if w2.selectable():
|
|
|
|
w = w2
|
|
|
|
break
|
|
|
|
else:
|
|
|
|
break
|
2017-11-07 22:59:13 +00:00
|
|
|
if w.focus is not None:
|
|
|
|
w = w.focus
|
|
|
|
elif hasattr(w, "_wrapped_widget"):
|
|
|
|
w = w._wrapped_widget
|
|
|
|
elif hasattr(w, "original_widget"):
|
|
|
|
w = w.original_widget
|
|
|
|
else:
|
|
|
|
break
|
|
|
|
return path
|
2017-12-10 20:52:36 +00:00
|
|
|
|
2018-05-21 20:39:31 +00:00
|
|
|
|
2017-12-10 20:52:36 +00:00
|
|
|
def enter_data(form, data):
|
|
|
|
for k, v in data.items():
|
2019-05-28 10:59:30 +00:00
|
|
|
bf = getattr(form, k)
|
|
|
|
assert bf.enabled, "%s is not enabled" % (k,)
|
|
|
|
bf.value = v
|
2024-02-08 10:24:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def wait_for_overlay(
|
|
|
|
ui: SubiquityCoreUI, overlay_type: Type[Stretchy], *, timeout=None, step=0.01
|
|
|
|
) -> Stretchy:
|
|
|
|
"""Wait until an overlay of the specified type gets displayed on the
|
|
|
|
screen and return it. If timeout is hit before the overlay is displayed, an
|
|
|
|
asyncio.TimeoutError will be raised. When timeout is set to None, we will
|
|
|
|
wait forever."""
|
|
|
|
if timeout is not None:
|
|
|
|
task = wait_for_overlay(ui, overlay_type)
|
|
|
|
return await asyncio.wait_for(task, timeout=timeout)
|
|
|
|
|
|
|
|
while True:
|
|
|
|
try:
|
|
|
|
stretchy = ui.body._w.stretchy
|
|
|
|
except AttributeError:
|
|
|
|
pass
|
|
|
|
else:
|
|
|
|
if isinstance(stretchy, overlay_type):
|
|
|
|
return stretchy
|
|
|
|
await asyncio.sleep(step)
|