From 5d77d71499b0916d17c42d679a746ff55f8699e6 Mon Sep 17 00:00:00 2001 From: Maciej Borzecki Date: Tue, 24 Mar 2020 10:50:24 +0100 Subject: [PATCH] subiquitycore: allow overriding input/output when creating screens The interaction with snap-recovery-chooser happens over stdin/stdout. The early setup code in console-conf will attempt to restore sys.stdin/sys.stdout and hook them up to the current tty. The patch allows passing input/output streams explicitly as parameters to the constructors. Also, default to sys.stdin/sys.stdout and pass both streams explicitly when constructing urwid.raw_display.Screen(), to workaround the bug in their constructor. THe constructor is defined as follows: class Screen(BaseScreen, RealTerminal): def __init__(self, input=sys.stdin, output=sys.stdout): What means, that even if we override sys.stdout/sys.stdin globally in our setup code, this will have no effect as `input` and `output` already got their values. Signed-off-by: Maciej Borzecki --- subiquity/core.py | 4 ++-- subiquitycore/core.py | 22 ++++++++++++++-------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/subiquity/core.py b/subiquity/core.py index 5cb38ed6..b855eeab 100644 --- a/subiquity/core.py +++ b/subiquity/core.py @@ -140,9 +140,9 @@ class Subiquity(Application): cmdline = [sys.executable] + sys.argv os.execvp(cmdline[0], cmdline) - def make_screen(self): + def make_screen(self, input=None, output=None): if self.interactive(): - return super().make_screen() + return super().make_screen(input, output) else: r, w = os.pipe() s = urwid.raw_display.Screen( diff --git a/subiquitycore/core.py b/subiquitycore/core.py index 8d6d3418..b2c98124 100644 --- a/subiquitycore/core.py +++ b/subiquitycore/core.py @@ -60,9 +60,9 @@ KDSKBMODE = 0x4B45 # sets current keyboard mode class TwentyFourBitScreen(urwid.raw_display.Screen): - def __init__(self, _urwid_name_to_rgb): + def __init__(self, _urwid_name_to_rgb, **kwargs): self._urwid_name_to_rgb = _urwid_name_to_rgb - super().__init__() + super().__init__(**kwargs) def _cc(self, color): """Return the "SGR" parameter for selecting color. @@ -610,7 +610,7 @@ class Application: if os.isatty(fd): tty.setraw(fd) - def make_screen(self): + def make_screen(self, inputf=None, outputf=None): """Return a screen to be passed to MainLoop. colors is a list of exactly 8 tuples (name, (r, g, b)), the same as @@ -619,6 +619,11 @@ class Application: # On the linux console, we overwrite the first 8 colors to be those # defined by colors. Otherwise, we return a screen that uses ISO # 8613-3ish codes to display the colors. + if inputf is None: + inputf = sys.stdin + if outputf is None: + outputf = sys.stdout + if len(self.COLORS) != 8: raise Exception( "make_screen must be passed a list of exactly 8 colors") @@ -631,18 +636,19 @@ class Application: for j in range(3): curpal[i*3+j] = self.COLORS[i][1][j] fcntl.ioctl(sys.stdout.fileno(), PIO_CMAP, curpal) - return urwid.raw_display.Screen() + return urwid.raw_display.Screen(input=inputf, output=outputf) elif self.opts.ascii: - return urwid.raw_display.Screen() + return urwid.raw_display.Screen(input=inputf, output=outputf) else: _urwid_name_to_rgb = {} for i, n in enumerate(urwid_8_names): _urwid_name_to_rgb[n] = self.COLORS[i][1] - return TwentyFourBitScreen(_urwid_name_to_rgb) + return TwentyFourBitScreen(_urwid_name_to_rgb, + input=inputf, output=outputf) - def run(self): + def run(self, input=None, output=None): log.debug("Application.run") - screen = self.make_screen() + screen = self.make_screen(input, output) self.urwid_loop = urwid.MainLoop( self.ui, palette=self.color_palette, screen=screen,