The following series of patches changes anaconda over to using the new python-meh for exception handling. I have tested this, though something is bound to go wrong once we get all the packaging done and into a release. Before this can be pushed, the new python-meh package needs to make it in, though that's supposed to be in the works.
Doing this will allow me to later get rid of rhpl.exception. I think there's a bug and patch filed against all components that use it now. At least, I know I've cleaned up my code.
- Chris
--- filer.py | 452 ------------------------------------- ui/exnSave.glade | 664 ------------------------------------------------------ 2 files changed, 0 insertions(+), 1116 deletions(-) delete mode 100644 filer.py delete mode 100644 ui/exnSave.glade
diff --git a/filer.py b/filer.py deleted file mode 100644 index d693162..0000000 --- a/filer.py +++ /dev/null @@ -1,452 +0,0 @@ -# Copyright (C) 2008 Red Hat, Inc. -# All rights reserved. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see http://www.gnu.org/licenses/. -# -# Author(s): Chris Lumens clumens@redhat.com -# -import xmlrpclib -import socket - -class LoginError(Exception): - """An error occurred while logging into the bug reporting system.""" - def __init__(self, bugUrl, username): - self.bugUrl = bugUrl - self.username = username - - def __str__(self): - return "Could not login to %s with username %s" % (self.bugUrl, self.username) - -class CommunicationError(Exception): - """Some miscellaneous error occurred while communicating with the - bug reporting system. This could include XML-RPC errors, passing - bad data, or network problems.""" - def __init__(self, msg): - self.msg = msg - - def __str__(self): - return "Error communicating with bug system: %s" % self.msg - - -# These classes don't do anything except say that automated bug filing are not -# supported. They also define the interface that concrete classes should use, -# as this is what will be expected by exception.py. -class AbstractFiler(object): - """The base class for Filer objects. This is an abstract class. - - Within this class's help, Bug refers to a concrete AbstractBug subclass - and Filer refers to a concrete AbstractFiler subclass. - - A Filer object communicates with a bug filing system - like bugzilla - - that a distribution uses to track defects. Install classes specify - what bug filing system they use by instantiating a subclass of - AbstractFiler. The intention is that each subclass of AbstractFiler - will make use of some system library to handle the actual communication - with the bug filing system. For now, all systems will be assumed to act - like bugzilla. - - Methods in this class should raise the following exceptions: - - CommunicationError -- For all problems communicating with the remote - bug filing system. - LoginError -- For invalid login information. - ValueError -- For all other operations where the client - supplied values are not correct. - """ - def __init__(self, bugUrl=None, develVersion=None, defaultProduct=None): - """Create a new AbstractFiler instance. This method need not be - overridden by subclasses. - - bugUrl -- The URL of the bug filing system. - develVersion -- What version of the product should be treated as - the development version. This is used in case - anaconda attempts to file bugs against invalid - versions. It need not be set. - defaultProduct -- The product bugs should be filed against, should - anaconda get an invalid product name from the - boot media. This must be set. - """ - self.bugUrl = bugUrl - self.develVersion = develVersion - self.defaultProduct = defaultProduct - - def login(self, username, password): - """Using the given username and password, attempt to login to the - bug filing system. This method must be provided by all subclasses, - and should raise LoginError if login is unsuccessful. - """ - raise NotImplementedError - - def createbug(self, *args, **kwargs): - """Create a new bug. The kwargs dictionary is all the arguments that - should be used when creating the new bug and is entirely up to the - subclass to handle. This method must be provided by all subclasses. - On success, it should return a Bug instance. - """ - raise NotImplementedError - - def getbug(self, id): - """Search for a bug given by id and return it. This method must be - provided by all subclasses. On success, it should return a Bug - instance. On error, it should return an instance that is empty. - """ - raise NotImplementedError - - def getbugs(self, idlist): - """Search for all the bugs given by the IDs in idlist and return. - This method must be provided by all subclasses. On success, it - should return a list of Bug instances, or an empty instance for - invalid IDs. - """ - raise NotImplementedError - - def getproduct(self, prod): - """Verify that prod is a valid product name. If it is, return that - same product name. If not, return self.defaultProduct. This method - queries the bug filing system for a list of valid products. It must - be provided by all subclasses. - """ - raise NotImplementedError - - def getversion(self, ver, prod): - """Verify that ver is a valid version number for the product name prod. - If it is, return that same version number. If not, return - self.develVersion if it exists or the latest version number - otherwise. This method queries the bug filing system for a list of - valid versions numbers. It must be provided by all subclasses. - """ - raise NotImplementedError - - def query(self, query): - """Perform the provided query and return a list of Bug instances that - meet the query. What the query is depends on the exact bug filing - system, though anaconda will treat it as a dictionary of bug - attibutes since this is what bugzilla expects. Other filing systems - will need to take extra work to munge this data into the expected - format. This method must be provided by all subclasses. - """ - raise NotImplementedError - - def supportsFiling(self): - """Does this class support filing bugs? All subclasses should override - this method and return True, or automatic filing will not work. The - base install class will use this method, so automatic filing will - not be attempted by anaconda on unknown products. - """ - return False - -class AbstractBug(object): - """The base class for Bug objects. This is an abstract class. - - Within this class's help, Bug refers to a concrete AbstractBug subclass - and Filer refers to a concrete AbstractFiler subclass. - - A Bug object represents one single bug within a Filer. This is where - most of the interesting stuff happens - attaching files, adding comments - and email addresses, and modifying whiteboards. Subclasses of this - class are returned by most operations within a Filer subclass. For now, - all bugs will be assumed to act like bugzilla's bugs. - - Bug objects wrap objects in the underlying module that communicates with - the bug filing system. For example, the bugzilla filer uses the - python-bugzilla module to communicate. This module has its own Bug - object. So, BugzillaBug wraps that object. Therefore, Bugs may be - created out of existing BugzillaBugs or may create their own if - necessary. - - Methods in this class should raise the following exceptions: - - CommunicationError -- For all problems communicating with the remote - bug filing system. - ValueError -- For all other operations where the client - supplied values are not correct (invalid - resolution, status, whiteboard, etc.). - """ - def __init__(self, filer, bug=None, *args, **kwargs): - """Create a new Bug instance. It is recommended that subclasses - override this method to add extra attributes. - - filer -- A reference to a Filer object used when performing - certain operations. This may be None if it is not - required by the Filer or Bug objects. - bug -- If None, the filer-specific code should create a new - bug object. Otherwise, the filer-specific code - should use the provided object as needed. - args, kwargs -- If provided, these arguments should be passed as-is - when creating a new underlying bug object. This - only makes sense if bug is not None. - """ - self.filer = filer - - def __str__(self): - raise NotImplementedError - - def __repr__(self): - raise NotImplementedError - - def addCC(self, address): - """Add the provided email address to this bug. This method must be - provided by all subclasses, and return some non-None value on - success. - """ - raise NotImplementedError - - def addcomment(self, comment): - """Add the provided comment to this bug. This method must be provided - by all subclasses, and return some non-None value on success. - """ - raise NotImplementedError - - def attachfile(self, file, description, **kwargs): - """Attach the filename given by file, with the given description, to - this bug. If provided, the given kwargs will be passed along to - the Filer when attaching the file. These args may be useful for - doing things like setting the MIME type of the file. This method - must be provided by all subclasses and return some non-None value - on success. - """ - raise NotImplementedError - - def close(self, resolution, dupeid=0, comment=''): - """Close this bug with the given resolution, optionally closing it - as a duplicate of the provided dupeid and with the optional comment. - resolution must be a value accepted by the Filer. This method must - be provided by all subclasses and return some non-None value on - success. - """ - raise NotImplementedError - - def id(self): - """Return this bug's ID number. This method must be provided by all - subclasses. - """ - raise NotImplementedError - - def setstatus(self, status, comment=''): - """Set this bug's status and optionally add a comment. status must be - a value accepted by the Filer. This method must be provided by all - subclasses and return some non-None value on success. - """ - raise NotImplementedError - - def setassignee(self, assigned_to='', reporter='', comment=''): - """Assign this bug to the person given by assigned_to, optionally - changing the reporter and attaching a comment. assigned_to must be - a valid account in the Filer. This method must be provided by all - subclasses and return some non-None value on success. - """ - raise NotImplementedError - - def getwhiteboard(self, which=''): - """Get the given whiteboard from this bug and return it. Not all bug - filing systems support the concept of whiteboards, so this method - is optional. Currently, anaconda does not call it. - """ - return "" - - def appendwhiteboard(self, text, which=''): - """Append the given text to the given whiteboard. Not all bug filing - systems support the concept of whiteboards, so this method is - optional. If provided, it should return some non-None value on - success. Currently, anaconda does not call this method. - """ - return True - - def prependwhiteboard(self, text, which=''): - """Put the given text at the front of the given whiteboard. Not all - bug filing systems support the concept of whiteboards, so this - method is optional. If provided, it should return some non-None - value on success. Currently, anaconda does not call this method. - """ - return True - - def setwhiteboard(self, text, which=''): - """Set the given whiteboard to be the given text. Not all bug filing - systems support the concept of whiteboards, so this method is - optional. If provided, it should return some non-None value on - success. Currently, anaconda does not call this method. - """ - return True - - -# Concrete classes for automatically filing bugs against Bugzilla instances. -# This requires the python-bugzilla module to do almost all of the real work. -# We basically just make some really thin wrappers around it here since we -# expect all bug filing systems to act similar to bugzilla. -class BugzillaFiler(AbstractFiler): - def __withBugzillaDo(self, fn): - try: - retval = fn(self._bz) - return retval - except xmlrpclib.ProtocolError, e: - raise CommunicationError(str(e)) - except xmlrpclib.Fault, e: - raise ValueError(str(e)) - except socket.error, e: - raise CommunicationError(str(e)) - - def __init__(self, bugUrl=None, develVersion=None, defaultProduct=None): - AbstractFiler.__init__(self, bugUrl=bugUrl, develVersion=develVersion, - defaultProduct=defaultProduct) - self._bz = None - - def login(self, username, password): - import bugzilla - - try: - self._bz = bugzilla.Bugzilla(url=self.bugUrl) - retval = self._bz.login(username, password) - except socket.error, e: - raise CommunicationError(str(e)) - - if not retval: - raise LoginError(self.bugUrl, username) - - return retval - - def createbug(self, *args, **kwargs): - whiteboards = [] - - for (key, val) in kwargs.items(): - if key.endswith("_whiteboard"): - wb = key.split("_")[0] - whiteboards.append((wb, val)) - kwargs.pop(key) - - if key == "platform": - platformLst = self.__withBugzillaDo(lambda b: b._proxy.Bug.legal_values({'field': 'platform'})) - if not val in platformLst['values']: - kwargs[key] = platformLst['values'][0] - - bug = self.__withBugzillaDo(lambda b: b.createbug(**kwargs)) - for (wb, val) in whiteboards: - bug.setwhiteboard(val, which=wb) - - return BugzillaBug(self, bug=bug) - - def getbug(self, id): - return BugzillaBug(self, bug=self.__withBugzillaDo(lambda b: b.getbug(id))) - - def getbugs(self, idlist): - lst = self.__withBugzillaDo(lambda b: b.getbugs(idlist)) - return map(lambda b: BugzillaBug(self, bug=b), lst) - - def getproduct(self, prod): - details = self.__withBugzillaDo(lambda b: b.getproducts()) - for d in details: - if d['name'] == prod: - return prod - - if self.defaultProduct: - return self.defaultProduct - else: - raise ValueError, "The product %s is not valid and no defaultProduct is set." % prod - - def getversion(self, ver, prod): - details = self.__withBugzillaDo(lambda b: b._proxy.bugzilla.getProductDetails(prod)) - bugzillaVers = details[1] - bugzillaVers.sort() - - if ver not in bugzillaVers: - if self.develVersion: - return self.develVersion - else: - return bugzillaVers[-1] - else: - return ver - - def query(self, query): - lst = self.__withBugzillaDo(lambda b: b.query(query)) - return map(lambda b: BugzillaBug(self, bug=b), lst) - - def supportsFiling(self): - return True - -class BugzillaBug(AbstractBug): - def __withBugDo(self, fn): - try: - retval = fn(self._bug) - return retval - except xmlrpclib.ProtocolError, e: - raise CommunicationError(str(e)) - except xmlrpclib.Fault, e: - raise ValueError(str(e)) - except socket.error, e: - raise CommunicationError(str(e)) - - def __init__(self, filer, bug=None, *args, **kwargs): - import bugzilla - - self.filer = filer - - if not bug: - self._bug = bugzilla.Bug(self.filer, *args, **kwargs) - else: - self._bug = bug - - def __str__(self): - return self._bug.__str__() - - def __repr__(self): - return self._bug.__repr__() - - def addCC(self, address): - try: - return self.filer._bz._updatecc(self._bug.bug_id, [address], 'add') - except xmlrpclib.ProtocolError, e: - raise CommunicationError(str(e)) - except xmlrpclib.Fault, e: - raise ValueError(str(e)) - except socket.error, e: - raise CommunicationError(str(e)) - - def addcomment(self, comment): - return self.__withBugDo(lambda b: b.addcomment(comment)) - - def attachfile(self, file, description, **kwargs): - try: - return self.filer._bz.attachfile(self._bug.bug_id, file, description, **kwargs) - except xmlrpclib.ProtocolError, e: - raise CommunicationError(str(e)) - except xmlrpclib.Fault, e: - raise ValueError(str(e)) - except socket.error, e: - raise CommunicationError(str(e)) - - def id(self): - return self._bug.bug_id - - def close(self, resolution, dupeid=0, comment=''): - return self.__withBugDo(lambda b: b.close(resolution, dupeid=dupeid, - comment=comment)) - - def setstatus(self, status, comment=''): - return self.__withBugDo(lambda b: b.setstatus(status, comment=comment)) - - def setassignee(self, assigned_to='', reporter='', comment=''): - return self.__withBugDo(lambda b: b.setassignee(assigned_to=assigned_to, - reporter=reporter, - comment=comment)) - - def getwhiteboard(self, which='status'): - return self.__withBugDo(lambda b: b.getwhiteboard(which=which)) - - def appendwhiteboard(self, text, which='status'): - return self.__withBugDo(lambda b: b.appendwhiteboard(text, which=which)) - - def prependwhiteboard(self, text, which='status'): - return self.__withBugDo(lambda b: b.prependwhiteboard(text, which=which)) - - def setwhiteboard(self, text, which='status'): - return self.__withBugDo(lambda b: b.setwhiteboard(text, which=which)) diff --git a/ui/exnSave.glade b/ui/exnSave.glade deleted file mode 100644 index ca9106a..0000000 --- a/ui/exnSave.glade +++ /dev/null @@ -1,664 +0,0 @@ -<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> -<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd"> - -<glade-interface> - -<widget class="GtkDialog" id="saveDialog"> - <property name="visible">True</property> - <property name="title" translatable="yes">Save</property> - <property name="type">GTK_WINDOW_TOPLEVEL</property> - <property name="window_position">GTK_WIN_POS_CENTER</property> - <property name="modal">True</property> - <property name="resizable">True</property> - <property name="destroy_with_parent">False</property> - <property name="decorated">True</property> - <property name="skip_taskbar_hint">False</property> - <property name="skip_pager_hint">False</property> - <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> - <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> - <property name="focus_on_map">True</property> - <property name="urgency_hint">False</property> - <property name="has_separator">True</property> - - <child internal-child="vbox"> - <widget class="GtkVBox" id="dialog-vbox1"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child internal-child="action_area"> - <widget class="GtkHButtonBox" id="dialog-action_area1"> - <property name="visible">True</property> - <property name="layout_style">GTK_BUTTONBOX_END</property> - - <child> - <widget class="GtkButton" id="cancelbutton1"> - <property name="visible">True</property> - <property name="can_default">True</property> - <property name="can_focus">True</property> - <property name="label">gtk-cancel</property> - <property name="use_stock">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="response_id">-6</property> - </widget> - </child> - - <child> - <widget class="GtkButton" id="okbutton1"> - <property name="visible">True</property> - <property name="can_default">True</property> - <property name="can_focus">True</property> - <property name="label">gtk-ok</property> - <property name="use_stock">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="response_id">-5</property> - </widget> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="pack_type">GTK_PACK_END</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vbox1"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkLabel" id="label6"> - <property name="visible">True</property> - <property name="label" translatable="yes">Please choose a destination for saving your traceback.</property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">True</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0</property> - <property name="xpad">0</property> - <property name="ypad">5</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkComboBox" id="destCombo"> - <property name="visible">True</property> - <property name="items" translatable="yes">Local storage device -Local disk -Remote server (scp)</property> - <property name="add_tearoffs">False</property> - <property name="focus_on_click">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkNotebook" id="destNotebook"> - <property name="visible">True</property> - <property name="show_tabs">False</property> - <property name="show_border">False</property> - <property name="tab_pos">GTK_POS_TOP</property> - <property name="scrollable">False</property> - <property name="enable_popup">False</property> - - <child> - <widget class="GtkAlignment" id="alignment1"> - <property name="visible">True</property> - <property name="xalign">0.5</property> - <property name="yalign">0.10000000149</property> - <property name="xscale">1</property> - <property name="yscale">0</property> - <property name="top_padding">0</property> - <property name="bottom_padding">0</property> - <property name="left_padding">0</property> - <property name="right_padding">0</property> - - <child> - <widget class="GtkComboBox" id="diskCombo"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="add_tearoffs">False</property> - <property name="focus_on_click">True</property> - </widget> - </child> - </widget> - <packing> - <property name="tab_expand">False</property> - <property name="tab_fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label12"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="type">tab</property> - </packing> - </child> - - <child> - <widget class="GtkFileChooserButton" id="localChooser"> - <property name="visible">True</property> - <property name="title" translatable="yes">Select A File</property> - <property name="action">GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER</property> - <property name="local_only">True</property> - <property name="show_hidden">False</property> - <property name="do_overwrite_confirmation">False</property> - <property name="width_chars">-1</property> - </widget> - <packing> - <property name="tab_expand">False</property> - <property name="tab_fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label14"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="type">tab</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="bugzillaBox"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkVBox" id="vbox2"> - <property name="border_width">5</property> - <property name="visible">True</property> - <property name="homogeneous">True</property> - <property name="spacing">5</property> - - <child> - <widget class="GtkLabel" id="label4"> - <property name="visible">True</property> - <property name="label">_User name</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label5"> - <property name="visible">True</property> - <property name="label">_Password</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label7"> - <property name="visible">True</property> - <property name="label" translatable="yes">Bug _description</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vbox3"> - <property name="border_width">5</property> - <property name="visible">True</property> - <property name="homogeneous">True</property> - <property name="spacing">5</property> - - <child> - <widget class="GtkEntry" id="bugzillaNameEntry"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">•</property> - <property name="activates_default">False</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkEntry" id="bugzillaPasswordEntry"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">False</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">•</property> - <property name="activates_default">False</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkEntry" id="bugDesc"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">•</property> - <property name="activates_default">False</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="tab_expand">False</property> - <property name="tab_fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label16"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="type">tab</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="scpBox"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkVBox" id="vbox5"> - <property name="border_width">5</property> - <property name="visible">True</property> - <property name="homogeneous">True</property> - <property name="spacing">5</property> - - <child> - <widget class="GtkLabel" id="label8"> - <property name="visible">True</property> - <property name="label" translatable="yes">_User name</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label9"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Password</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label10"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Host (host:port)</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label11"> - <property name="visible">True</property> - <property name="label" translatable="yes">Destination _file</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vbox6"> - <property name="border_width">5</property> - <property name="visible">True</property> - <property name="homogeneous">True</property> - <property name="spacing">5</property> - - <child> - <widget class="GtkEntry" id="scpNameEntry"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">•</property> - <property name="activates_default">False</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkEntry" id="scpPasswordEntry"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">False</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">•</property> - <property name="activates_default">False</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkEntry" id="scpHostEntry"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">•</property> - <property name="activates_default">False</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkEntry" id="scpDestEntry"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">•</property> - <property name="activates_default">False</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="tab_expand">False</property> - <property name="tab_fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label18"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="type">tab</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - </child> -</widget> - -</glade-interface>
This involves getting rid of most of the real code out of this file, adding a minimal subclass of the ExceptionHandler class to do the copying and pdb setup anaconda needs, and calling the install method from within anaconda. We also need to no longer call handleException from elsewhere in anaconda. That method no longer exists. --- anaconda | 6 +- exception.py | 688 +++++++--------------------------------------------------- packages.py | 3 +- 3 files changed, 80 insertions(+), 617 deletions(-)
diff --git a/anaconda b/anaconda index aef0c95..3474d9a 100755 --- a/anaconda +++ b/anaconda @@ -546,7 +546,6 @@ if __name__ == "__main__": setupPythonUpdates()
import signal, string, isys, iutil, time - from exception import handleException import dispatch import warnings import vnc @@ -958,14 +957,13 @@ if __name__ == "__main__": kickstart.setSteps(anaconda)
# comment out the next line to make exceptions non-fatal - sys.excepthook = lambda type, value, tb, anaconda=anaconda: handleException(anaconda, (type, value, tb)) + from exception import initExceptionHandling + initExceptionHandling(anaconda)
try: anaconda.intf.run(anaconda) except SystemExit, code: anaconda.intf.shutdown() - except: - handleException(anaconda, sys.exc_info())
if anaconda.isKickstart and anaconda.id.ksdata.reboot.eject: for drive in anaconda.id.storage.devicetree.devices.values(): diff --git a/exception.py b/exception.py index dffb7cb..f6ce416 100644 --- a/exception.py +++ b/exception.py @@ -21,632 +21,98 @@ # Erik Troan ewt@redhat.com # Chris Lumens clumens@redhat.com # - -from constants import * -from filer import * -from network import hasActiveNetDev +from meh.handler import * +from meh.dump import * import isys import sys import os import shutil import signal -import traceback -import inspect -import iutil -import types -import bdb -from string import joinfields -from cPickle import Pickler from flags import flags import kickstart
-import gettext -_ = lambda x: gettext.ldgettext("anaconda", x) - -import logging -log = logging.getLogger("anaconda") - -class AnacondaExceptionDump: - def __init__(self, type, value, stack): - self.type = type - self.value = value - - # this isn't used, but it's an option if we want to leave the - # two instantiations of this class as they are instead of - # passing in a stack - if inspect.istraceback(stack): - stack = inspect.getinnerframes(stack) - - self.stack = stack - - self.tbFile = None - - self._dumpHash = {} - - # Reverse the order that tracebacks are printed so people will hopefully quit - # giving us the least useful part of the exception in bug reports. - def __str__(self): - lst = self.format_stack() - lst.reverse() - lst.insert(0, "anaconda %s exception report\n" % os.getenv("ANACONDAVERSION")) - lst.insert(1, 'Traceback (most recent call first):\n') - - if self.type is not None and self.value is not None: - lst.extend(traceback.format_exception_only(self.type, self.value)) - - return joinfields(lst, "") - - def format_stack(self): - frames = [] - for (frame, file, lineno, func, ctx, idx) in self.stack: - if type(ctx) == type([]): - code = "".join(ctx) - else: - code = ctx - - frames.append((file, lineno, func, code)) - - return traceback.format_list(frames) - - # Create a string representation of a class and write it to fd. This - # method will recursively handle all attributes of the base given class. - def _dumpClass(self, instance, fd, level=0, parentkey="", skipList=[]): - # protect from loops - try: - if not self._dumpHash.has_key(instance): - self._dumpHash[instance] = None - else: - fd.write("Already dumped\n") - return - except TypeError: - fd.write("Cannot dump object\n") - return - - if (instance.__class__.__dict__.has_key("__str__") or - instance.__class__.__dict__.has_key("__repr__")): - fd.write("%s\n" % (instance,)) - return - fd.write("%s instance, containing members:\n" % - (instance.__class__.__name__)) - pad = ' ' * ((level) * 2) - - for key, value in instance.__dict__.items(): - if key.startswith("_%s__" % instance.__class__.__name__): - continue - - if parentkey != "": - curkey = parentkey + "." + key - else: - curkey = key - - # Don't dump objects that are in our skip list, though ones that are - # None are probably okay. - if eval("instance.%s is not None" % key) and \ - eval("id(instance.%s)" % key) in skipList: - continue - - if type(value) == types.ListType: - fd.write("%s%s: [" % (pad, curkey)) - first = 1 - for item in value: - if not first: - fd.write(", ") - else: - first = 0 - if type(item) == types.InstanceType: - self._dumpClass(item, fd, level + 1, skipList=skipList) - else: - fd.write("%s" % (item,)) - fd.write("]\n") - elif type(value) == types.DictType: - fd.write("%s%s: {" % (pad, curkey)) - first = 1 - for k, v in value.items(): - if not first: - fd.write(", ") - else: - first = 0 - if type(k) == types.StringType: - fd.write("'%s': " % (k,)) - else: - fd.write("%s: " % (k,)) - if type(v) == types.InstanceType: - self._dumpClass(v, fd, level + 1, parentkey = curkey, skipList=skipList) - else: - fd.write("%s" % (v,)) - fd.write("}\n") - elif type(value) == types.InstanceType: - fd.write("%s%s: " % (pad, curkey)) - self._dumpClass(value, fd, level + 1, parentkey=curkey, skipList=skipList) - else: - fd.write("%s%s: %s\n" % (pad, curkey, value)) - - # Dump the python traceback, internal state, and several files to the given - # file descriptor. - def dump (self, fd, anaconda): - skipList = [ "anaconda.backend.ayum", - "anaconda.backend.dlpkgs", - "anaconda.id.accounts", - "anaconda.id.bootloader.password", - "anaconda.id.comps", - "anaconda.id.dispatch", - "anaconda.id.hdList", - "anaconda.id.ksdata", - "anaconda.id.instLanguage.font", - "anaconda.id.instLanguage.kbd", - "anaconda.id.instLanguage.info", - "anaconda.id.instLanguage.localeInfo", - "anaconda.id.instLanguage.nativeLangNames", - "anaconda.id.instLanguage.tz", - "anaconda.id.keyboard._mods._modelDict", - "anaconda.id.keyboard.modelDict", - "anaconda.id.storage.encryptionPassphrase", - "anaconda.id.rootPassword", - "anaconda.id.tmpData", - "anaconda.intf.icw.buff", - "anaconda.intf.icw.currentWindow.storage.encryptionPassphrase", - "anaconda.intf.icw.stockButtons", - "dispatch.sack.excludes", - ] - idSkipList = [] - - # Skip any local variables that contain these words - localSkipList = [ "passphrase", "password" ] - - # Catch attributes that do not exist at the time we do the exception dump - # and ignore them. - for k in skipList: - try: - eval("idSkipList.append(id(%s))" % k) - except: - pass - - p = Pickler(fd) - - fd.write(str(self)) - - if self.stack: - frame = self.stack[-1][0] - fd.write ("\nLocal variables in innermost frame:\n") +class AnacondaExceptionHandler(ExceptionHandler): + def postWriteHook(self, (ty, value, tb), anaconda): + # See if /mnt/sysimage is present and put exception there as well + if os.access("/mnt/sysimage/root", os.X_OK): try: - for (key, value) in frame.f_locals.items(): - loweredKey = key.lower() - if len(filter(lambda s: loweredKey.find(s) != -1, localSkipList)) > 0: - continue - - fd.write ("%s: %s\n" % (key, value)) + shutil.copyfile("/tmp/anacdump.txt", "/mnt/sysimage/root/anacdump.txt") except: + log.error("Failed to copy anacdump.txt to /mnt/sysimage/root") pass
+ # run kickstart traceback scripts (if necessary) try: - fd.write("\n\n") - self._dumpClass(anaconda, fd, skipList=idSkipList) + if anaconda.isKickstart: + kickstart.runTracebackScripts(anaconda) except: - fd.write("\nException occurred during state dump:\n") - traceback.print_exc(None, fd) - - for file in ("/tmp/syslog", "/tmp/anaconda.log", - "/tmp/lvmout", "/tmp/resize.out", - "/tmp/program.log", "/tmp/storage.log", - "/tmp/yum.log", - anaconda.rootPath + "/root/install.log", - anaconda.rootPath + "/root/upgrade.log", - "/proc/cmdline"): - try: - f = open(file, 'r') - line = "\n\n%s:\n" % (file,) - while line: - fd.write(line) - line = f.readline() - f.close() - except IOError: - pass - except: - fd.write("\nException occurred during %s file copy:\n" % (file,)) - traceback.print_exc(None, fd) - - def hash(self): - import hashlib - s = "" - - for (file, lineno, func, text) in [f[1:5] for f in self.stack]: - if type(text) == type([]): - text = "".join(text) - s += "%s %s %s\n" % (os.path.basename(file), func, text) - - return hashlib.sha256(s).hexdigest() - - def write(self, anaconda): - self.tbFile = "/tmp/anacdump.txt" - fd = open(self.tbFile, "w") - self.dump(fd, anaconda) - fd.close() - -def scpAuthenticate(master, childpid, password): - while 1: - # Read up to password prompt. Propagate OSError exceptions, which - # can occur for anything that causes scp to immediately die (bad - # hostname, host down, etc.) - buf = os.read(master, 4096) - if buf.lower().find("password: ") != -1: - os.write(master, password+"\n") - # read the space and newline that get echoed back - os.read(master, 2) - break - - while 1: - buf = "" - try: - buf = os.read(master, 4096) - except (OSError, EOFError): - break - - (pid, childstatus) = os.waitpid (childpid, 0) - return childstatus - -# Save the traceback to a remote system via SCP. Returns success or not. -def copyExceptionToRemote(intf, scpInfo): - import pty - - (user, password, host, path) = scpInfo - - if host.find(":") != -1: - (host, port) = host.split(":") - - # Try to convert the port to an integer just as a check to see - # if it's a valid port number. If not, they'll get a chance to - # correct the information when scp fails. - try: - int(port) - portArgs = ["-P", port] - except ValueError: - portArgs = [] - else: - portArgs = [] - - # Thanks to Will Woods wwoods@redhat.com for the scp control - # here and in scpAuthenticate. - - # Fork ssh into its own pty - (childpid, master) = pty.fork() - if childpid < 0: - log.critical("Could not fork process to run scp") - return False - elif childpid == 0: - # child process - run scp - args = ["scp", "-oNumberOfPasswordPrompts=1", - "-oStrictHostKeyChecking=no"] + portArgs + \ - ["/tmp/anacdump.txt", "%s@%s:%s" % (user, host, path)] - os.execvp("scp", args) - - # parent process - try: - childstatus = scpAuthenticate(master, childpid, password) - except OSError: - return False - - os.close(master) - - if os.WIFEXITED(childstatus) and os.WEXITSTATUS(childstatus) == 0: - return True - else: - return False - -# Save the traceback to a removable storage device, such as a floppy disk -# or a usb/firewire drive. If there's no filesystem on the disk/partition, -# write a vfat one. -# Returns success or not. -def copyExceptionToDisk(anaconda, device): - # in test mode have save to disk option just copy to new name - if not flags.setupFilesystems: - try: - shutil.copyfile("/tmp/anacdump.txt", "/tmp/test-anacdump.txt") - except: - log.error("Failed to copy anacdump.txt to /tmp/test-anacdump.txt") pass
- anaconda.intf.__del__ () - return True - - try: - fd = os.open(device, os.O_RDONLY) - except: - return False - - os.close(fd) - - fstype = isys.readFSType(device) - if fstype == None: - fstype = 'vfat' - try: - isys.mount(device, "/tmp/crash", fstype) - except SystemError: - if fstype != 'vfat': - return False - cmd = "/usr/sbin/mkdosfs" - - if os.access("/sbin/mkdosfs", os.X_OK): - cmd = "/sbin/mkdosfs" - - iutil.execWithRedirect (cmd, [device], stdout = '/dev/tty5', - stderr = '/dev/tty5') - - try: - isys.mount(device, "/tmp/crash", fstype) - except SystemError: - return False - - # copy trace dump we wrote to local storage to disk - try: - shutil.copyfile("/tmp/anacdump.txt", "/tmp/crash/anacdump.txt") - except: - log.error("Failed to copy anacdump.txt to device %s" % device) - return False - - isys.umount("/tmp/crash") - return True - -def saveToBugzilla(anaconda, exn, dest): - import bugzilla, xmlrpclib - import product, rpmUtils - - def withBugzillaDo(bz, fn): - try: - retval = fn(bz) - return retval - except CommunicationError, e: - msg = _("Your bug could not be filed due to the following error " - "when communicating with bugzilla:\n\n%s" % str(e)) - except (TypeError, ValueError), e: - msg = _("Your bug could not be filed due to bad information in " - "the bug fields. This is most likely an error in " - "anaconda:\n\n%s" % str(e)) - - anaconda.intf.messageWindow(_("Unable To File Bug"), msg) - return None - - filer = anaconda.id.instClass.bugFiler - - if not filer.supportsFiling() or not filer.bugUrl: - anaconda.intf.messageWindow(_("Bug Filing Not Supported"), - _("This distribution does not provide a " - "supported bug filing system, so you " - "cannot save your exception this way.")) - return False - - if dest[0].strip() == "" or dest[1].strip() == "" or dest[2].strip() == "": - anaconda.intf.messageWindow(_("Invalid Bug Information"), - _("Please provide a valid username, " - "password, and a short description of " - "the bug.")) - return False - - hash = exn.hash() - - if not exn.tbFile: - exn.write(anaconda) - - try: - cred = withBugzillaDo(filer, lambda b: b.login(dest[0], dest[1])) - except LoginError: - anaconda.intf.messageWindow(_("Unable To Login"), - _("There was an error logging into %s " - "using the provided username and " - "password.") % product.bugUrl) - return False - - # Are there any existing bugs with this hash value? If so we will just - # add this traceback to the bug report and put the reporter on the CC - # list. Otherwise, we need to create a new bug. - wb = "anaconda_trace_hash:%s" % hash - buglist = withBugzillaDo(filer, lambda b: b.query({'status_whiteboard': wb, - 'status_whiteboard_type':'allwordssubstr', - 'bug_status': []})) - if buglist is None: - return False - - if len(buglist) == 0: - bug = withBugzillaDo(filer, lambda b: b.createbug(product=filer.getproduct(product.productName), - component="anaconda", - version=filer.getversion(product.productVersion, - product.productName), - platform=rpmUtils.arch.getBaseArch(), - bug_severity="medium", - priority="medium", - op_sys="Linux", - bug_file_loc="http://", - summary=dest[2], - comment="The following was filed automatically by anaconda:\n%s" % str(exn), - status_whiteboard=wb)) - if bug is None: - return False - - withBugzillaDo(bug, lambda b: b.attachfile(exn.tbFile, - "Attached traceback automatically from anaconda.", - contenttype="text/plain", filename="anacdump.txt")) - - # Tell the user we created a new bug for them and that they should - # go add a descriptive comment. - anaconda.intf.messageWindow(_("Bug Created"), - _("A new bug has been created with the traceback attached. " - "Please add additional information such as what you were doing " - "when you encountered the bug, screenshots, and any other " - "relevant information to the following bug:\n\n%s/%s") % (bugzillaUrl, bug.id()), - type="custom", custom_icon="info", - custom_buttons=[_("_Exit installer")]) - sys.exit(0) - else: - bug = buglist[0] - withBugzillaDo(bug, lambda b: b.attachfile(exn.tbFile, - "Attached traceback automatically from anaconda.", - contenttype="text/plain", filename="anacdump.txt")) - withBugzillaDo(bug, lambda b: b.addCC(dest[0])) - - # Tell the user which bug they've been CC'd on and that they should - # go add a descriptive comment. - anaconda.intf.messageWindow(_("Bug Updated"), - _("A bug with this profile has already been filed. Your account " - "has been added to the CC list and your traceback added as a " - "comment. Please review the following bug, and add additional " - "information if necessary:\n\n%s/%s") % (bugzillaUrl, bug.id()), - type="custom", custom_icon="info", - custom_buttons=[_("_Exit installer")]) - sys.exit(0) - -def runSaveDialog(anaconda, exn): - saveWin = anaconda.intf.saveExceptionWindow(anaconda, exn.tbFile) - if not saveWin: - anaconda.intf.__del__() + def runDebug(self, (ty, value, tb)): + isys.vtActivate(1) + self.intf.__del__ () + + pidfl = "/tmp/vncshell.pid" + if os.path.exists(pidfl) and os.path.isfile(pidfl): + pf = open(pidfl, "r") + for pid in pf.readlines(): + if not int(pid) == os.getpid(): + os.kill(int(pid), signal.SIGKILL) + pf.close() + + if not flags.test: + os.open("/dev/console", os.O_RDWR) # reclaim stdin + os.dup2(0, 1) # reclaim stdout + os.dup2(0, 2) # reclaim stderr + # ^ + # | + # +------ dup2 is magic, I tells ya! + + # bring back the echo + import termios + si = sys.stdin.fileno() + attr = termios.tcgetattr(si) + attr[3] = attr[3] & termios.ECHO + termios.tcsetattr(si, termios.TCSADRAIN, attr) + + print("\nEntering debugger...") + import pdb + pdb.post_mortem (tb) os.kill(os.getpid(), signal.SIGKILL)
- while 1: - saveWin.run() - rc = saveWin.getrc() - - if rc == EXN_OK: - if saveWin.saveToDisk(): - device = saveWin.getDest() - cpSucceeded = copyExceptionToDisk(anaconda, device) - - if cpSucceeded: - anaconda.intf.messageWindow(_("Dump Written"), - _("System state has been successfully written to " - "the disk. The installer will now exit."), - type="custom", custom_icon="info", - custom_buttons=[_("_Exit installer")]) - sys.exit(0) - else: - anaconda.intf.messageWindow(_("Dump Not Written"), - _("There was a problem writing the system state to the " - "disk.")) - continue - elif saveWin.saveToLocal(): - dest = saveWin.getDest() - try: - shutil.copyfile(exn.tbFile, "%s/InstallError.txt" %(dest,)) - anaconda.intf.messageWindow(_("Dump Written"), - _("System state has been successfully written to " - "the disk. The installer will now exit."), - type="custom", custom_icon="info", - custom_buttons=[_("_Exit installer")]) - sys.exit(0) - except Exception, e: - log.error("Failed to copy %s to %s/anacdump.txt: %s" %(exn.tbFile, dest, e)) - else: - anaconda.intf.messageWindow(_("Dump Not Written"), - _("There was a problem writing the system state to the " - "disk.")) - continue - elif saveWin.saveToRemote(): - if not hasActiveNetDev(): - if not anaconda.intf.enableNetwork(anaconda): - anaconda.intf.messageWindow(_("No Network Available"), - _("Cannot save a bug report since there is no " - "active networking device available.")) - continue - - scpInfo = saveWin.getDest() - scpSucceeded = copyExceptionToRemote(anaconda.intf, scpInfo) - - if scpSucceeded: - anaconda.intf.messageWindow(_("Dump Written"), - _("System state has been successfully transferred to " - "the remote host. The installer will now exit."), - type="custom", custom_icon="info", - custom_buttons=[_("_Exit installer")]) - sys.exit(0) - else: - anaconda.intf.messageWindow(_("Dump Not Written"), - _("There was a problem transferring the system state " - "to the remote host.")) - continue - else: - if not hasActiveNetDev(): - if not anaconda.intf.enableNetwork(anaconda): - anaconda.intf.messageWindow(_("No Network Available"), - _("Cannot save a bug report since there is no " - "active networking device available.")) - continue - - if not saveToBugzilla(anaconda, exn, saveWin.getDest()): - continue - elif rc == EXN_CANCEL: - break - - saveWin.pop() - -def handleException(anaconda, (type, value, tb)): - if isinstance(value, bdb.BdbQuit): - sys.exit(1) - - # restore original exception handler - sys.excepthook = sys.__excepthook__ - - # convert the traceback to a stack - stack = inspect.getinnerframes(tb) - - # Save the exception file to local storage first. - exn = AnacondaExceptionDump(type, value, stack) - exn.write(anaconda) - text = str(exn) - - # see if /mnt/sysimage is present and put exception there as well - if os.access("/mnt/sysimage/root", os.X_OK): - try: - shutil.copyfile("/tmp/anacdump.txt", "/mnt/sysimage/root/anacdump.txt") - except: - log.error("Failed to copy anacdump.txt to /mnt/sysimage/root") - pass - - # run kickstart traceback scripts (if necessary) - try: - if anaconda.isKickstart: - kickstart.runTracebackScripts(anaconda) - except: - pass - - mainWin = anaconda.intf.mainExceptionWindow(text, exn.tbFile) - if not mainWin: - anaconda.intf.__del__() - os.kill(os.getpid(), signal.SIGKILL) - - while 1: - mainWin.run() - rc = mainWin.getrc() - - if rc == EXN_OK: - anaconda.intf.__del__ () - os.kill(os.getpid(), signal.SIGKILL) - elif rc == EXN_DEBUG: - anaconda.intf.__del__ () - print(text) - - pidfl = "/tmp/vncshell.pid" - if os.path.exists(pidfl) and os.path.isfile(pidfl): - pf = open(pidfl, "r") - for pid in pf.readlines(): - if not int(pid) == os.getpid(): - os.kill(int(pid), signal.SIGKILL) - pf.close() - - if not flags.test: - os.open("/dev/console", os.O_RDWR) # reclaim stdin - os.dup2(0, 1) # reclaim stdout - os.dup2(0, 2) # reclaim stderr - # ^ - # | - # +------ dup2 is magic, I tells ya! - - # bring back the echo - import termios - si = sys.stdin.fileno() - attr = termios.tcgetattr(si) - attr[3] = attr[3] & termios.ECHO - termios.tcsetattr(si, termios.TCSADRAIN, attr) - - print("\nEntering debugger...") - import pdb - pdb.post_mortem (tb) - os.kill(os.getpid(), signal.SIGKILL) - elif rc == EXN_SAVE: - runSaveDialog(anaconda, exn) +def initExceptionHandling(anaconda): + conf = Config(programName="anaconda", programVersion=os.environ["ANACONDAVERSION"], + bugFiler=anaconda.id.instClass.bugFiler, + attrSkipList=[ "anaconda.backend.ayum", + "anaconda.backend.dlpkgs", + "anaconda.id.accounts", + "anaconda.id.bootloader.password", + "anaconda.id.comps", + "anaconda.id.dispatch", + "anaconda.id.hdList", + "anaconda.id.ksdata", + "anaconda.id.instLanguage.font", + "anaconda.id.instLanguage.kbd", + "anaconda.id.instLanguage.info", + "anaconda.id.instLanguage.localeInfo", + "anaconda.id.instLanguage.nativeLangNames", + "anaconda.id.instLanguage.tz", + "anaconda.id.keyboard._mods._modelDict", + "anaconda.id.keyboard.modelDict", + "anaconda.id.storage.encryptionPassphrase", + "anaconda.id.rootPassword", + "anaconda.id.tmpData", + "anaconda.intf.icw.buff", + "anaconda.intf.icw.currentWindow.storage.encryptionPassphrase", + "anaconda.intf.icw.stockButtons", + "dispatch.sack.excludes", + ], + localSkipList=[ "passphrase", "password" ], + fileList=[ "/tmp/syslog", "/tmp/anaconda.log", "/tmp/lvmout", + "/tmp/resize.out", "/tmp/program.log", + "/tmp/storage.log", "/tmp/yum.log", + anaconda.rootPath + "/root/install.log", + anaconda.rootPath + "/root/upgrade.log", + "/proc/cmdline"]) + handler = AnacondaExceptionHandler(conf, anaconda.intf, ReverseExceptionDump) + handler.install(anaconda) diff --git a/packages.py b/packages.py index 0721923..4e90b7c 100644 --- a/packages.py +++ b/packages.py @@ -33,7 +33,6 @@ import string import language import shutil import traceback -from exception import handleException from flags import flags from product import * from constants import * @@ -189,7 +188,7 @@ def turnOnFilesystems(anaconda): custom_buttons = [_("_File Bug"), _("_Exit installer")])
if rc == 0: - handleException(anaconda, sys.exc_info()) + raise elif rc == 1: sys.exit(1)
--- installclass.py | 6 ++++-- installclasses/fedora.py | 6 ++++-- installclasses/rhel.py | 6 ++++-- 3 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/installclass.py b/installclass.py index d0f535d..c16cb04 100644 --- a/installclass.py +++ b/installclass.py @@ -31,7 +31,8 @@ import types from instdata import InstallData
from constants import * -from filer import * +from meh.filer import * +from product import * from storage.partspec import *
import gettext @@ -56,7 +57,8 @@ class BaseInstallClass(object): # default to showing the upgrade option showUpgrade = True
- bugFiler = AbstractFiler() + bugFiler = AbstractFiler(product.bugUrl, product.bugUrl, + product.productVersion, product.productName)
# list of of (txt, grplist) tuples for task selection screen tasks = [] diff --git a/installclasses/fedora.py b/installclasses/fedora.py index 98002ed..c27767e 100644 --- a/installclasses/fedora.py +++ b/installclasses/fedora.py @@ -20,7 +20,7 @@ from installclass import BaseInstallClass from constants import * from product import * -from filer import * +from meh.filer import * from flags import flags import os, types import iutil @@ -50,7 +50,9 @@ class InstallClass(BaseInstallClass): (N_("Software Development"), ["development-libs", "development-tools", "gnome-software-development", "x-software-development"],), (N_("Web Server"), ["web-server"])]
- bugFiler = BugzillaFiler(bugUrl="https://bugzilla.redhat.com/xmlrpc.cgi", + bugFiler = BugzillaFiler("https://bugzilla.redhat.com/xmlrpc.cgi", + "https://bugzilla.redhat.com/", + product.productVersion, product.productName, develVersion="rawhide", defaultProduct="Fedora")
def getPackagePaths(self, uri): diff --git a/installclasses/rhel.py b/installclasses/rhel.py index 5906c8e..0cb291f 100644 --- a/installclasses/rhel.py +++ b/installclasses/rhel.py @@ -20,7 +20,7 @@ from installclass import BaseInstallClass from constants import * from product import * -from filer import * +from meh.filer import * from flags import flags import os import iutil @@ -79,7 +79,9 @@ class InstallClass(BaseInstallClass): skipkeytext = N_("If you cannot locate the Installation Number, consult " "http://www.redhat.com/InstNum/")
- bugFiler = BugzillaFiler(bugUrl="https://bugzilla.redhat.com/xmlrpc.cgi") + bugFiler = BugzillaFiler("https://bugzilla.redhat.com/xmlrpc.cgi", + "https://bugzilla.redhat.com/", + product.productVersion, product.productName)
def setInstallData(self, anaconda): BaseInstallClass.setInstallData(self, anaconda)
--- gui.py | 160 ---------------------------------------------------------------- 1 files changed, 0 insertions(+), 160 deletions(-)
diff --git a/gui.py b/gui.py index 3d75ae1..03c5af4 100755 --- a/gui.py +++ b/gui.py @@ -735,124 +735,6 @@ class PassphraseEntryWindow: def destroy(self): self.win.destroy()
-class SaveExceptionWindow: - def __init__(self, anaconda, longTracebackFile=None, screen=None): - exnxml = gtk.glade.XML(findGladeFile("exnSave.glade"), domain="anaconda") - - self.bugzillaNameEntry = exnxml.get_widget("bugzillaNameEntry") - self.bugzillaPasswordEntry = exnxml.get_widget("bugzillaPasswordEntry") - self.bugDesc = exnxml.get_widget("bugDesc") - - self.scpNameEntry = exnxml.get_widget("scpNameEntry") - self.scpPasswordEntry = exnxml.get_widget("scpPasswordEntry") - self.scpHostEntry = exnxml.get_widget("scpHostEntry") - self.scpDestEntry = exnxml.get_widget("scpDestEntry") - - self.notebook = exnxml.get_widget("destNotebook") - self.destCombo = exnxml.get_widget("destCombo") - - self.diskCombo = exnxml.get_widget("diskCombo") - self.localChooser = exnxml.get_widget("localChooser") - self.win = exnxml.get_widget("saveDialog") - - self.destCombo.connect("changed", self.combo_changed) - - self.destCombo.insert_text(2, _("Bugzilla (%s)") % bugUrl) - - cell = gtk.CellRendererText() - self.diskCombo.pack_start(cell, True) - self.diskCombo.set_attributes(cell, text=1) - - store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING) - - dests = [] - if anaconda.id.storage.devicetree.populated: - try: - dests = anaconda.id.storage.exceptionDisks() - except Exception as e: - log.error("Error when probing exception disks: %s" % e) - else: - log.info("Storage configuration unknown; not probing for " - "exception disks") - - if flags.livecdInstall: - self.destCombo.remove_text(0) - self.destCombo.set_active(0) - self.notebook.remove_page(0) - self.notebook.set_current_page(0) - elif len(dests) > 0: - for d in dests: - iter = store.append(None) - store[iter] = (d[0], "%s - %s" % (d[0], d[1])) - - self.diskCombo.set_model(store) - self.diskCombo.set_active(0) - self.diskCombo.set_sensitive(True) - - self.destCombo.remove_text(1) - self.destCombo.set_active(0) - self.notebook.remove_page(1) - self.notebook.set_current_page(0) - else: - iter = store.append(None) - store[iter] = (None, _("No devices found")) - - self.diskCombo.set_model(store) - self.diskCombo.set_active(0) - self.diskCombo.set_sensitive(False) - - self.destCombo.remove_text(1) - self.destCombo.set_active(1) - self.notebook.remove_page(1) - self.notebook.set_current_page(1) - - addFrame(self.win) - self.win.show() - self.window = self.win - - def combo_changed(self, args): - self.notebook.set_current_page(self.destCombo.get_active()) - - def getrc(self): - if self.rc == gtk.RESPONSE_OK: - return EXN_OK - elif self.rc == gtk.RESPONSE_CANCEL: - return EXN_CANCEL - - def getDest(self): - if self.saveToDisk(): - active = self.diskCombo.get_active() - if active < 0 or self.diskCombo.get_model()[active][0] is None: - return None - - return self.diskCombo.get_model()[active][0] - elif self.saveToLocal(): - return self.localChooser.get_filename() - elif self.saveToRemote(): - return map(lambda e: e.get_text(), [self.scpNameEntry, - self.scpPasswordEntry, - self.scpHostEntry, - self.scpDestEntry]) - else: - return map(lambda e: e.get_text(), [self.bugzillaNameEntry, - self.bugzillaPasswordEntry, - self.bugDesc]) - - def pop(self): - self.window.destroy() - - def run(self): - self.rc = self.window.run () - - def saveToDisk(self): - return self.destCombo.get_active() == 0 and not flags.livecdInstall - - def saveToLocal(self): - return self.destCombo.get_active() == 0 and flags.livecdInstall - - def saveToRemote(self): - return self.destCombo.get_active() == 2 - class MessageWindow: def getrc (self): return self.rc @@ -1065,48 +947,6 @@ class DetailedMessageWindow(MessageWindow): if run: self.run(destroyAfterRun)
-class MainExceptionWindow(DetailedMessageWindow): - def __init__ (self, shortTraceback, longTracebackFile=None, screen=None): - longText=None - - if longTracebackFile: - try: - f = open(longTracebackFile) - longText = f.readlines() - f.close() - except: - pass - - if flags.livecdInstall: - custom_buttons = ["gtk-save", _("Exit installer")] - else: - custom_buttons = [_("Debug"), "gtk-save", _("Exit installer")] - - DetailedMessageWindow.__init__(self, _("Exception Occurred"), - exceptionText, longText=longText, - type="custom", run=False, - custom_buttons=custom_buttons, - custom_icon=findPixmap("exception.png")) - - def getrc (self): - if flags.livecdInstall: - if self.rc == 0: - return EXN_SAVE - elif self.rc == 1: - return EXN_OK - else: - if self.rc == 0: - try: - # switch to VC1 so we can debug - isys.vtActivate (1) - except SystemError: - pass - return EXN_DEBUG - elif self.rc == 1: - return EXN_SAVE - elif self.rc == 2: - return EXN_OK - class EntryWindow(MessageWindow): def __init__ (self, title, text, prompt, entrylength = None): mainWindow = None
--- gui.py | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/gui.py b/gui.py index 03c5af4..0e4a455 100755 --- a/gui.py +++ b/gui.py @@ -1073,12 +1073,16 @@ class InstallInterface: return rc
def mainExceptionWindow(self, shortText, longTextFile): + from meh.ui.gui import MainExceptionWindow log.critical(shortText) win = MainExceptionWindow (shortText, longTextFile) + addFrame(win.dialog) return win
- def saveExceptionWindow(self, anaconda, longTextFile): - win = SaveExceptionWindow (anaconda, longTextFile) + def saveExceptionWindow(self, longTextFile): + from meh.ui.gui import SaveExceptionWindow + win = SaveExceptionWindow (self.anaconda, longTextFile) + addFrame(win.dialog) return win
def getInstallKey(self, anaconda, key = ""):
--- gui.py | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/gui.py b/gui.py index 0e4a455..a4bd75c 100755 --- a/gui.py +++ b/gui.py @@ -1085,6 +1085,17 @@ class InstallInterface: addFrame(win.dialog) return win
+ def exitWindow(self, title, text): + if self.icw: + parent = self.icw.window + else: + parent = None + + rc = MessageWindow (title, text, type="custom", + custom_icon="info", parent=parent, + custom_buttons=[_("_Exit installer")]).getrc() + return rc + def getInstallKey(self, anaconda, key = ""): d = InstallKeyWindow(anaconda, key) rc = d.run()
--- gui.py | 22 +++++++++++----------- iw/task_gui.py | 6 +++--- packages.py | 2 +- text.py | 23 ++++++++++++----------- yuminstall.py | 14 +++++++------- 5 files changed, 34 insertions(+), 33 deletions(-)
diff --git a/gui.py b/gui.py index a4bd75c..7f56036 100755 --- a/gui.py +++ b/gui.py @@ -998,11 +998,11 @@ class InstallInterface: def resume(self): pass
- def enableNetwork(self, anaconda): - if len(anaconda.id.network.netdevices) == 0: + def enableNetwork(self): + if len(self.anaconda.id.network.netdevices) == 0: return False from netconfig_dialog import NetworkConfigurator - net = NetworkConfigurator(anaconda.id.network) + net = NetworkConfigurator(self.anaconda.id.network) ret = net.run() net.destroy()
@@ -1035,21 +1035,21 @@ class InstallInterface: custom_buttons, custom_icon, run=True, parent=parent).getrc() return rc
- def createRepoWindow(self, anaconda): + def createRepoWindow(self): from task_gui import RepoCreator - dialog = RepoCreator(anaconda) + dialog = RepoCreator(self.anaconda) dialog.createDialog() dialog.run()
- def editRepoWindow(self, anaconda, repoObj): + def editRepoWindow(self, repoObj): from task_gui import RepoEditor - dialog = RepoEditor(anaconda, repoObj) + dialog = RepoEditor(self.anaconda, repoObj) dialog.createDialog() dialog.run()
- def methodstrRepoWindow(self, anaconda): + def methodstrRepoWindow(self): from task_gui import RepoMethodstrEditor - dialog = RepoMethodstrEditor(anaconda) + dialog = RepoMethodstrEditor(self.anaconda) dialog.createDialog() return dialog.run()
@@ -1096,8 +1096,8 @@ class InstallInterface: custom_buttons=[_("_Exit installer")]).getrc() return rc
- def getInstallKey(self, anaconda, key = ""): - d = InstallKeyWindow(anaconda, key) + def getInstallKey(self, key = ""): + d = InstallKeyWindow(self.anaconda, key) rc = d.run() if rc == gtk.RESPONSE_CANCEL: ret = None diff --git a/iw/task_gui.py b/iw/task_gui.py index a91209a..9dd044d 100644 --- a/iw/task_gui.py +++ b/iw/task_gui.py @@ -488,7 +488,7 @@ class TaskWindow(InstallWindow): return
if repo.needsNetwork() and not network.hasActiveNetDev(): - if not self.anaconda.intf.enableNetwork(self.anaconda): + if not self.anaconda.intf.enableNetwork(): return gtk.RESPONSE_CANCEL
dialog = RepoEditor(self.anaconda, repo) @@ -504,7 +504,7 @@ class TaskWindow(InstallWindow): return gtk.RESPONSE_CANCEL
if dialog.repo.needsNetwork() and not network.hasActiveNetDev(): - if not self.anaconda.intf.enableNetwork(self.anaconda): + if not self.anaconda.intf.enableNetwork(): return gtk.RESPONSE_CANCEL
s = self.xml.get_widget("repoList").get_model() @@ -536,7 +536,7 @@ class TaskWindow(InstallWindow):
if not wasChecked: if repo.needsNetwork() and not network.hasActiveNetDev(): - if not self.anaconda.intf.enableNetwork(self.anaconda): + if not self.anaconda.intf.enableNetwork(): return
repo.enable() diff --git a/packages.py b/packages.py index 4e90b7c..dda98c4 100644 --- a/packages.py +++ b/packages.py @@ -366,7 +366,7 @@ def regKeyScreen(anaconda): anaconda.id.instClass.skipkey = False
while not anaconda.id.instClass.skipkey: - rc = anaconda.intf.getInstallKey(anaconda, key) + rc = anaconda.intf.getInstallKey(key) if rc is None and anaconda.dispatch.canGoBack(): return DISPATCH_BACK elif rc is None: diff --git a/text.py b/text.py index fada4e2..7077be8 100644 --- a/text.py +++ b/text.py @@ -480,11 +480,11 @@ class InstallInterface: return self.messageWindow(title, text, type, default, custom_icon, custom_buttons)
- def createRepoWindow(self, anaconda): + def createRepoWindow(self): self.messageWindow(_("Error"), _("Repository editing is not available in text mode."))
- def editRepoWindow(self, anaconda, repoObj): + def editRepoWindow(self, repoObj): self.messageWindow(_("Error"), _("Repository editing is not available in text mode."))
@@ -509,16 +509,16 @@ class InstallInterface: w.pop() return (passphrase, isglobal)
- def enableNetwork(self, anaconda): - if len(anaconda.id.network.netdevices) == 0: + def enableNetwork(self): + if len(self.anaconda.id.network.netdevices) == 0: return False from netconfig_text import NetworkConfiguratorText - w = NetworkConfiguratorText(self.screen, anaconda) + w = NetworkConfiguratorText(self.screen, self.anaconda) ret = w.run() return ret != INSTALL_BACK
- def getInstallKey(self, anaconda, key = ""): - ic = anaconda.id.instClass + def getInstallKey(self, key = ""): + ic = self.anaconda.id.instClass keyname = _(ic.instkeyname) if keyname is None: keyname = _("Installation Key") @@ -532,7 +532,7 @@ class InstallInterface:
radio = RadioGroup() - keyradio = radio.add(keyname, "key", int(not anaconda.id.instClass.skipkey)) + keyradio = radio.add(keyname, "key", int(not self.anaconda.id.instClass.skipkey)) keyentry = Entry(24) keyentry.set(key)
@@ -545,7 +545,7 @@ class InstallInterface: if ic.allowinstkeyskip: skipradio = radio.add(_("Skip entering %(instkey)s") % {"instkey": keyname}, "skip", - int(anaconda.id.instClass.skipkey)) + int(self.anaconda.id.instClass.skipkey)) g.add(skipradio, 0, 2)
bb = ButtonBar(self.screen, [ TEXT_OK_BUTTON, TEXT_BACK_BUTTON ]) @@ -577,8 +577,8 @@ class InstallInterface: exnWin = MainExceptionWindow(shortText, longTextFile, self.screen) return exnWin
- def saveExceptionWindow(self, anaconda, longTextFile): - win = SaveExceptionWindow (anaconda, longTextFile, self.screen) + def saveExceptionWindow(self, longTextFile): + win = SaveExceptionWindow (self.anaconda, longTextFile, self.screen) return win
def waitWindow(self, title, text): @@ -631,6 +631,7 @@ class InstallInterface: return True
def run(self, anaconda): + self.anaconda = anaconda instLang = anaconda.id.instLanguage
if instLang.getFontFile(instLang.getCurrent()) == "none": diff --git a/yuminstall.py b/yuminstall.py index b13e443..6876463 100644 --- a/yuminstall.py +++ b/yuminstall.py @@ -288,7 +288,7 @@ class AnacondaYum(YumSorter): "installation repository:\n\n%s\n\nPlease provide the " "correct information for installing %s.") % (e, productName))
- self.anaconda.methodstr = self.anaconda.intf.methodstrRepoWindow(anaconda) + self.anaconda.methodstr = self.anaconda.intf.methodstrRepoWindow()
self.doConfigSetup(root=anaconda.rootPath) self.conf.installonlypkgs = [] @@ -406,7 +406,7 @@ class AnacondaYum(YumSorter):
# Calling _switchImage takes care of mounting /mnt/isodir first. if not network.hasActiveNetDev(): - if not self.anaconda.intf.enableNetwork(self.anaconda): + if not self.anaconda.intf.enableNetwork(): self._baseRepoURL = None return
@@ -416,7 +416,7 @@ class AnacondaYum(YumSorter): self._baseRepoURL = m elif m.startswith("nfs:"): if not network.hasActiveNetDev(): - if not self.anaconda.intf.enableNetwork(self.anaconda): + if not self.anaconda.intf.enableNetwork(): self._baseRepoURL = None
isys.mount(m[4:], self.tree, "nfs") @@ -680,7 +680,7 @@ class AnacondaYum(YumSorter): pkgFile = to_unicode(os.path.basename(package.remote_path))
if package.repo.needsNetwork() and not network.hasActiveNetDev(): - if not self.anaconda.intf.enableNetwork(self.anaconda): + if not self.anaconda.intf.enableNetwork(): return
rc = self.anaconda.intf.messageWindow(_("Error"), @@ -1043,7 +1043,7 @@ reposdir=/etc/anaconda.repos.d,/tmp/updates/anaconda.repos.d,/tmp/product/anacon # know this in advance. if len(filter(lambda r: r.needsNetwork(), self.ayum.repos.listEnabled())) > 0 and \ not network.hasActiveNetDev(): - if not anaconda.intf.enableNetwork(anaconda): + if not anaconda.intf.enableNetwork(): anaconda.intf.messageWindow(_("No Network Available"), _("Some of your software repositories require " "networking, but there was an error enabling the " @@ -1128,7 +1128,7 @@ reposdir=/etc/anaconda.repos.d,/tmp/updates/anaconda.repos.d,/tmp/product/anacon except RepoError, e: waitwin.pop() if repo.needsNetwork() and not network.hasActiveNetDev(): - if anaconda.intf.enableNetwork(anaconda): + if anaconda.intf.enableNetwork(): repo.mirrorlistparsed = False continue
@@ -1156,7 +1156,7 @@ reposdir=/etc/anaconda.repos.d,/tmp/updates/anaconda.repos.d,/tmp/product/anacon sys.exit(0) elif rc == 1: # edit - anaconda.intf.editRepoWindow(anaconda, repo) + anaconda.intf.editRepoWindow(repo) elif rc == 2: # retry, but only if button is present continue
--- pixmaps/exception.png | Bin 4308 -> 0 bytes 1 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 pixmaps/exception.png
diff --git a/pixmaps/exception.png b/pixmaps/exception.png deleted file mode 100644 index 5eb4af420395323e8be1b78165301e216dcfadbb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001
literal 4308 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 C2ylD=
--- anaconda | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/anaconda b/anaconda index 3474d9a..8fc4797 100755 --- a/anaconda +++ b/anaconda @@ -139,7 +139,7 @@ def setupPythonUpdates(): except: pass
- for pypkg in ("block", "rhpl", "yum", "rpmUtils", "urlgrabber", "pykickstart", "parted"): + for pypkg in ("block", "rhpl", "yum", "rpmUtils", "urlgrabber", "pykickstart", "parted", "meh"): # get the libdir. *sigh* if os.access("/usr/lib64/python%s/site-packages/%s" %(pyver, pypkg), os.X_OK):
--- anaconda | 3 +++ gui.py | 11 ++++------- 2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/anaconda b/anaconda index 8fc4797..0db6755 100755 --- a/anaconda +++ b/anaconda @@ -315,6 +315,9 @@ def setupEnvironment(): if os.environ.has_key("LD_PRELOAD"): del os.environ["LD_PRELOAD"]
+ os.environ["GLADEPATH"] = "/tmp/updates/:/tmp/updates/ui/:ui/:/usr/share/anaconda/ui/:/usr/share/python-meh/" + os.environ["PIXMAPPATH"] = "/tmp/updates/pixmaps/:/tmp/updates/:/tmp/product/pixmaps/:/tmp/product/:pixmaps/:/usr/share/anaconda/pixmaps/:/usr/share/pixmaps/:/usr/share/anaconda/:/usr/share/python-meh/" + def setupLoggingFromOpts(opts): if opts.loglevel and logLevelMap.has_key(opts.loglevel): log.setHandlersLevel(logLevelMap[opts.loglevel]) diff --git a/gui.py b/gui.py index 7f56036..0a4ca3b 100755 --- a/gui.py +++ b/gui.py @@ -369,8 +369,8 @@ def addFrame(dialog, title=None, showtitle = 1): dialog.connect ("key-release-event", handleShiftPrintScrnRelease)
def findGladeFile(file): - for dir in ("/tmp/updates/", "/tmp/updates/ui/", "ui/", - "/usr/share/anaconda/ui/"): + path = os.environ.get("GLADEPATH", "./:ui/:/tmp/updates/:/tmp/updates/ui/") + for dir in path.split(":"): fn = dir + file if os.access(fn, os.R_OK): return fn @@ -386,11 +386,8 @@ def getGladeWidget(file, rootwidget, i18ndomain="anaconda"): return (xml, w)
def findPixmap(file): - for dir in ( "/tmp/updates/pixmaps/", "/tmp/updates/", - "/tmp/product/pixmaps/", "/tmp/product/", "pixmaps/", - "/usr/share/anaconda/pixmaps/", - "/usr/share/pixmaps/", - "/usr/share/anaconda/", ""): + path = os.environ.get("PIXMAPPATH", "./:pixmaps/:/tmp/updates/:/tmp/updates/pixmaps/") + for dir in path.split(":"): fn = dir + file if os.access(fn, os.R_OK): return fn
--- installclasses/fedora.py | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/installclasses/fedora.py b/installclasses/fedora.py index c27767e..d3add70 100644 --- a/installclasses/fedora.py +++ b/installclasses/fedora.py @@ -52,8 +52,7 @@ class InstallClass(BaseInstallClass):
bugFiler = BugzillaFiler("https://bugzilla.redhat.com/xmlrpc.cgi", "https://bugzilla.redhat.com/", - product.productVersion, product.productName, - develVersion="rawhide", defaultProduct="Fedora") + product.productVersion, product.productName)
def getPackagePaths(self, uri): if not type(uri) == types.ListType:
--- text.py | 190 +++------------------------------------------------------------ 1 files changed, 8 insertions(+), 182 deletions(-)
diff --git a/text.py b/text.py index 7077be8..fb43360 100644 --- a/text.py +++ b/text.py @@ -139,186 +139,6 @@ class ProgressWindow: g.draw() self.screen.refresh()
-class SaveExceptionWindow: - def __init__(self, anaconda, longTracebackFile=None, screen=None): - self.anaconda = anaconda - self.screen = screen - self._method = "disk" - - def getrc(self): - if self.rc == TEXT_OK_CHECK: - return EXN_OK - elif self.rc == TEXT_CANCEL_CHECK: - return EXN_CANCEL - - def getDest(self): - if self.saveToDisk(): - return self.diskList.current() - elif self.saveToRemote(): - return map(lambda e: e.value(), [self.scpNameEntry, - self.scpPasswordEntry, - self.scpHostEntry, - self.scpDestEntry]) - else: - return map(lambda e: e.value(), [self.bugzillaNameEntry, - self.bugzillaPasswordEntry, - self.bugDesc]) - - def pop(self): - self.screen.popWindow() - self.screen.refresh() - - def runSaveToDisk(self): - toplevel = GridForm(self.screen, _("Save to local disk"), 1, 2) - - buttons = ButtonBar(self.screen, [TEXT_OK_BUTTON, TEXT_CANCEL_BUTTON]) - self.diskList = Listbox(height=3, scroll=1) - - for (dev, desc) in self.dests: - self.diskList.append("/dev/%s - %s" % (dev, desc), dev) - - toplevel.add(self.diskList, 0, 0, (0, 0, 0, 1)) - toplevel.add(buttons, 0, 1, growx=1) - - result = toplevel.run() - return buttons.buttonPressed(result) - - def runSaveToBugzilla(self): - toplevel = GridForm(self.screen, _("Send to bugzilla (%s)") % product.bugUrl, 1, 2) - - buttons = ButtonBar(self.screen, [TEXT_OK_BUTTON, TEXT_CANCEL_BUTTON]) - self.bugzillaNameEntry = Entry(24) - self.bugzillaPasswordEntry = Entry(24, password=1) - self.bugDesc = Entry(24) - - bugzillaGrid = Grid(2, 3) - bugzillaGrid.setField(Label(_("User name")), 0, 0, anchorLeft=1) - bugzillaGrid.setField(self.bugzillaNameEntry, 1, 0) - bugzillaGrid.setField(Label(_("Password")), 0, 1, anchorLeft=1) - bugzillaGrid.setField(self.bugzillaPasswordEntry, 1, 1) - bugzillaGrid.setField(Label(_("Bug Description")), 0, 2, anchorLeft=1) - bugzillaGrid.setField(self.bugDesc, 1, 2) - - toplevel.add(bugzillaGrid, 0, 0, (0, 0, 0, 1)) - toplevel.add(buttons, 0, 1, growx=1) - - result = toplevel.run() - return buttons.buttonPressed(result) - - def runSaveToRemote(self): - toplevel = GridForm(self.screen, _("Send to remote server (scp)"), 1, 2) - - buttons = ButtonBar(self.screen, [TEXT_OK_BUTTON, TEXT_CANCEL_BUTTON]) - self.scpNameEntry = Entry(24) - self.scpPasswordEntry = Entry(24, password=1) - self.scpHostEntry = Entry(24) - self.scpDestEntry = Entry(24) - - scpGrid = Grid(2, 4) - scpGrid.setField(Label(_("User name")), 0, 0, anchorLeft=1) - scpGrid.setField(self.scpNameEntry, 1, 0) - scpGrid.setField(Label(_("Password")), 0, 1, anchorLeft=1) - scpGrid.setField(self.scpPasswordEntry, 1, 1) - scpGrid.setField(Label(_("Host (host:port)")), 0, 2, anchorLeft=1) - scpGrid.setField(self.scpHostEntry, 1, 2) - scpGrid.setField(Label(_("Destination file")), 0, 3, anchorLeft=1) - scpGrid.setField(self.scpDestEntry, 1, 3) - - toplevel.add(scpGrid, 0, 0, (0, 0, 0, 1)) - toplevel.add(buttons, 0, 1, growx=1) - - result = toplevel.run() - return buttons.buttonPressed(result) - - def run(self): - mapping = {"disk": self.runSaveToDisk, - "scp": self.runSaveToRemote, - "bugzilla": self.runSaveToBugzilla} - - toplevel = GridForm(self.screen, _("Save"), 1, 4) - - self.rg = RadioGroup() - self.diskButton = self.rg.add(_("Save to local disk"), "disk", True) - self.bugzillaButton = self.rg.add(_("Send to bugzilla (%s)") % product.bugUrl, "bugzilla", False) - self.scpButton = self.rg.add(_("Send to remote server (scp)"), "scp", False) - - buttons = ButtonBar(self.screen, [TEXT_OK_BUTTON, TEXT_CANCEL_BUTTON]) - - toplevel.add(self.diskButton, 0, 0, (0, 0, 0, 1)) - toplevel.add(self.bugzillaButton, 0, 1, (0, 0, 0, 1)) - toplevel.add(self.scpButton, 0, 2, (0, 0, 0, 1)) - toplevel.add(buttons, 0, 3, growx=1) - - self.dests = [] - if self.anaconda.id.storage.devicetree.populated: - try: - self.dests = self.anaconda.id.storage.exceptionDisks() - except Exception as e: - log.error("Error when probing exception disks: %s" % e) - else: - log.info("Storage configuration unknown; not probing for " - "exception disks") - - # If there aren't any local disks, don't set it to be the default. - if len(self.dests) == 0: - self.diskButton.w.checkboxSetFlags(FLAG_DISABLED, FLAGS_SET) - self.diskButton.w.checkboxSetValue(" ") - self.bugzillaButton.w.checkboxSetFlags(FLAG_DISABLED, FLAGS_RESET) - self.bugzillaButton.w.checkboxSetValue("*") - - while True: - result = toplevel.run() - rc = buttons.buttonPressed(result) - - if rc == TEXT_OK_CHECK: - if mapping[self.rg.getSelection()]() == TEXT_CANCEL_CHECK: - continue - - self.rc = TEXT_OK_CHECK - self._method = self.rg.getSelection() - else: - self.rc = TEXT_CANCEL_CHECK - - break - - def saveToDisk(self): - return self._method == "disk" - - def saveToLocal(self): - return False - - def saveToRemote(self): - return self._method == "scp" - -class MainExceptionWindow: - def __init__ (self, shortTraceback, longTracebackFile=None, screen=None): - self.text = "%s\n\n" % shortTraceback - self.screen = screen - - self.buttons=[TEXT_OK_BUTTON] - - self.buttons.append(_("Save")) - - if not flags.livecdInstall: - self.buttons.append(_("Debug")) - - def run(self): - log.info ("in run, screen = %s" % self.screen) - self.rc = ButtonChoiceWindow(self.screen, _("Exception Occurred"), - self.text, self.buttons) - - def getrc(self): - if self.rc == string.lower(_("Debug")): - return EXN_DEBUG - elif self.rc == string.lower(_("Save")): - return EXN_SAVE - else: - return EXN_OK - - def pop(self): - self.screen.popWindow() - self.screen.refresh() - class LuksPassphraseWindow: def __init__(self, screen, passphrase = "", preexist = False): self.screen = screen @@ -441,6 +261,10 @@ class InstallInterface: def progressWindow(self, title, text, total, updpct = 0.05, pulse = False): return ProgressWindow(self.screen, title, text, total, updpct, pulse)
+ def exitWindow(self, title, text): + return self.messageWindow(title, text, type="custom", + custom_buttons=[_("Exit installer")]) + def messageWindow(self, title, text, type="ok", default = None, custom_icon=None, custom_buttons=[]): if type == "ok": @@ -573,12 +397,14 @@ class InstallInterface: custom_icon="error")
def mainExceptionWindow(self, shortText, longTextFile): + from meh.ui.text import MainExceptionWindow log.critical(shortText) - exnWin = MainExceptionWindow(shortText, longTextFile, self.screen) + exnWin = MainExceptionWindow(shortText, longTextFile, screen=self.screen) return exnWin
def saveExceptionWindow(self, longTextFile): - win = SaveExceptionWindow (self.anaconda, longTextFile, self.screen) + from meh.ui.text import SaveExceptionWindow + win = SaveExceptionWindow (self.anaconda, longTextFile, screen=self.screen) return win
def waitWindow(self, title, text):
On Tuesday, July 28 2009, Chris Lumens said:
The following series of patches changes anaconda over to using the new python-meh for exception handling. I have tested this, though something is bound to go wrong once we get all the packaging done and into a release. Before this can be pushed, the new python-meh package needs to make it in, though that's supposed to be in the works.
Reading through I didn't notice any real syntax-y problems and the overall dropping a lot of code is good.
One minor nit (that probably isn't worth the effort it might take to resolve) is that you're removing things in patches before you put their replacement in. Which then means that bisecting would break across the boundary.
Jeremy
anaconda-devel@lists.fedoraproject.org