[kupfer/next] core: Reorganize plugin importing, introduce import_plugin_any



commit fb55c6bfbdfa7977928856ed06509e89e41da0bf
Author: Ulrik Sverdrup <ulrik sverdrup gmail com>
Date:   Sat Jan 23 13:40:35 2010 +0100

    core: Reorganize plugin importing, introduce import_plugin_any

 kupfer/core/plugins.py |  138 ++++++++++++++++++++++++++++++-----------------
 1 files changed, 88 insertions(+), 50 deletions(-)
---
diff --git a/kupfer/core/plugins.py b/kupfer/core/plugins.py
index 47db66d..5016b04 100644
--- a/kupfer/core/plugins.py
+++ b/kupfer/core/plugins.py
@@ -1,3 +1,4 @@
+import os
 import sys
 from kupfer import pretty, config
 from kupfer.core import settings
@@ -15,13 +16,14 @@ info_attributes = [
 		"__author__",
 	]
 
+class NotEnabledError (Exception):
+	"Plugin may not be imported since it is not enabled"
+
 def get_plugin_ids():
 	"""Enumerate possible plugin ids;
 	return a sequence of possible plugin ids, not
 	guaranteed to be plugins"""
 	import pkgutil
-	import os
-
 	from kupfer import plugin
 
 	def is_plugname(plug):
@@ -62,7 +64,7 @@ def get_plugin_info():
 	"""
 	for plugin_name in sorted(get_plugin_ids()):
 		try:
-			plugin = import_plugin(plugin_name)
+			plugin = import_plugin_any(plugin_name)
 			if not plugin:
 				continue
 			plugin = vars(plugin)
@@ -107,12 +109,14 @@ def get_plugin_desc():
 			))
 	return "\n".join(desc)
 
-imported_plugins = {}
+_imported_plugins = {}
 
-def import_fake_plugin(modpath):
+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
 	"""
 	import pkgutil
 
@@ -123,66 +127,97 @@ def import_fake_plugin(modpath):
 	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)
+		pretty.print_debug(__name__, "Loading", modpath, exc)
+	errmsg = error and unicode(error)
 	attributes = dict((k, env.get(k)) for k in info_attributes)
-	return FakePlugin(modpath, attributes, error)
+	return FakePlugin(modpath, attributes, errmsg)
 
-def import_plugin(name):
+def _import_hook_fake(pathcomps):
+	modpath = ".".join(pathcomps)
+	return _import_plugin_fake(modpath)
+
+def _import_hook_true(pathcomps):
+	"""@pathcomps path components to the import"""
+	path = ".".join(pathcomps)
+	fromlist = pathcomps[-1:]
+	try:
+		setctl = settings.GetSettingsController()
+		if not setctl.get_plugin_enabled(pathcomps[-1]):
+			raise NotEnabledError("%s is not enabled" % pathcomps[-1])
+		plugin = __import__(path, fromlist=fromlist)
+	except ImportError, exc:
+		# Try to find a fake plugin if it exists
+		plugin = _import_plugin_fake(path, error=exc)
+		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
+
+def _import_plugin_true(name):
 	"""Try to import the plugin from the package, 
 	and then from our plugin directories in $DATADIR
 	"""
-	if name in imported_plugins:
-		return imported_plugins[name]
-	def importit(pathcomps):
-		"""@pathcomps path components to the import"""
-		path = ".".join(pathcomps)
-		fromlist = pathcomps[-1:]
-		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
 	try:
-		try:
-			plugin = importit(("kupfer", "plugin", name))
-		except ImportError, e:
-			if name not in e.args[0]:
-				raise
-			oldpath = sys.path
-			try:
-				# Look in datadir kupfer/plugins for plugins
-				# (and in current directory)
-				extra_paths = list(config.get_data_dirs("plugins"))
-				sys.path = extra_paths + sys.path
-				plugin = importit((name,))
-			finally:
-				sys.path = oldpath
-	except ImportError, e:
+		plugin = _staged_import(name, _import_hook_true)
+	except ImportError:
 		# Reraise to send this up
 		raise
+	except NotEnabledError:
+		raise
 	except Exception, e:
 		# catch any other error for plugins and write traceback
 		import traceback
 		traceback.print_exc()
 		pretty.print_error(__name__, "Could not import plugin '%s'" % name)
+	return plugin
+
+def _staged_import(name, import_hook):
+	"Import first from kupfer.plugin, then from plugins data directories"
+	plugin = None
+	try:
+		plugin = import_hook(("kupfer", "plugin", name))
+	except ImportError, e:
+		if name not in e.args[0]:
+			raise
+
+	if not plugin:
+		oldpath = sys.path
+		try:
+			# Look in datadir kupfer/plugins for plugins
+			# (and in current directory)
+			extra_paths = list(config.get_data_dirs("plugins"))
+			sys.path = extra_paths + sys.path
+			plugin = import_hook((name,))
+		finally:
+			sys.path = oldpath
+	return plugin
+
+
+def import_plugin(name):
+	if name in _imported_plugins:
+		return _imported_plugins[name]
+	plugin = None
+	try:
+		plugin = _import_plugin_true(name)
+	except NotEnabledError:
+		plugin = _staged_import(name, _import_hook_fake)
 	finally:
 		# store nonexistant plugins as None here
-		imported_plugins[name] = plugin
+		_imported_plugins[name] = plugin
 	return plugin
 
+def import_plugin_any(name):
+	if name in _imported_plugins:
+		return _imported_plugins[name]
+	return _staged_import(name, _import_hook_fake)
+
+
+# Plugin Attributes
 def get_plugin_attributes(plugin_name, attrs, warn=False):
 	"""Generator of the attributes named @attrs
 	to be found in plugin @plugin_name
@@ -228,6 +263,12 @@ def load_plugin_sources(plugin_name, attr=sources_attribute, instantiate=True):
 		else:
 			pretty.print_info(__name__, "Source not found for %s" % plugin_name)
 
+
+# Plugin Initialization & Error
+def is_plugin_loaded(plugin_name):
+	return (plugin_name in _imported_plugins and
+			not get_plugin_attribute(plugin_name, "is_fake_plugin"))
+
 def initialize_plugin(plugin_name):
 	"""Initialize plugin.
 	Find settings attribute if defined, and initialize it
@@ -249,6 +290,3 @@ def get_plugin_error(plugin_name):
 	except ImportError, e:
 		return "'%s' is not a plugin" % plugin_name
 
-def is_plugin_loaded(plugin_name):
-	return (plugin_name in imported_plugins and
-			not get_plugin_attribute(plugin_name, "is_fake_plugin"))



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