Before this patch our UserInterface classes somehow "implicitly" inherited python-meh's *Intf classes by providing two methods with right names. This patch adds a meh_interface property to our UserInterface classes that returns an instance of a class that really is inherited from the python-meh's *Intf class or actually is an instance of the python-meh's *Intf class in case of gui and tui respectively. It also adds a tty_num property to our *UserInterface classes that can be used in runDebug to get user to the right console before and after the pdb session automatically.
Signed-off-by: Vratislav Podzimek vpodzime@redhat.com --- pyanaconda/exception.py | 24 +++++++++---- pyanaconda/ui/__init__.py | 26 +++++++------- pyanaconda/ui/gui/__init__.py | 83 +++++++++++++++++++++++++++++-------------- pyanaconda/ui/tui/__init__.py | 19 +++++----- 4 files changed, 99 insertions(+), 53 deletions(-)
diff --git a/pyanaconda/exception.py b/pyanaconda/exception.py index 09f9837..2c852ae 100644 --- a/pyanaconda/exception.py +++ b/pyanaconda/exception.py @@ -43,6 +43,17 @@ _ = lambda x: gettext.ldgettext("anaconda", x)
class AnacondaExceptionHandler(ExceptionHandler): + + def __init__(self, confObj, intfClass, exnClass, tty_num): + """ + @see: python-meh's ExceptionHandler + @param tty_num: the number of tty the interface is running on + + """ + + ExceptionHandler.__init__(self, confObj, intfClass, exnClass) + self._intf_tty_num = tty_num + def handleException(self, (ty, value, tb), obj):
def run_handleException_on_idle(args_tuple): @@ -60,7 +71,7 @@ class AnacondaExceptionHandler(ExceptionHandler): super(AnacondaExceptionHandler, self).handleException((ty, value, tb), obj) return False - + if issubclass(ty, storage.errors.StorageError) and value.hardware_fault: hw_error_msg = _("The installation was stopped due to what " "seems to be a problem with your hardware. " @@ -105,9 +116,8 @@ class AnacondaExceptionHandler(ExceptionHandler): pass
def runDebug(self, (ty, value, tb)): - # vtActivate does not work on certain ppc64 machines, so just skip - # that and continue with the rest of the debugger setup. - iutil.vtActivate(1) + if self._intf_tty_num != 1: + iutil.vtActivate(1)
pidfl = "/tmp/vncshell.pid" if os.path.exists(pidfl) and os.path.isfile(pidfl): @@ -137,7 +147,8 @@ class AnacondaExceptionHandler(ExceptionHandler): import pdb pdb.post_mortem (tb)
- iutil.vtActivate(6) + if self._intf_tty_num != 1: + iutil.vtActivate(self._intf_tty_num)
def initExceptionHandling(anaconda): fileList = [ "/tmp/anaconda.log", "/tmp/packaging.log", @@ -164,7 +175,8 @@ def initExceptionHandling(anaconda): "payload._yum"], localSkipList=[ "passphrase", "password" ], fileList=fileList) - handler = AnacondaExceptionHandler(conf, anaconda.intf, ReverseExceptionDump) + handler = AnacondaExceptionHandler(conf, anaconda.intf.meh_interface, + ReverseExceptionDump, anaconda.intf.tty_num) handler.install(anaconda)
return conf diff --git a/pyanaconda/ui/__init__.py b/pyanaconda/ui/__init__.py index 9337a2a..d09e9b4 100644 --- a/pyanaconda/ui/__init__.py +++ b/pyanaconda/ui/__init__.py @@ -64,6 +64,11 @@ class UserInterface(object): basemask = "pyanaconda.ui" paths = PathDict({})
+ @property + def tty_num(self): + """Returns the number of tty the UserInterface is running on.""" + raise NotImplementedError + @classmethod def update_paths(cls, pathdict): """Receives pathdict and appends it's contents to the current @@ -85,6 +90,15 @@ class UserInterface(object): """ raise NotImplementedError
+ @property + def meh_interface(self): + """ + Returns an interface for exception handling (defined by python-meh's + AbstractIntf class). + + """ + raise NotImplementedError + ### ### MESSAGE HANDLING METHODS ### @@ -156,15 +170,3 @@ class UserInterface(object): key=lambda obj: obj.priority))
return actionClasses - - def mainExceptionWindow(self, text, exn_file): - """Return window with the exception and buttons for debugging, bug - reporting and exitting the installer. - - This method will be called only when unhandled exception appears. - """ - raise NotImplementedError - - def saveExceptionWindow(self, account_manager, signature): - """Show a window that provides a way to report a bug.""" - raise NotImplementedError diff --git a/pyanaconda/ui/gui/__init__.py b/pyanaconda/ui/gui/__init__.py index a7c9ea7..73925e7 100644 --- a/pyanaconda/ui/gui/__init__.py +++ b/pyanaconda/ui/gui/__init__.py @@ -230,7 +230,9 @@ class GraphicalUserInterface(UserInterface): self._distributionText = distributionText self._isFinal = isFinal self._quitDialog = quitDialog - + self._mehInterface = GraphicalExceptionHandlingIface( + self.lightbox_over_current_action) + # This is a hack to make sure the AnacondaWidgets library gets loaded # before glade tries to use Anaconda types # glade file should contain the following line to make this seamless @@ -259,7 +261,15 @@ class GraphicalUserInterface(UserInterface): os.path.join(path, "hubs")) for path in pathlist] } - + + @property + def tty_num(self): + return 6 + + @property + def meh_interface(self): + return self._mehInterface + def _list_hubs(self): """Return a list of Hub classes to be imported to this interface""" from .hubs.summary import SummaryHub @@ -289,6 +299,20 @@ class GraphicalUserInterface(UserInterface): # Second, order them according to their relationship return self._orderActionClasses(standalones, hubs)
+ def lightbox_over_current_action(self, window): + """ + Creates lightbox over current action for the given window. Or + DOES NOTHING IF THERE ARE NO ACTIONS. + + """ + + from gi.repository import AnacondaWidgets + + # if there are no actions (not populated yet), we can do nothing + if len(self._actions) > 0: + lightbox = AnacondaWidgets.lb_show_over(self._currentAction.window) + window.main_window.set_transient_for(lightbox) + def _instantiateAction(self, actionClass): from spokes import StandaloneSpoke
@@ -399,30 +423,6 @@ class GraphicalUserInterface(UserInterface):
return bool(rc)
- - def mainExceptionWindow(self, text, exn_file, *args, **kwargs): - from gi.repository import Gtk, AnacondaWidgets - - meh_intf = meh.ui.gui.GraphicalIntf() - exc_window = meh_intf.mainExceptionWindow(text, exn_file) - exc_window.main_window.set_decorated(False) - - # exception may appear before self._actions gets populated - if len(self._actions) > 0: - lightbox = AnacondaWidgets.lb_show_over(self._currentAction.window) - exc_window.main_window.set_transient_for(lightbox) - - # without WindowGroup, python-meh's window is insensitive if it appears - # above a spoke (Gtk.Window running its own Gtk.main loop) - window_group = Gtk.WindowGroup() - window_group.add_window(exc_window.main_window) - - return exc_window - - def saveExceptionWindow(self, signature, *args, **kwargs): - meh_intf = meh.ui.gui.GraphicalIntf() - meh_intf.saveExceptionWindow(signature) - ### ### SIGNAL HANDLING METHODS ### @@ -493,7 +493,38 @@ class GraphicalUserInterface(UserInterface): if rc == 1: sys.exit(0)
+class GraphicalExceptionHandlingIface(meh.ui.gui.GraphicalIntf): + """ + Class inheriting from python-meh's GraphicalIntf and overriding methods + that need some modification in Anaconda. + + """ + + def __init__(self, lightbox_func): + """ + @param lightbox_func: a function that creates lightbox for a given + window + @type lightbox_func: GtkWindow -> None + + """ + + self._lightbox_func = lightbox_func
+ def mainExceptionWindow(self, text, exn_file, *args, **kwargs): + from gi.repository import Gtk + + meh_intf = meh.ui.gui.GraphicalIntf() + exc_window = meh_intf.mainExceptionWindow(text, exn_file) + exc_window.main_window.set_decorated(False) + + self._lightbox_func(exc_window) + + # without WindowGroup, python-meh's window is insensitive if it appears + # above a spoke (Gtk.Window running its own Gtk.main loop) + window_group = Gtk.WindowGroup() + window_group.add_window(exc_window.main_window) + + return exc_window
def busyCursor(): window = Gdk.get_default_root_window() diff --git a/pyanaconda/ui/tui/__init__.py b/pyanaconda/ui/tui/__init__.py index cebb6c4..64b9f7f 100644 --- a/pyanaconda/ui/tui/__init__.py +++ b/pyanaconda/ui/tui/__init__.py @@ -130,6 +130,7 @@ class TextUserInterface(ui.UserInterface):
ui.UserInterface.__init__(self, storage, payload, instclass) self._app = None + self._meh_interface = meh.ui.text.TextIntf()
basemask = "pyanaconda.ui.tui" basepath = os.path.dirname(__file__) @@ -146,7 +147,15 @@ class TextUserInterface(ui.UserInterface): os.path.join(path, "hubs")) for path in pathlist] } - + + @property + def tty_num(self): + return 1 + + @property + def meh_interface(self): + return self._meh_interface + def _list_hubs(self): """returns the list of hubs to use""" return [SummaryHub, ProgressHub] @@ -225,11 +234,3 @@ class TextUserInterface(ui.UserInterface): question_window = YesNoDialog(self._app, message) self._app.switch_screen_modal(question_window) return question_window.answer - - def mainExceptionWindow(self, text, exn_file, *args, **kwargs): - meh_intf = meh.ui.text.TextIntf() - return meh_intf.mainExceptionWindow(text, exn_file, *args, **kwargs) - - def saveExceptionWindow(self, signature, *args, **kwargs): - meh_intf = meh.ui.text.TextIntf() - return meh_intf.saveExceptionWindow(signature, *args, **kwargs)