diff --git a/console_conf/controllers/identity.py b/console_conf/controllers/identity.py index 445486f1..1a7fbe67 100644 --- a/console_conf/controllers/identity.py +++ b/console_conf/controllers/identity.py @@ -219,7 +219,7 @@ class IdentityController(BaseController): self.model.add_user(result) login_details_path = '.subiquity/login-details.txt' else: - self.loop.draw_screen() + self.app.urwid_loop.draw_screen() cp = run_command( ["snap", "create-user", "--sudoer", "--json", email]) if cp.returncode != 0: diff --git a/subiquity/controllers/error.py b/subiquity/controllers/error.py index 40041da4..253212a0 100644 --- a/subiquity/controllers/error.py +++ b/subiquity/controllers/error.py @@ -69,7 +69,7 @@ class Upload(metaclass=urwid.MetaSignals): cancelled = attr.ib(default=False) def start(self): - self.pipe_w = self.controller.loop.watch_pipe(self._progress) + self.pipe_w = self.controller.app.urwid_loop.watch_pipe(self._progress) def _progress(self, x): urwid.emit_signal(self, 'progress') @@ -81,7 +81,7 @@ class Upload(metaclass=urwid.MetaSignals): os.write(self.pipe_w, b'x') def stop(self): - self.controller.loop.remove_watch_pipe(self.pipe_w) + self.controller.app.urwid_loop.remove_watch_pipe(self.pipe_w) os.close(self.pipe_w) diff --git a/subiquity/ui/views/error.py b/subiquity/ui/views/error.py index d0cef933..3fc059ab 100644 --- a/subiquity/ui/views/error.py +++ b/subiquity/ui/views/error.py @@ -149,7 +149,7 @@ class ErrorReportStretchy(Stretchy): for n, b in self.btns.items(): self.btns[n] = Padding(b, width=w, align='center') - self.spinner = Spinner(app.loop, style='dots') + self.spinner = Spinner(app.aio_loop, style='dots') self.pile = Pile([]) self._report_changed() super().__init__("", [self.pile], 0, 0) diff --git a/subiquity/ui/views/filesystem/probing.py b/subiquity/ui/views/filesystem/probing.py index 22155aff..152e639e 100644 --- a/subiquity/ui/views/filesystem/probing.py +++ b/subiquity/ui/views/filesystem/probing.py @@ -41,7 +41,7 @@ class SlowProbing(BaseView): def __init__(self, controller): self.controller = controller - self.spinner = Spinner(loop=controller.loop, style="dots") + self.spinner = Spinner(loop=controller.app.aio_loop, style="dots") self.spinner.start() super().__init__(screen( [ diff --git a/subiquity/ui/views/installprogress.py b/subiquity/ui/views/installprogress.py index fefbd562..73f45d44 100644 --- a/subiquity/ui/views/installprogress.py +++ b/subiquity/ui/views/installprogress.py @@ -41,7 +41,7 @@ class MyLineBox(LineBox): class ProgressView(BaseView): def __init__(self, controller): self.controller = controller - self.spinner = Spinner(controller.loop) + self.spinner = Spinner(controller.app.aio_loop) self.reboot_btn = Toggleable(ok_btn( _("Reboot Now"), on_press=self.reboot)) diff --git a/subiquity/ui/views/keyboard.py b/subiquity/ui/views/keyboard.py index 1fa4411d..3a2fbfb7 100644 --- a/subiquity/ui/views/keyboard.py +++ b/subiquity/ui/views/keyboard.py @@ -285,8 +285,8 @@ class Detector: class ApplyingConfig(WidgetWrap): - def __init__(self, loop): - spinner = Spinner(loop, style='dots') + def __init__(self, aio_loop): + spinner = Spinner(aio_loop, style='dots') spinner.start() text = _("Applying config") # | text | @@ -465,7 +465,7 @@ class KeyboardView(BaseView): def really_done(self, setting): if setting != self.model.setting: - ac = ApplyingConfig(self.controller.loop) + ac = ApplyingConfig(self.controller.app.aio_loop) self.show_overlay(ac, width=ac.width, min_width=None) self.controller.done(setting) diff --git a/subiquity/ui/views/refresh.py b/subiquity/ui/views/refresh.py index 6cb34c24..8394f972 100644 --- a/subiquity/ui/views/refresh.py +++ b/subiquity/ui/views/refresh.py @@ -138,7 +138,7 @@ class RefreshView(BaseView): def __init__(self, controller): self.controller = controller - self.spinner = Spinner(self.controller.loop, style="dots") + self.spinner = Spinner(self.controller.app.aio_loop, style="dots") if self.controller.check_state == CheckState.UNKNOWN: self.check_state_checking() diff --git a/subiquity/ui/views/snaplist.py b/subiquity/ui/views/snaplist.py index a7b2194b..36d12cde 100644 --- a/subiquity/ui/views/snaplist.py +++ b/subiquity/ui/views/snaplist.py @@ -248,9 +248,9 @@ class SnapInfoView(WidgetWrap): class FetchingInfo(WidgetWrap): - def __init__(self, parent, snap, loop): + def __init__(self, parent, snap, aio_loop): self.parent = parent - self.spinner = Spinner(loop, style='dots') + self.spinner = Spinner(aio_loop, style='dots') self.spinner.start() self.closed = False text = _("Fetching info for {}").format(snap.name) @@ -342,7 +342,7 @@ class SnapCheckBox(CheckBox): self.loaded() return fi = FetchingInfo( - self.parent, self.snap, self.parent.controller.loop) + self.parent, self.snap, self.parent.controller.app.aio_loop) self.parent.show_overlay(fi, width=fi.width) schedule_task(self.wait(t, fi)) @@ -391,7 +391,7 @@ class SnapListView(BaseView): if t.done(): self.loaded() return - spinner = Spinner(self.controller.loop, style='dots') + spinner = Spinner(self.controller.app.aio_loop, style='dots') spinner.start() self._w = screen( [spinner], [ok_btn(label=_("Continue"), on_press=self.done)], diff --git a/subiquity/ui/views/ssh.py b/subiquity/ui/views/ssh.py index 93c6a0b0..167f286d 100644 --- a/subiquity/ui/views/ssh.py +++ b/subiquity/ui/views/ssh.py @@ -155,7 +155,7 @@ class SSHForm(Form): class FetchingSSHKeys(WidgetWrap): def __init__(self, parent): self.parent = parent - spinner = Spinner(parent.controller.loop, style='dots') + spinner = Spinner(parent.controller.app.aio_loop, style='dots') spinner.start() text = _("Fetching SSH keys...") button = cancel_btn(label=_("Cancel"), on_press=self.cancel) diff --git a/subiquity/ui/views/tests/test_installprogress.py b/subiquity/ui/views/tests/test_installprogress.py index 9978431e..c3a6dd06 100644 --- a/subiquity/ui/views/tests/test_installprogress.py +++ b/subiquity/ui/views/tests/test_installprogress.py @@ -11,7 +11,8 @@ class IdentityViewTests(unittest.TestCase): def make_view(self): controller = mock.create_autospec(spec=InstallProgressController) - controller.loop = None + controller.app = mock.Mock() + controller.app.aio_loop = None return ProgressView(controller) def test_initial_focus(self): diff --git a/subiquitycore/controller.py b/subiquitycore/controller.py index 7ba9932b..16d8e5fe 100644 --- a/subiquitycore/controller.py +++ b/subiquitycore/controller.py @@ -34,7 +34,6 @@ class BaseController(ABC): self.ui = app.ui self.signal = app.signal self.opts = app.opts - self.loop = app.loop self.app = app self.context = self.app.context.child(self.name, childlevel="DEBUG") self.answers = app.answers.get(self.name, {}) @@ -128,9 +127,7 @@ class BaseController(ABC): next(it) except StopIteration: return - self.loop.set_alarm_in( - delay, - lambda *args: self._run_iterator(it, delay/1.1)) + self.app.aio_loop.call_later(delay, self._run_iterator, it, delay/1.1) class RepeatedController(BaseController): diff --git a/subiquitycore/core.py b/subiquitycore/core.py index 9efc8237..8e1917b4 100644 --- a/subiquitycore/core.py +++ b/subiquitycore/core.py @@ -13,6 +13,7 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +import asyncio import fcntl import json import logging @@ -386,13 +387,14 @@ class Application: self.updated = os.path.exists(os.path.join(self.state_dir, 'updating')) self.signal = Signal() self.prober = prober - self.loop = None + self.aio_loop = asyncio.get_event_loop() + self.urwid_loop = None self.controllers = ControllerSet(self, self.controllers) self.context = Context.new(self) def run_command_in_foreground(self, cmd, before_hook=None, after_hook=None, **kw): - screen = self.loop.screen + screen = self.urwid_loop.screen # Calling screen.stop() sends the INPUT_DESCRIPTORS_CHANGED # signal. This calls _reset_input_descriptors() which calls @@ -528,14 +530,14 @@ class Application: ss = ScriptState() - def _run_script(*args): + def _run_script(): log.debug("running %s", ss.scripts[0]) exec(ss.scripts[0], ss.ns) if ss.waiting: return ss.scripts = ss.scripts[1:] if ss.scripts: - self.loop.set_alarm_in(0.01, _run_script) + self.aio_loop.call_soon(_run_script) def c(pat): but = view_helpers.find_button_matching(self.ui, '.*' + pat + '.*') @@ -552,7 +554,7 @@ class Application: def wait(delay, func=None): ss.waiting = True - def next(loop, user_data): + def next(): ss.waiting = False if func is not None: func() @@ -560,13 +562,13 @@ class Application: ss.scripts = ss.scripts[1:] if ss.scripts: _run_script() - self.loop.set_alarm_in(delay, next) + self.aio_loop.call_later(delay, next) ss.ns['c'] = c ss.ns['wait'] = wait ss.ns['ui'] = self.ui - self.loop.set_alarm_in(0.06, _run_script) + self.aio_loop.call_later(0.06, _run_script) def toggle_color(self): if self.is_color: @@ -575,14 +577,14 @@ class Application: else: new_palette = self.color_palette self.is_color = True - self.loop.screen.register_palette(new_palette) - self.loop.screen.clear() + self.urwid_loop.screen.register_palette(new_palette) + self.urwid_loop.screen.clear() def unhandled_input(self, key): if self.opts.dry_run and key == 'ctrl x': self.exit() elif key == 'f3': - self.loop.screen.clear() + self.urwid_loop.screen.clear() elif key in ['ctrl t', 'f4']: self.toggle_color() @@ -616,12 +618,12 @@ class Application: log.debug("Application.run") screen = make_screen(self.COLORS, self.is_linux_tty, self.opts.ascii) - self.loop = urwid.MainLoop( + self.urwid_loop = urwid.MainLoop( self.ui, palette=self.color_palette, screen=screen, handle_mouse=False, pop_ups=True, input_filter=self.input_filter.filter, unhandled_input=self.unhandled_input, - event_loop=AsyncioEventLoop()) + event_loop=AsyncioEventLoop(loop=self.aio_loop)) if self.opts.ascii: urwid.util.set_encoding('ascii') @@ -642,16 +644,14 @@ class Application: if self.updated: initial_controller_index = self.load_serialized_state() - self.loop.set_alarm_in( - 0.00, lambda loop, ud: tty.setraw(0)) - self.loop.set_alarm_in( - 0.05, lambda loop, ud: self.select_initial_screen( - initial_controller_index)) + self.aio_loop.call_soon(tty.setraw, 0) + self.aio_loop.call_soon( + self.select_initial_screen, initial_controller_index) self._connect_base_signals() self.start_controllers() - self.loop.run() + self.urwid_loop.run() except Exception: log.exception("Exception in controller.run():") raise diff --git a/subiquitycore/ui/spinner.py b/subiquitycore/ui/spinner.py index d7f6585f..fd9385bd 100644 --- a/subiquitycore/ui/spinner.py +++ b/subiquitycore/ui/spinner.py @@ -32,8 +32,8 @@ styles = { class Spinner(Text): - def __init__(self, loop=None, style='spin', align='center'): - self.loop = loop + def __init__(self, aio_loop=None, style='spin', align='center'): + self.aio_loop = aio_loop self.spin_index = 0 self.spin_text = styles[style]['texts'] self.rate = styles[style]['rate'] @@ -44,9 +44,9 @@ class Spinner(Text): self.spin_index = (self.spin_index + 1) % len(self.spin_text) self.set_text(self.spin_text[self.spin_index]) - def _advance(self, sender=None, user_data=None): + def _advance(self): self.spin() - self.handle = self.loop.set_alarm_in(self.rate, self._advance) + self.handle = self.aio_loop.call_later(self.rate, self._advance) def start(self): self.stop() @@ -55,5 +55,5 @@ class Spinner(Text): def stop(self): self.set_text('') if self.handle is not None: - self.loop.remove_alarm(self.handle) + self.handle.cancel() self.handle = None diff --git a/subiquitycore/ui/views/network.py b/subiquitycore/ui/views/network.py index 0829ace4..c54c81f9 100644 --- a/subiquitycore/ui/views/network.py +++ b/subiquitycore/ui/views/network.py @@ -158,7 +158,7 @@ class NetworkView(BaseView): ) def show_apply_spinner(self): - s = Spinner(self.controller.loop) + s = Spinner(self.controller.app.aio_loop) s.start() c = TablePile([ TableRow([ @@ -202,7 +202,7 @@ class NetworkView(BaseView): address_info.extend( [(label, Text(addr)) for addr in addrs]) elif dev.dhcp_state(v) == "PENDING": - s = Spinner(self.controller.loop, align='left') + s = Spinner(self.controller.app.aio_loop, align='left') s.rate = 0.3 s.start() address_info.append((label, s))