[kupfer] plugins: Load a Fake Plugin for plugins that raise on import
- From: Ulrik Sverdrup <usverdrup src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [kupfer] plugins: Load a Fake Plugin for plugins that raise on import
- Date: Fri, 9 Oct 2009 00:01:42 +0000 (UTC)
commit dad64f2731eb9eab90a4413e3e5237c92df571de
Author: Ulrik Sverdrup <ulrik sverdrup gmail com>
Date: Thu Oct 8 21:45:58 2009 +0200
plugins: Load a Fake Plugin for plugins that raise on import
Plugins should raise ImportError on import, and Kupfer's plugin loader
will register it and record the error. ImportErrors are special-cased
and any other errors raised on plugin import (such as SyntaxError) are
printed with a traceback instead.
After we catch the ImportError we use a minor hack to still try to get
as much information as possible out of the plugin; we ask the import
loader for its code object and evaluate it; thus we can grab the
kupfer information variables in the plugins, if they are defined
before the exception is raised.
kupfer/plugins.py | 58 +++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 52 insertions(+), 6 deletions(-)
---
diff --git a/kupfer/plugins.py b/kupfer/plugins.py
index deac7e6..0bf3a7e 100644
--- a/kupfer/plugins.py
+++ b/kupfer/plugins.py
@@ -7,6 +7,13 @@ content_decorators_attribute = "__kupfer_contents__"
action_decorators_attribute = "__kupfer_actions__"
settings_attribute = "__kupfer_settings__"
+info_attributes = [
+ "__kupfer_name__",
+ "__version__",
+ "__description__",
+ "__author__",
+ ]
+
def get_plugin_ids():
"""Enumerate possible plugin ids;
return a sequence of possible plugin ids, not
@@ -33,6 +40,15 @@ def get_plugin_ids():
pretty.print_error(exc)
return plugin_ids
+class FakePlugin (object):
+ def __init__(self, plugin_id, attributes, error_message):
+ self.is_fake_plugin = True
+ self.error_message = error_message
+ self.__name__ = plugin_id
+ vars(self).update(attributes)
+ def __repr__(self):
+ return "<%s %s>" % (type(self).__name__, self.__name__)
+
def get_plugin_info():
"""Generator, yields dictionaries of plugin descriptions
@@ -48,7 +64,7 @@ def get_plugin_info():
plugin = import_plugin(plugin_name)
if not plugin:
continue
- plugin = plugin.__dict__
+ plugin = vars(plugin)
except ImportError, e:
pretty.print_error(__name__, "import plugin '%s':" % plugin_name, e)
continue
@@ -77,6 +93,27 @@ def get_plugin_desc():
imported_plugins = {}
+def import_fake_plugin(modpath):
+ """
+ Return an object that has the plugin info attributes we can rescue
+ from a plugin raising on import.
+ """
+ import pkgutil
+
+ loader = pkgutil.get_loader(modpath)
+ if not loader:
+ return None
+ env = {}
+ try:
+ eval(loader.get_code(), env)
+ except Exception, exc:
+ error = unicode(exc)
+ else:
+ error = None
+ pretty.print_error(__name__, "Fake plugin for good plugin", modpath)
+ attributes = dict((k, env.get(k)) for k in info_attributes)
+ return FakePlugin(modpath, attributes, error)
+
def import_plugin(name):
"""Try to import the plugin from the package,
and then from our plugin directories in $DATADIR
@@ -87,9 +124,18 @@ def import_plugin(name):
"""@pathcomps path components to the import"""
path = ".".join(pathcomps)
fromlist = pathcomps[-1:]
- plugin = __import__(path, fromlist=fromlist)
- pretty.print_debug(__name__, "Loading %s" % plugin.__name__)
- pretty.print_debug(__name__, " from %s" % plugin.__file__)
+ try:
+ plugin = __import__(path, fromlist=fromlist)
+ except ImportError, exc:
+ # Try to find a fake plugin if it exists
+ plugin = import_fake_plugin(path)
+ if not plugin:
+ raise
+ pretty.print_error(__name__, "Could not import plugin '%s': %s" %
+ (plugin.__name__, exc))
+ else:
+ pretty.print_debug(__name__, "Loading %s" % plugin.__name__)
+ pretty.print_debug(__name__, " from %s" % plugin.__file__)
return plugin
plugin = None
@@ -108,11 +154,11 @@ def import_plugin(name):
plugin = importit((name,))
finally:
sys.path = oldpath
- except ImportError:
+ except ImportError, e:
# Reraise to send this up
raise
except StandardError, e:
- # catch any other error for plugins in data directories
+ # catch any other error for plugins and write traceback
import traceback
traceback.print_exc()
pretty.print_error(__name__, "Could not import plugin '%s'" % name)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]