def process_input(self, user_input): """Process input from the screens. :param user_input: User input string. :type user_input: String. :raises: ExitMainLoop or any other kind of exception from screen processing. """ # process the input, if it wasn't processed (valid) # increment the error counter try: result = self._process_input(user_input) except ExitMainLoop: # pylint: disable=try-except-raise raise except Exception: # pylint: disable=broad-except App.get_event_loop().enqueue_signal(ExceptionSignal(self)) return if result.was_successful(): self._input_error_counter = 0 else: self._input_error_counter += 1 App.get_scheduler().process_input_result( result, self.input_error_threshold_exceeded)
def _process_signal(self, signal): log.debug("Processing signal %s", signal) self._mark_signal_processed(signal) if type(signal) in self._handlers: for handler_data in self._handlers[type(signal)]: try: handler_data.callback(signal, handler_data.data) except ExitMainLoop: # pylint: disable=try-except-raise raise except Exception: # pylint: disable=broad-except self.enqueue_signal(ExceptionSignal(self)) elif type(signal) is ExceptionSignal: self.kill_app_with_traceback(signal)
def _draw_screen(self, active_screen): """Draws the current `active_screen`. :param active_screen: Screen which should be draw to the console. :type active_screen: Classed based on `simpleline.render.screen.UIScreen`. """ # get the widget tree from the screen and show it in the screen try: if not active_screen.ui_screen.no_separator: # separate the content on the screen from the stuff we are about to display now print(self._spacer()) # print UIScreen content active_screen.ui_screen.show_all() except ExitMainLoop: # pylint: disable=try-except-raise raise except Exception: # pylint: disable=broad-except self._event_loop.enqueue_signal(ExceptionSignal(self))
def _process_screen(self): """Process the current screen. 1) It will call setup if the screen is not already set. 2a) If setup was success then draw the screen. 2b) If setup wasn't successful then pop the screen and try to process next in the stack. Continue by (1). 3)Ask for user input if requested. """ top_screen = self._get_last_screen() log.debug("Processing screen %s", top_screen) # this screen is used first time (call setup() method) if not top_screen.ui_screen.screen_ready: if not top_screen.ui_screen.setup(top_screen.args): # remove the screen and skip if setup went wrong self._screen_stack.pop() self.redraw() log.warning("Screen %s setup wasn't successful", top_screen) return # get the widget tree from the screen and show it in the screen try: # refresh screen content top_screen.ui_screen.refresh(top_screen.args) # Screen was closed in the refresh method if top_screen != self._get_last_screen(): return # draw screen to the console self._draw_screen(top_screen) if top_screen.ui_screen.input_required: log.debug("Input is required by %s screen", top_screen) top_screen.ui_screen.get_input_with_error_check( top_screen.args) except ExitMainLoop: # pylint: disable=try-except-raise raise except Exception: # pylint: disable=broad-except self._event_loop.enqueue_signal(ExceptionSignal(self)) return
def _run_handlers(self, data): """Run handlers attached to this signal and clean source afterwards.""" signal = data.signal source = data.source handlers = data.handlers if not self._force_quit: try: for handler in handlers: handler.callback(signal, handler.data) except ExitMainLoop: self._quit_all_loops() except Exception: # pylint: disable=broad-except self.enqueue_signal(ExceptionSignal(self)) # based on GLib documentation we should clean source # source will be removed from event loop context this way source.destroy() self._mark_signal_processed(signal)
def _process_screen(self): """Draws the current screen and returns True if user input is requested. If modal screen is requested, starts a new loop and initiates redraw after it ends. """ top_screen = self._get_last_screen() log.debug("Processing screen %s", top_screen) # this screen is used first time (call setup() method) if not top_screen.ui_screen.screen_ready: if not top_screen.ui_screen.setup(top_screen.args): # remove the screen and skip if setup went wrong self._screen_stack.pop() self.redraw() log.warning("Screen %s setup wasn't successful", top_screen) return # get the widget tree from the screen and show it in the screen try: # refresh screen content top_screen.ui_screen.refresh(top_screen.args) # Screen was closed in the refresh method if top_screen != self._get_last_screen(): return # draw screen to the console self._draw_screen(top_screen) if top_screen.ui_screen.input_required: log.debug("Input is required by %s screen", top_screen) top_screen.ui_screen.get_input_with_error_check( top_screen.args) except ExitMainLoop: # pylint: disable=try-except-raise raise except Exception: # pylint: disable=broad-except self._event_loop.enqueue_signal(ExceptionSignal(self)) return False
def handleException(self, dump_info): """ Our own handleException method doing some additional stuff before calling the original python-meh's one. :type dump_info: an instance of the meh.DumpInfo class :see: python-meh's ExceptionHandler.handleException """ log.debug("running handleException") exception_lines = traceback.format_exception(*dump_info.exc_info) log.critical("\n".join(exception_lines)) ty = dump_info.exc_info.type value = dump_info.exc_info.value try: gi.require_version("Gtk", "3.0") from gi.repository import Gtk # XXX: Gtk stopped raising RuntimeError if it fails to # initialize. Horay! But will it stay like this? Let's be # cautious and raise the exception on our own to work in both # cases initialized = Gtk.init_check(None)[0] if not initialized: raise RuntimeError() # Attempt to grab the GUI initializing lock, do not block if not self._gui_lock.acquire(False): # the graphical interface is running, don't crash it by # running another one potentially from a different thread log.debug( "Gtk running, queuing exception handler to the main loop") run_in_loop(self._main_loop_handleException, dump_info) else: log.debug( "Gtk not running, starting Gtk and running exception handler in it" ) self._main_loop_handleException(dump_info) except (RuntimeError, ImportError, ValueError): log.debug("Gtk cannot be initialized") # X not running (Gtk cannot be initialized) if threadMgr.in_main_thread(): log.debug("In the main thread, running exception handler") if issubclass(ty, NonInteractiveError) or not self._interactive: if issubclass(ty, NonInteractiveError): cmdline_error_msg = _( "\nThe installation was stopped due to an " "error which occurred while running in " "non-interactive cmdline mode. Since there " "cannot be any questions in cmdline mode, edit " "your kickstart file and retry installation. " "\nThe exact error message is: \n\n%s. \n\nThe " "installer will now terminate.") % str(value) else: cmdline_error_msg = _( "\nRunning in cmdline mode, no interactive " "debugging allowed.\nThe exact error message is: " "\n\n%s.\n\nThe installer will now terminate." ) % str(value) # since there is no UI in cmdline mode and it is completely # non-interactive, we can't show a message window asking the user # to acknowledge the error; instead, print the error out and sleep # for a few seconds before exiting the installer print(cmdline_error_msg) time.sleep(180) sys.exit(1) else: print("\nAn unknown error has occured, look at the " "/tmp/anaconda-tb* file(s) for more details") # in the main thread, run exception handler self._main_loop_handleException(dump_info) else: log.debug( "In a non-main thread, sending a message with exception data" ) # not in the main thread, just send message with exception # data and let message handler run the exception handler in # the main thread exc_info = dump_info.exc_info # new Simpleline package is now used in TUI. Look if Simpleline is # initialized or if this is some fallback from GTK or other stuff. if App.is_initialized(): # if Simpleline is initialized enqueue exception there loop = App.get_event_loop() loop.enqueue_signal( ExceptionSignal(App.get_scheduler(), exception_info=exc_info)) else: hubQ.send_exception( (exc_info.type, exc_info.value, exc_info.stack))