[kupfer] Show full traceback for unexpected plugin load errors



commit 6ec27f18fb04e7639e5a687233ac59503bef6f22
Author: Ulrik Sverdrup <ulrik sverdrup gmail com>
Date:   Thu Feb 4 12:53:04 2010 +0100

    Show full traceback for unexpected plugin load errors
    
    In core we save the full exception information when a plugin fails to
    load.
    
    We then show this information in the plugin information in the
    preferences dialog. As usual, the common case of a missing module is
    detected and localized, but an unknown error is shown with full
    traceback.

 kupfer/core/plugins.py   |   19 +++++++++----------
 kupfer/ui/preferences.py |   25 +++++++++++++++++--------
 2 files changed, 26 insertions(+), 18 deletions(-)
---
diff --git a/kupfer/core/plugins.py b/kupfer/core/plugins.py
index ab1e69c..4aaee23 100644
--- a/kupfer/core/plugins.py
+++ b/kupfer/core/plugins.py
@@ -44,9 +44,9 @@ def get_plugin_ids():
 	return plugin_ids
 
 class FakePlugin (object):
-	def __init__(self, plugin_id, attributes, error_message):
+	def __init__(self, plugin_id, attributes, exc_info):
 		self.is_fake_plugin = True
-		self.error_message = error_message
+		self.exc_info = exc_info
 		self.__name__ = plugin_id
 		vars(self).update(attributes)
 	def __repr__(self):
@@ -173,7 +173,7 @@ def _import_plugin_fake(modpath, error=None):
 	Return an object that has the plugin info attributes we can rescue
 	from a plugin raising on import.
 
-	If applicable, write in @error as the exception responsible
+	@error: If applicable, a tuple of exception info
 	"""
 	import pkgutil
 
@@ -189,10 +189,9 @@ def _import_plugin_fake(modpath, error=None):
 		eval(code, env)
 	except Exception, exc:
 		pretty.print_debug(__name__, "Loading", modpath, exc)
-	errmsg = error and unicode(error)
 	attributes = dict((k, env.get(k)) for k in info_attributes)
 	attributes.update((k, env.get(k)) for k in ["__name__", "__file__"])
-	return FakePlugin(modpath, attributes, errmsg)
+	return FakePlugin(modpath, attributes, error)
 
 def _import_hook_fake(pathcomps):
 	modpath = ".".join(pathcomps)
@@ -209,7 +208,7 @@ def _import_hook_true(pathcomps):
 		plugin = __import__(path, fromlist=fromlist)
 	except ImportError, exc:
 		# Try to find a fake plugin if it exists
-		plugin = _import_plugin_fake(path, error=exc)
+		plugin = _import_plugin_fake(path, error=sys.exc_info())
 		if not plugin:
 			raise
 		pretty.print_error(__name__, "Could not import plugin '%s': %s" %
@@ -343,12 +342,12 @@ def initialize_plugin(plugin_name):
 def get_plugin_error(plugin_name):
 	"""
 	Return None if plugin is loaded without error, else
-	return a string describing the error.
+	return a tuple of exception information
 	"""
 	try:
 		plugin = import_plugin(plugin_name)
 		if getattr(plugin, "is_fake_plugin", None):
-			return plugin.error_message
-	except ImportError, e:
-		return "'%s' is not a plugin" % plugin_name
+			return plugin.exc_info
+	except ImportError:
+		return sys.exc_info()
 
diff --git a/kupfer/ui/preferences.py b/kupfer/ui/preferences.py
index 8b32e5d..2c44a61 100644
--- a/kupfer/ui/preferences.py
+++ b/kupfer/ui/preferences.py
@@ -339,21 +339,30 @@ class PreferencesWindowController (pretty.OutputMixin):
 			infobox.pack_start(label, False)
 		about.pack_start(infobox, False)
 
-		# Check for plugin load error
-		error = plugins.get_plugin_error(plugin_id)
-		if error:
+		# Check for plugin load exception
+		exc_info = plugins.get_plugin_error(plugin_id)
+		if exc_info is not None:
+			etype, error, tb = exc_info
 			# TRANS: Error message when Plugin needs a Python module to load
 			import_error_localized = _("Python module '%s' is needed") % u"\\1"
 			import_error_pat = u"No module named ([^\s]+)"
-			if re.match(import_error_pat, error):
-				error = re.sub(import_error_pat,
+			errmsg = unicode(error)
+			if re.match(import_error_pat, errmsg):
+				errstr = re.sub(import_error_pat,
 						import_error_localized,
-						error, count=1)
+						errmsg, count=1)
+			else:
+				import traceback
+				errstr = "".join(traceback.format_exception(*exc_info))
+
 			label = gtk.Label()
 			label.set_alignment(0, 0)
-			label.set_markup(u"<b>%s</b>\n%s" %
-					(_("Plugin could not be read due to an error:"), error))
+			label.set_markup(u"<b>%s</b>\n\n%s" % (
+				_("Plugin could not be read due to an error:"),
+				gobject.markup_escape_text(errstr),
+				))
 			label.set_selectable(True)
+			label.set_line_wrap(True)
 			about.pack_start(label, False)
 		elif not plugins.is_plugin_loaded(plugin_id):
 			label = gtk.Label()



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]