[master][PATCH] Check _current_action for not being None before using it
by Vratislav Podzimek
It may happen that _current_action is None even when self._actions is
not None and not empty.
---
pyanaconda/ui/gui/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyanaconda/ui/gui/__init__.py b/pyanaconda/ui/gui/__init__.py
index 1e432d4..7ace103 100644
--- a/pyanaconda/ui/gui/__init__.py
+++ b/pyanaconda/ui/gui/__init__.py
@@ -309,7 +309,7 @@ class GraphicalUserInterface(UserInterface):
from gi.repository import AnacondaWidgets
# if there are no actions (not populated yet), we can do nothing
- if len(self._actions) > 0:
+ if len(self._actions) > 0 and self._currentAction:
lightbox = AnacondaWidgets.lb_show_over(self._currentAction.window)
window.main_window.set_transient_for(lightbox)
--
1.7.11.7
11 years, 1 month
[master] Patch for the new libxklavier
by Vratislav Podzimek
This adapts our XklWrapper to the new behaviour of libxklavier. Though it seems
to work I'm not sure it will work correctly with some non-ascii strings. Maybe
they are gone now. I'll ask the libxklavier maintainer what's going on, but
let's start with this patch making rawhide Anaconda work again.
Vratislav Podzimek (1):
Adapt to the new libxklavier's behaviour
pyanaconda/keyboard.py | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
--
1.7.11.7
11 years, 1 month
[PATCH] Fix two places where we are locking up the main thread (#886680).
by Chris Lumens
(1) Letting _first_refresh be the first time we reference payload.groups and
payload.environments means we are potentially downloading lots of big data in
the main thread, which means the UI cannot update.
(2) Referencing anything in software.py's _initialize grabs the yum lock,
possibly for a long time. When we later check the source spoke's status, we
reference ready which checks baseRepo, which also attempts to grab the same
lock. This isn't a deadlock because it will eventually get released, but it
does make the UI unresponsive for a while.
---
pyanaconda/ui/gui/spokes/software.py | 24 ++++++++++++++++++------
pyanaconda/ui/gui/spokes/source.py | 7 +++----
2 files changed, 21 insertions(+), 10 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/software.py b/pyanaconda/ui/gui/spokes/software.py
index bc21af9..14b15c6 100644
--- a/pyanaconda/ui/gui/spokes/software.py
+++ b/pyanaconda/ui/gui/spokes/software.py
@@ -24,6 +24,7 @@ _ = lambda x: gettext.ldgettext("anaconda", x)
N_ = lambda x: x
from pyanaconda.flags import flags
+from pyanaconda.packaging import MetadataError
from pyanaconda.threads import threadMgr, AnacondaThread
from pyanaconda.ui import communication
@@ -184,8 +185,25 @@ class SoftwareSelectionSpoke(NormalSpoke):
# We don't want to do a full refresh, just join the metadata thread
threadMgr.wait("AnaPayloadMDThread")
else:
+ # Grabbing the list of groups could potentially take a long time
+ # at first (yum does a lot of magic property stuff, some of which
+ # involves side effects like network access. We need to reference
+ # them here, outside of the main thread, to not block the UI.
+ try:
+ self.payload.environments
+ self.payload.groups
+ except MetadataError:
+ communication.send_message(self.__class__.__name__,
+ _("No installation source available"))
+ return
+
+ # And then having done all that slow downloading, we need to do the first
+ # refresh of the UI here so there's an environment selected by default.
+ # This happens inside the main thread by necessity. We can't do anything
+ # that takes any real amount of time, or it'll block the UI from updating.
if not self._first_refresh():
return
+
self.payload.release()
communication.send_ready(self.__class__.__name__)
@@ -196,12 +214,6 @@ class SoftwareSelectionSpoke(NormalSpoke):
@gtk_thread_wait
def _first_refresh(self):
- # Grabbing the list of groups could potentially take a long time the
- # first time (yum does a lot of magic property stuff, some of which
- # involves side effects like network access) so go ahead and grab
- # them once now.
- from pyanaconda.packaging import MetadataError
-
try:
self.refresh()
return True
diff --git a/pyanaconda/ui/gui/spokes/source.py b/pyanaconda/ui/gui/spokes/source.py
index 4b3d90d..6381130 100644
--- a/pyanaconda/ui/gui/spokes/source.py
+++ b/pyanaconda/ui/gui/spokes/source.py
@@ -614,10 +614,9 @@ class SourceSpoke(NormalSpoke):
@property
def ready(self):
from pyanaconda.threads import threadMgr
- # By default, the source spoke is not ready. We have to wait until
- # storageInitialize is done to know whether or not there's local
- # devices potentially holding install media.
- return (self._ready and not threadMgr.get("AnaPayloadMDThread") and
+ return (self._ready and
+ not threadMgr.get("AnaPayloadMDThread") and
+ not threadMgr.get("AnaSoftwareWatcher") and
not threadMgr.get("AnaCheckSoftwareThread"))
@property
--
1.8.1.2
11 years, 1 month
[PATCH] Log when we acquire and release the _yum_lock (dlehman, clumens).
by Chris Lumens
We've got a temporary locking issue somewhere that causes the UI to become
unresponsive for a bit (see #886680, perhaps other bugs). Examining the code
indicates this isn't necessarily due to running things in the main loop
that shouldn't be. There's something waiting for the _yum_lock. This patch
adds logging to help debug.
---
pyanaconda/packaging/yumpayload.py | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/pyanaconda/packaging/yumpayload.py b/pyanaconda/packaging/yumpayload.py
index 9549420..fe132f7 100644
--- a/pyanaconda/packaging/yumpayload.py
+++ b/pyanaconda/packaging/yumpayload.py
@@ -94,9 +94,25 @@ from pykickstart.constants import KS_MISSING_IGNORE
default_repos = [productName.lower(), "rawhide"]
-from threading import RLock
-_yum_lock = RLock()
+import inspect
+import threading
+_private_yum_lock = threading.RLock()
+class YumLock(object):
+ def __enter__(self):
+ frame = inspect.stack()[2]
+ threadName = threading.currentThread().name
+
+ log.info("about to acquire _yum_lock for %s at %s:%s (%s)" % (threadName, frame[1], frame[2], frame[3]))
+ _private_yum_lock.acquire()
+ log.info("have _yum_lock for %s" % threadName)
+ return _private_yum_lock
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ _private_yum_lock.release()
+ log.info("gave up _yum_lock for %s" % threading.currentThread().name)
+
+_yum_lock = YumLock()
_yum_cache_dir = "/tmp/yum.cache"
class YumPayload(PackagePayload):
--
1.8.1.2
11 years, 1 month
[master] [PATCH] Redraw screen in case of valid input and nothing new scheduled
by Vratislav Podzimek
If the screen successfully processes the input and doesn't schedule
another screen, it should be redrawn, so that the new state is shown.
Signed-off-by: Vratislav Podzimek <vpodzime(a)redhat.com>
---
pyanaconda/ui/tui/simpleline/base.py | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/pyanaconda/ui/tui/simpleline/base.py b/pyanaconda/ui/tui/simpleline/base.py
index 5e2e8be..131a54a 100644
--- a/pyanaconda/ui/tui/simpleline/base.py
+++ b/pyanaconda/ui/tui/simpleline/base.py
@@ -269,7 +269,7 @@ class App(object):
except Exception as ex:
send_exception(self.queue, ex)
return False
-
+
else:
# this can happen only in case there was invalid input and prompt
# should be shown again
@@ -341,6 +341,10 @@ class App(object):
# increment the error counter
if not self.input(self._screens[-1][1], c):
error_counter += 1
+ else:
+ # input was successfully processed, but no other screen was
+ # scheduled, just redraw the screen to display current state
+ self.redraw()
# redraw the screen after 5 bad inputs
if error_counter >= 5:
--
1.7.11.7
11 years, 1 month
[master] Two exception handling related patches
by Vratislav Podzimek
PATCH 1/2 uses the proposed patch for python-meh to replace magic tuples
with much clearer named tuples and may be squashed with the patch ensuring
exception handling in text mode runs in the main thread.
PATCH 2/2 fixes bug nobody has probably hit yet.
Vratislav Podzimek (2):
Use namedtuple instead of our magic tuples
We use python-meh's interfaces instead of Anaconda's
pyanaconda/exception.py | 35 +++++++++++++++++------------------
1 file changed, 17 insertions(+), 18 deletions(-)
--
1.7.11.7
11 years, 1 month
[python-meh][PATCH] Use named tuples instead of our magic tuples
by Vratislav Podzimek
Using ExceptionInfo and DumpInfo named tuples makes code clearer and
simplifies documentation.
Signed-off-by: Vratislav Podzimek <vpodzime(a)redhat.com>
---
meh/__init__.py | 8 ++++++++
meh/dump.py | 24 ++++++++++++------------
meh/handler.py | 54 +++++++++++++++++++++++++++---------------------------
po/python-meh.pot | 2 +-
tests/baseclass.py | 3 ++-
5 files changed, 50 insertions(+), 41 deletions(-)
diff --git a/meh/__init__.py b/meh/__init__.py
index 329969f..d09a131 100644
--- a/meh/__init__.py
+++ b/meh/__init__.py
@@ -20,6 +20,8 @@
# Author(s): Chris Lumens <clumens(a)redhat.com>
#
+from collections import namedtuple
+
# These constants represent the return values of buttons on the initial
# exception handling dialog - the dialog that first pops up when an
# exception is hit.
@@ -127,3 +129,9 @@ class Config(object):
else:
msg = "Callback with name '%s' already registered" % item_name
raise ConfigError(msg)
+
+# type, value and stack are items provided by Python for the exception handler
+ExceptionInfo = namedtuple("ExceptionInfo", ["type", "value", "stack"])
+
+# ExceptionInfo instance plus the object that should be dumped
+DumpInfo = namedtuple("DumpInfo", ["exc_info", "object"])
diff --git a/meh/dump.py b/meh/dump.py
index c868aa4..4639327 100644
--- a/meh/dump.py
+++ b/meh/dump.py
@@ -35,23 +35,23 @@ class ExceptionDump(object):
for manipulating a traceback. In general, clients should not have to
use this class. It is mainly for internal use.
"""
- def __init__(self, (ty, value, stack), configObj):
+ def __init__(self, exc_info, config_obj):
"""Create a new ExceptionDump instance. Instance attributes:
- (type, value, stack) -- These are the values provided by python
- when an exception is generated, and are
- what ExceptionDump wraps to make more
- useful.
- conf -- An instance of the Config object.
+ @param exc_info: info about the exception provided by Python
+ @type exc_info: an instance of the meh.ExceptionInfo class
+ @param config_obj: configuration for python-meh
+ @type config_obj: an instance of the meh.Config class
"""
- if inspect.istraceback(stack):
- stack = inspect.getinnerframes(stack)
+ if inspect.istraceback(exc_info.stack):
+ self.stack = inspect.getinnerframes(exc_info.stack)
+ else:
+ self.stack = exc_info.stack
- self.conf = configObj
- self.stack = stack
- self.type = ty
- self.value = value
+ self.conf = config_obj
+ self.type = exc_info.type
+ self.value = exc_info.value
self._dumpHash = {}
diff --git a/meh/handler.py b/meh/handler.py
index 6338cf2..6427656 100644
--- a/meh/handler.py
+++ b/meh/handler.py
@@ -68,7 +68,7 @@ class ExceptionHandler(object):
exn = property(lambda s: s._exn,
lambda s, v: s._setExn(v))
- def handleException(self, (ty, value, tb), obj):
+ def handleException(self, dump_info):
"""This is the main exception handling entry point. When Python
gets an exception it doesn't know how to handle, this method will
be called. It then saves the traceback and displays the main
@@ -79,6 +79,9 @@ class ExceptionHandler(object):
All arguments are passed in from the handler created by calling
self.install(). This method should not usually be overridden by
a subclass.
+
+ @type dump_info: an instance of the meh.DumpInfo class
+
"""
responseHash = {MAIN_RESPONSE_QUIT: self.runQuit,
@@ -86,34 +89,34 @@ class ExceptionHandler(object):
MAIN_RESPONSE_SAVE: self.runSave}
# Quit if we got an exception when running pdb.
- if isinstance(value, bdb.BdbQuit):
+ if isinstance(dump_info.exc_info.value, bdb.BdbQuit):
sys.exit(self.exitcode)
# Restore original exception handler.
sys.excepthook = sys.__excepthook__
- self.preWriteHook((ty, value, tb), obj)
+ self.preWriteHook(dump_info)
# Save the exception to the filesystem first.
- self.exn = self.exnClass((ty, value, tb), self.conf)
+ self.exn = self.exnClass(dump_info.exc_info, self.conf)
(fobj, self.exnFile) = self.openFile()
- self.exnText = self.exn.traceback_and_object_dump(obj)
+ self.exnText = self.exn.traceback_and_object_dump(dump_info.object)
fobj.write(self.exnText)
fobj.close()
- self.postWriteHook((ty, value, tb), obj)
+ self.postWriteHook(dump_info)
# Run initial UI screen, asking whether to save/debug/quit.
while True:
win = self.intf.mainExceptionWindow(str(self.exn), self.exnText)
if not win:
- self.runQuit((ty, value, tb))
+ self.runQuit(dump_info.exc_info)
rc = win.run()
win.destroy()
try:
- responseHash[rc]((ty, value, tb))
+ responseHash[rc](dump_info.exc_info)
except KeyError:
# This happens if (for example) the user hits Escape instead
# of pressing a button.
@@ -121,33 +124,23 @@ class ExceptionHandler(object):
win.destroy()
- def preWriteHook(self, (ty, value, tb), obj):
+ def preWriteHook(self, dump_info):
"""Subclasses may supply a function with this name that will be
called immediately before the traceback is written to disk in
order to have any sort of special pre-write processing that needs
to be done.
- (ty, value, tb) -- The Python objects created when a traceback
- occurs. These are passed in directly from
- handleException.
- obj -- A Python object that may be dumped to a file when the
- exception is saved. This should be something like the top
- level object in a program.
+ @type dump_info: an instance of the meh.DumpInfo class
"""
pass
- def postWriteHook(self, (ty, value, tb), obj):
+ def postWriteHook(self, dump_info):
"""Subclasses may supply a function with this name that will be
called immediately after the traceback is written to disk, but
immediately before the UI is run. This is to provide a place for
any special handling to happen once there is a file on disk.
- (ty, value, tb) -- The Python objects created when a traceback
- occurs. These are passed in directly from
- handleException.
- obj -- A Python object that may be dumped to a file when the
- exception is saved. This should be something like the top
- level object in a program.
+ @type dump_info: an instance of the meh.DumpInfo class
"""
pass
@@ -160,7 +153,8 @@ class ExceptionHandler(object):
exception is saved. This should be something like the top
level object in a program.
"""
- sys.excepthook = lambda ty, value, tb: self.handleException((ty, value, tb), obj)
+ sys.excepthook = lambda ty, value, tb: \
+ self.handleException(DumpInfo(ExceptionInfo(ty, value, tb), obj))
def openFile(self):
"""Create a randomly named output file to write the exception dump to.
@@ -176,29 +170,35 @@ class ExceptionHandler(object):
### Methods called by the primary exception handling dialog.
- def runQuit(self, (ty, value, tb)):
+ def runQuit(self, exc_info):
"""This method is called when the "Exit" button is clicked. It may
be overridden by a subclass, but the basic behavior of eventually
quitting should be preserved.
+
+ @type exc_info: an instance of the meh.ExceptionInfo class
"""
sys.exit(self.exitcode)
- def runDebug(self, (ty, value, tb)):
+ def runDebug(self, exc_info):
"""This method is called when the "Debug" button is clicked. It may
be overridden by a subclass if specialized behavior is required to
enter debug mode.
+
+ @type exc_info: an instance of the meh.ExceptionInfo class
"""
print
print "Use 'continue' command to quit the debugger and get back to "\
"the main menu"
import pdb
- pdb.post_mortem(tb)
+ pdb.post_mortem(exc_info.stack)
#no need to quit here, let's just get back to the main dialog
- def runSave(self, (ty, value, tb)):
+ def runSave(self, exc_info):
"""This method is called when the "Save" button is clicked. It may
be overridden by a subclass, but that's going to be a lot of work.
+
+ @type exc_info: an instance of the meh.ExceptionInfo class
"""
params = dict()
diff --git a/po/python-meh.pot b/po/python-meh.pot
index 44395da..5d4f33f 100644
--- a/po/python-meh.pot
+++ b/po/python-meh.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2013-01-21 12:43+0100\n"
+"POT-Creation-Date: 2013-03-05 12:14+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL(a)li.org>\n"
diff --git a/tests/baseclass.py b/tests/baseclass.py
index a0173b7..befa9b4 100644
--- a/tests/baseclass.py
+++ b/tests/baseclass.py
@@ -5,6 +5,7 @@ import sys
import tempfile
import unittest
+from meh import ExceptionInfo
from meh.handler import *
from meh.dump import *
@@ -13,7 +14,7 @@ class BaseTestCase(unittest.TestCase):
from inspect import stack as _stack
stack = _stack()[1:]
- dump = ExceptionDump((None, None, stack), conf)
+ dump = ExceptionDump(ExceptionInfo(None, None, stack), conf)
return dump.dump(obj)
def openFile(self):
--
1.7.11.7
11 years, 1 month
[PATCH] Could not load UI file advanced_user.glade
by Mark Hamzy
Fixes IOError: Could not load UI file 'advanced_user.glade' for object
---
pyanaconda/ui/gui/spokes/user.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyanaconda/ui/gui/spokes/user.py b/pyanaconda/ui/gui/spokes/user.py
index 93b4d08..af39856 100644
--- a/pyanaconda/ui/gui/spokes/user.py
+++ b/pyanaconda/ui/gui/spokes/user.py
@@ -56,7 +56,7 @@ def strip_accents(s):
class AdvancedUserDialog(GUIObject):
builderObjects = ["advancedUserDialog", "uid", "gid"]
mainWidgetName = "advancedUserDialog"
- uiFile = "advanced_user.glade"
+ uiFile = "spokes/advanced_user.glade"
def __init__(self, user, groupDict, data):
GUIObject.__init__(self, data)
--
1.8.1.2
11 years, 1 month
[PATCH] Ignore MTDs, as we do not have the tools to write to them (#916771).
by Chris Lumens
---
blivet/devicetree.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/blivet/devicetree.py b/blivet/devicetree.py
index 88ba130..c154343 100644
--- a/blivet/devicetree.py
+++ b/blivet/devicetree.py
@@ -501,6 +501,10 @@ class DeviceTree(object):
if name.startswith("ram"):
return True
+ # Memory Technology Devices require special tools to manipulate.
+ if name.startswith("mtd"):
+ return True
+
if name.startswith("loop"):
# ignore loop devices unless they're backed by a file
return (not devicelibs.loop.get_backing_file(name))
--
1.8.1.2
11 years, 2 months