def exception_msg_handler(signal, data): """ Handler for the ExceptionSignal signal. :param signal: event data :type signal: (event_type, message_data) :param data: additional data :type data: any """ global exception_processed if exception_processed: # get data from the event data structure exception_info = signal.exception_info stack_trace = "\n" + App.get_scheduler().dump_stack() log.error(stack_trace) # exception_info is a list sys.excepthook(*exception_info) else: # show only the first exception do not spam user with others exception_processed = True loop = App.get_event_loop() # start new loop for handling the exception # this will stop processing all the old signals and prevent raising new exceptions loop.execute_new_loop(signal)
def setup(self, data): """Construct all the objects required to implement this interface. This method must be provided by all subclasses. """ # Use GLib event loop for the Simpleline TUI loop = GLibEventLoop() App.initialize(event_loop=loop) loop.set_quit_callback(tui_quit_callback) scheduler = App.get_scheduler() scheduler.quit_screen = YesNoDialog(self.quitMessage) # tell python-meh it should use our raw_input meh_io_handler = meh.ui.text.IOHandler(in_func=self._get_meh_input_func) self._meh_interface.set_io_handler(meh_io_handler) # register handlers for various messages loop = App.get_event_loop() loop.register_signal_handler(ExceptionSignal, exception_msg_handler) loop.register_signal_handler(SendMessageSignal, self._handle_show_message) _hubs = self._list_hubs() # First, grab a list of all the standalone spokes. spokes = self._collectActionClasses(self.paths["spokes"], StandaloneSpoke) actionClasses = self._orderActionClasses(spokes, _hubs) for klass in actionClasses: obj = klass(data, self.storage, self.payload, self.instclass) # If we are doing a kickstart install, some standalone spokes # could already be filled out. In that case, we do not want # to display them. if self._is_standalone(obj) and obj.completed: del(obj) continue if hasattr(obj, "set_path"): obj.set_path("spokes", self.paths["spokes"]) obj.set_path("categories", self.paths["categories"]) should_schedule = obj.setup(self.ENVIRONMENT) if should_schedule: scheduler.schedule_screen(obj)
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))
def test_close_screen_closed_from_other_source_error(self): App.initialize() App.get_scheduler().schedule_screen(UIScreen()) with self.assertRaises(RenderUnexpectedError): App.get_scheduler().close_screen(closed_from=mock.MagicMock())
def _check_app_settings(self, event_loop, scheduler, configuration): self.assertEqual(App.get_event_loop(), event_loop) self.assertEqual(App.get_scheduler(), scheduler) self.assertEqual(App.get_configuration(), configuration)
def test_failed_screen_setup(self): screen = FailedSetupScreen() App.initialize() App.get_scheduler().schedule_screen(screen) App.run()
def test_quit_input(self, mock_stdin, mock_stdout): mock_stdin.return_value = "q" screen = UIScreen() App.get_scheduler().schedule_screen(screen) App.run()
def schedule_screen_and_run(screen): App.initialize() App.get_scheduler().schedule_screen(screen) App.run()
def test_create_instance_with_custom_scheduler(self): App.initialize(scheduler=CustomScreenScheduler(CustomEventLoop())) self.assertTrue(isinstance(App.get_scheduler(), CustomScreenScheduler))
def test_create_instance(self): App.initialize() self.assertTrue(isinstance(App.get_scheduler(), ScreenScheduler)) self.assertTrue(isinstance(App.get_event_loop(), MainLoop)) self.assertTrue( isinstance(App.get_configuration(), GlobalConfiguration))
def schedule_screen_and_run_with_glib(self, screen): self.setup_glib() App.get_scheduler().schedule_screen(screen) App.run()
def push_screen_modal(cls, ui_screen, args=None): """Schedule screen to the active scheduler. See: `simpleline.render.screen_scheduler.push_screen_modal()`. """ App.get_scheduler().push_screen_modal(ui_screen=ui_screen, args=args)
def replace_screen(cls, ui_screen, args=None): """Schedule screen to the active scheduler. See: `simpleline.render.screen_scheduler.replace_screen()`. """ App.get_scheduler().replace_screen(ui_screen=ui_screen, args=args)